<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Aaron Turon</title>
 <link href="http://aturon.github.io/blog/atom.xml" rel="self"/>
 <link href="http://aturon.github.io/blog/"/>
 <updated>2018-01-16T16:56:58-08:00</updated>
 <id>http://aturon.github.io</id>
 <author>
   <name>Aaron Turon</name>
   <email>aturon@mozilla.com</email>
 </author>

 
 <entry>
   <title>Retooling the Rust Libs Team team for 2018</title>
   <link href="http://aturon.github.io/blog/2018/01/16/libs-mission/"/>
   <updated>2018-01-16T00:00:00-08:00</updated>
   <id>http://aturon.github.io/2018/01/16/libs-mission</id>
   <content type="html">&lt;p&gt;The Libs Team met today to discuss a weighty topic: &lt;strong&gt;what is its mission as a
team, and are we set up to achieve it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As team lead, I took the liberty of proposing a mission statement:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To improve the quality of the crate ecosystem, as a product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Working backwards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;as a product&amp;rdquo; means that we need to focus on the &lt;em&gt;end-to-end experience&lt;/em&gt;
people have with the ecosystem. It&amp;rsquo;s not enough to have great libraries if no
one can find them. It can be a problem to have &lt;em&gt;too many&lt;/em&gt; libraries. Docs
count for a lot!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;the crate ecosystem&amp;rdquo; means that the Libs Team needs to look far beyond &lt;code&gt;std&lt;/code&gt;
and help look after the library ecosystem as a whole. The &lt;a href=&quot;https://blog.rust-lang.org/2017/05/05/libz-blitz.html&quot;&gt;Libz Blitz&lt;/a&gt; was one
of our first major attempts on this front.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;improve the quality&amp;rdquo; means that we don&amp;rsquo;t &lt;em&gt;own&lt;/em&gt; or &lt;em&gt;oversee&lt;/em&gt; the ecosystem,
but that we work together with library authors to improve the experience. What
quality means, and what aspects to prioritize, is of course also important to
nail down.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That&amp;rsquo;s a lofty goal! Let&amp;rsquo;s take a look at how we&amp;rsquo;ve approached it in the past,
and then talk about the future.&lt;/p&gt;

&lt;p&gt;Please comment on the &lt;a href=&quot;https://internals.rust-lang.org/t/the-libs-team-mission/6584&quot;&gt;internals post&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;the-libs-team-circa-2017&quot;&gt;The Libs Team circa 2017&lt;/h2&gt;

&lt;p&gt;Last year, the Libs Team split its focus onto two main topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overseeing &lt;code&gt;std&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://blog.rust-lang.org/2017/05/05/libz-blitz.html&quot;&gt;Libz Blitz&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;code&gt;std&lt;/code&gt;, the work involved shepherding and deciding on RFCs and jointly
reviewing PRs that impact the stable API surface. Despite the fact that &lt;code&gt;std&lt;/code&gt; is
not substantially growing, the workload here is sizable!&lt;/p&gt;

&lt;p&gt;For the Blitz, the work involved leading crate evaluations, doing API walks in
synchronous meetings, and working with crate authors to help push through
changes. As by-products, the team also worked on the &lt;a href=&quot;https://github.com/rust-lang-nursery/api-guidelines&quot;&gt;API guidelines&lt;/a&gt; and, to a
lesser extent, the &lt;a href=&quot;https://github.com/rust-lang-nursery/rust-cookbook&quot;&gt;Cookbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These efforts definitely made a positive impact on our goals, but collectively
the team feels that there&amp;rsquo;s more we could be doing, and that a rebalancing of
priorities is in order&amp;ndash;partly drawing on lessons from our 2017 work.&lt;/p&gt;

&lt;h2 id=&quot;retooling-the-team-in-2018&quot;&gt;Retooling the team in 2018&lt;/h2&gt;

&lt;h3 id=&quot;growing&quot;&gt;Growing&lt;/h3&gt;

&lt;p&gt;One clear lesson from the &lt;a href=&quot;https://blog.rust-lang.org/2017/05/05/libz-blitz.html&quot;&gt;Libz Blitz&lt;/a&gt; and the &lt;a href=&quot;https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html&quot;&gt;impl Period&lt;/a&gt; is that there are a
&lt;em&gt;lot&lt;/em&gt; of people out there who are excited to help improve Rust&amp;rsquo;s ecosystem, but
we lack the infrastructure and leadership bandwidth to direct this energy effectively.&lt;/p&gt;

&lt;p&gt;So the Libs Team needs to grow its leadership, &lt;em&gt;and&lt;/em&gt; grow to accommodate people
eager to pitch in. Today we announced &lt;a href=&quot;https://internals.rust-lang.org/t/welcome-kodraus-and-withoutboats-as-full-libs-team-members/6582/&quot;&gt;two additions to the team&lt;/a&gt;, which is a
good step.&lt;/p&gt;

&lt;p&gt;However, a limiting factor is the current &amp;ldquo;monolithic&amp;rdquo; structure to the team,
which means that &lt;em&gt;every&lt;/em&gt; member is expected to participate in all activities,
including signing off on &lt;code&gt;std&lt;/code&gt; changes. To remove this bottleneck, we are
considering a &amp;ldquo;working group&amp;rdquo; model, in which team members cluster into smaller
working groups that tackle particular topics, where each member participates
only in the groups they have time/interest for. Examples groups might be: std,
SIMD, networking, API guidelines, cookbook. To some degree these groups exist
informally now, but we want to be more systematic about them, explicitly
delegating decision-making power and designating a lead for each group.&lt;/p&gt;

&lt;p&gt;The working group model should allow us to drastically increase the number of
people involved in the team, while at the same time making us &lt;em&gt;more&lt;/em&gt; agile by
moving day-to-day decision-making to smaller, more focused groups.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re working with the Core Team to flesh out these ideas, in part because
several other subteams are pursuing similar thoughts; expect an RFC on this
topic soon!&lt;/p&gt;

&lt;h3 id=&quot;areas-of-focus&quot;&gt;Areas of focus&lt;/h3&gt;

&lt;p&gt;With the above changes, the Libs Team should be able to devote much more of its
focus to the broader crates ecosystem, and not just &lt;code&gt;std&lt;/code&gt;. But where should that
focus go?&lt;/p&gt;

&lt;p&gt;What follows are some &lt;em&gt;preliminary&lt;/em&gt; thoughts, with the main goal of stirring up
discussion.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s go back to the question of &amp;ldquo;product quality&amp;rdquo; for the ecosystem. I&amp;rsquo;d break
that down as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crate availability. &lt;em&gt;Does there exist a crate for your needs?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Crate discoverability. &lt;em&gt;Can you find that crate?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Crate quality. &lt;em&gt;Is the crate good? How can you tell?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Crate interoperability. &lt;em&gt;Does the crate fit well into the rest of the ecosystem?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last year, the Libs Team&amp;rsquo;s focus was clearly crate quality. Now we want to
retool to hit on &lt;em&gt;all&lt;/em&gt; of these topics.&lt;/p&gt;

&lt;h4 id=&quot;availability&quot;&gt;Availability&lt;/h4&gt;

&lt;p&gt;Where are the gaps in the ecosystem? That&amp;rsquo;s not just missing crates, but crates
that are missing important features in their domain. In the past, the Libs Team
has sometimes tried to look at availability issues by examining the &lt;em&gt;entire&lt;/em&gt;
ecosystem and comparing to ecosystems for other languages&amp;ndash;an approach that&amp;rsquo;s
never panned out.&lt;/p&gt;

&lt;p&gt;I think instead we should spin up working groups devoted to particular
topics/goals. For example, we could have a SIMD working group with the mandate
to produce a stable SIMD API and the power to make decisions on related
RFCs. But working groups could also be more broad, e.g. by bringing together
people interested in &amp;ldquo;networking&amp;rdquo; in general. The theory is that these domain
experts, by talking more regularly, can come to better understand the gaps and
turn them into contribution opportunities. They can also, of course, work to
improve the quality of the crates in their domain.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important to note, though, that working groups should be spun up only when
we have &lt;em&gt;committed leaderhip&lt;/em&gt; for keeping up momentum and organization of the
group. That comes back to team growth.&lt;/p&gt;

&lt;h4 id=&quot;discoverability&quot;&gt;Discoverability&lt;/h4&gt;

&lt;p&gt;In the &amp;ldquo;distant&amp;rdquo; past (circa 2016), we floated ideas like the &lt;a href=&quot;http://aturon.github.io/blog/2016/07/27/rust-platform/&quot;&gt;Rust Platform&lt;/a&gt;,
that involved &amp;ldquo;blessing&amp;rdquo; crates and tools that would then, in some sense, be
&amp;ldquo;shipped&amp;rdquo; as part of the Rust distribution. Part of the goal was to improve
discoverability by officially curating these crates. But in discussion with the
broader community, it became clear that this approach just has too many
downsides; it takes the oxygen out of the room for crate iteration and
competition, amongst other things.&lt;/p&gt;

&lt;p&gt;Instead, in 2017, the crates.io team put a lot of work into improving
discoverability within crates.io. The Libs Team also intended to turn the
&lt;a href=&quot;https://github.com/rust-lang-nursery/rust-cookbook&quot;&gt;Cookbook&lt;/a&gt; into a central point of discoverability, but that work hasn&amp;rsquo;t fully
panned out.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think the work here is finished. As I said in my &lt;a href=&quot;http://aturon.github.io/blog/2018/01/09/rust-2018/&quot;&gt;#Rust 2018 post&lt;/a&gt;, I
think this year we should focus on shipping a new iteration of Rust as a
product, and that should include a more polished discoverability story. As such,
I think we should have a working group dedicated purely to improving the process
of finding and evaluating crates. (There are lots of specific ideas about
further improvements, but those are out of scope for this post.)&lt;/p&gt;

&lt;h4 id=&quot;quality&quot;&gt;Quality&lt;/h4&gt;

&lt;p&gt;The Libs Team put a lot of its focus in 2017 on crate quality. As KodrAus put it,
this happened both strategically and tactically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Strategically: by creating resources like the &lt;a href=&quot;https://github.com/rust-lang-nursery/api-guidelines&quot;&gt;API guidelines&lt;/a&gt;, we started to
give library authors much more guidance how to create a high quality crate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tactically: through the &lt;a href=&quot;https://blog.rust-lang.org/2017/05/05/libz-blitz.html&quot;&gt;Libz Blitz&lt;/a&gt;, we &lt;em&gt;directly&lt;/em&gt; impacted the quality of
specific crates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these efforts were shaped by the &lt;a href=&quot;https://blog.rust-lang.org/2017/05/05/libz-blitz.html&quot;&gt;Libz Blitz&lt;/a&gt;, which purposefully
targeted nearly-stable crates in an attempt to help clear up remaining design
questions and polish toward a 1.0.&lt;/p&gt;

&lt;p&gt;These kinds of quality improvements are one of the highest-leverage activities
the Libs Team can take on, so we want to expand our efforts here. Some ideas and
open questions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Supplementing the &lt;a href=&quot;https://github.com/rust-lang-nursery/api-guidelines&quot;&gt;API guidelines&lt;/a&gt; with more &amp;ldquo;long form&amp;rdquo; material, e.g. by
writing detailed &amp;ldquo;design evaluation&amp;rdquo; documents that explain all the design
choices made in a particular crate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Surfacing pockets of the ecosystem that lack uniformity, such as the current
situation around &lt;code&gt;-sys&lt;/code&gt; crates, and working to produce a set of consensus conventions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improving maintenance of vital crates (e.g. libc, rand, cc) by bringing on
more contributors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Doing deeper dives into particular domains that need more design work; dhardy
took on such work with the &lt;code&gt;rand&lt;/code&gt; crate, and there are several other areas
that need more than a Blitz-style treatment to get to 1.0-level libraries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;rsquo;m sure there are other avenues to explore, and I&amp;rsquo;d love to hear your ideas!
It&amp;rsquo;ll also take some work to figure out how to map these to working groups we
can plausibly staff.&lt;/p&gt;

&lt;h4 id=&quot;interoperability&quot;&gt;Interoperability&lt;/h4&gt;

&lt;p&gt;One important aspect of looking at the ecosystem &lt;em&gt;as a whole&lt;/em&gt; is making sure
that crates work well together. For example, there&amp;rsquo;s currently an &lt;a href=&quot;https://github.com/rust-lang-nursery/error-chain/issues/240&quot;&gt;issue with
error-chain&lt;/a&gt; that is preventing smooth interop with &lt;a href=&quot;https://github.com/withoutboats/failure&quot;&gt;failure&lt;/a&gt;. The Libs Team
should be working to surface and help solve this kind of issue. Probably this is
best done by working toward another useful goal: building and documenting
mid-sized sample applications that plug together various Rust libraries.&lt;/p&gt;

&lt;h3 id=&quot;cross-cutting-concerns&quot;&gt;Cross-cutting concerns&lt;/h3&gt;

&lt;p&gt;Finally, a general point: to fully achieve its mission, the Libs Team needs to
have much more contact with the ecosystem in general; the team should understand
what libraries are becoming important in which areas, and spend time checking
them out and helping contribute. There are a lot of ways we could do that, but
most fundamentally this means bringing more folks working in particular
sub-ecosystems into the Libs Team working groups. Thoughts on how we might
structure such an effort are welcome, particularly from crate authors!&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;This post was essentially a brain-dump of my current thinking about how to take
the Libs Team to the next level. I&amp;rsquo;m eager to hear from you about the problems
&lt;em&gt;you&lt;/em&gt; see with the ecosystem, the ways you can envision the Libs Team helping,
and best of all, the ways you&amp;rsquo;d like to be involved.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rust in 2018: a people perspective</title>
   <link href="http://aturon.github.io/blog/2018/01/09/rust-2018/"/>
   <updated>2018-01-09T00:00:00-08:00</updated>
   <id>http://aturon.github.io/2018/01/09/rust-2018</id>
   <content type="html">&lt;p&gt;The &lt;a href=&quot;https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html&quot;&gt;call for #Rust2018 blog posts&lt;/a&gt; has generated a fantastic set of responses
so far, and there&amp;rsquo;s already an emerging consensus around much of the technical
focus for the year. Since I largely agree with what others have said on that
front, I want to focus my post on the &lt;em&gt;people&lt;/em&gt; side of things: what kind of
impact do we want to make on people, both contributors and customers, in 2018?&lt;/p&gt;

&lt;h2 id=&quot;tell-our-story-with-a-new-product&quot;&gt;Tell our story with a new &lt;em&gt;product&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Rust, like major web browsers, ships a new version every six weeks. There are a
ton of advantages to this rapid release process, but two major people-related
downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contributor downsides&lt;/strong&gt;. Part of the appeal of rapid-release is that
&amp;ldquo;there&amp;rsquo;s always another train on the way&amp;rdquo;; there&amp;rsquo;s no need to sprint to land
something in a given release, because another one will follow soon. But that
also makes it hard to &amp;ldquo;rally the troops&amp;rdquo;, bringing together the whole
community to drive a cohesive set of goals all the way to completion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customer downsides&lt;/strong&gt;. There&amp;rsquo;s a kind of &amp;ldquo;&lt;a href=&quot;https://en.wikipedia.org/wiki/Boiling_frog&quot;&gt;frog boil&lt;/a&gt;&amp;rdquo; effect from rapid
releases; Rust is always improving, a little bit at a time, so it can be hard
to fully grasp the large shifts that accumulate, especially if you&amp;rsquo;re not
following development closely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In 2017, we merged an RFC introducing &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2052&quot;&gt;epochs&lt;/a&gt;. While the discussion focused on
the technical mechanics, to me &lt;strong&gt;the thrust of the idea is to supplement our
release cycle with periodic &amp;ldquo;product&amp;rdquo; releases&lt;/strong&gt;. These are sometimes called
&amp;ldquo;marketing releases&amp;rdquo;, but I think marketing is just one (important!) part of the
story:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When thinking about Rust as a product, we shift our focus away from the
details of particular features, and instead think about the &lt;em&gt;end-to-end
experience&lt;/em&gt; of Rust. How do people hear about Rust, and what draws them in?
What are their first impressions of Rust? What are the major wins and pain
points at every point from novice to expert? This product focus helps us
prioritize our efforts on what will make the biggest impact on people using,
or thinking about using, Rust.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part of the end-to-end experience is &lt;em&gt;coherence&lt;/em&gt;: making sure that the set of
features available on stable work well together, without major gaps; that
these features are well documented; that the features are fully supported by
tools like IDEs; that the compiler provides top-notch error messages for the
full set of features; that there is likewise a coherent set of libraries
available in the ecosystem that works well with the set of currently-stable
features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aiming for a major product release gives us an opportunity, as a community, to
come together and do something &lt;em&gt;big&lt;/em&gt; that goes well beyond the usual six week
cycle. We&amp;rsquo;ve seen this effect leading up to the Rust 1.0 release, and also
with the more recent &lt;a href=&quot;https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html&quot;&gt;impl period&lt;/a&gt;. A product release gives us focus and drive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, there&amp;rsquo;s the marketing aspect, which comes in several
layers. Releasing &amp;ldquo;Rust 2018&amp;rdquo; gives us a chance to say to the world that &amp;ldquo;Rust
has taken a major step since 1.0; it&amp;rsquo;s time to take another look&amp;rdquo;. That, of
course, ties directly back to the end-to-end experience; we&amp;rsquo;ll want to have a
polished web site, installation process, etc. For existing Rust users who are
not deeply involved in Rust&amp;rsquo;s development, the product release gives a way to
understand Rust&amp;rsquo;s evolution as an overarching narrative. We can explain how
the features stabilized since the previous epoch all fit together to establish
new idioms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe that 2018 should be an &amp;ldquo;epoch year&amp;rdquo;, in which we focus on shipping a
quality product, for all of the above reasons. That&amp;rsquo;s going to require a lot of
discipline, and a steady stream of stabilizations, but I think we&amp;rsquo;re up to the
challenge!&lt;/p&gt;

&lt;h2 id=&quot;empower-new-technical-leaders&quot;&gt;Empower new technical leaders&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m really proud of the work we did in 2017 to grow Rust&amp;rsquo;s formal teams,
including creating several new subteams and expanding all of the existing
ones. But we&amp;rsquo;re still suffering from a deficit of technical leadership. That&amp;rsquo;s
in part because technical leadership is a hard job with mostly intangible
effects; it&amp;rsquo;s largely about enabling &lt;em&gt;other&lt;/em&gt; people to do the on-the-ground
technical work, by working to reach consensus on constraints and high-level
design. It requires enormous empathy, being able to understand the goals of a
wide variety of people and thread the needle between them. And it often
&lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; involve landing reams of code with your avatar attached to them.&lt;/p&gt;

&lt;p&gt;One of my personal lessons from 2017 is that we need to Think Big when it comes
to Rust&amp;rsquo;s teams. Rust is a staggeringly large project with a huge and talented
community, and we need its leadership structure to fully reflect that if we are
to reach our full potential.&lt;/p&gt;

&lt;p&gt;Concretely, this might look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Continuing to grow and subdivide the teams, so that we have more people in
total involved in leadership and decision-making, but each individual has a
narrower focus relative to today. This echos &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2018/01/05/lessons-from-the-impl-period/#worked-mostly-well-smaller-working-groups&quot;&gt;Niko&amp;rsquo;s points about impl period
working groups&lt;/a&gt;, which was one such attempt. Splitting up the &amp;ldquo;tools&amp;rdquo; team
into &amp;ldquo;dev tools&amp;rdquo;, &amp;ldquo;cargo&amp;rdquo;, and &amp;ldquo;infrastructure&amp;rdquo; in 2017 was another such
example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By the end of the year, having no single person leading more than one
subteam. That would hopefully reflect a greater degree of importance and
accountability around team leadership.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improving the RFC process to make it more manageable for team members and the
broader community alike. There are some strawman ideas on this front floating
around, which will hopefully get written up soon.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, the point is that there&amp;rsquo;s potential for much greater parallelism
within the Rust community than we have today, but to unlock that parallelism
we need to grow our leadership capacity.&lt;/p&gt;

&lt;h2 id=&quot;engage-corporations-as-users-and-sponsors&quot;&gt;Engage corporations as users and sponsors&lt;/h2&gt;

&lt;p&gt;Rust&amp;rsquo;s adoption approach so far has been relatively &amp;ldquo;bottom up&amp;rdquo;: create a
product with some strong potential business value, and focus largely on getting
engineers &amp;ldquo;on the ground&amp;rdquo; to see that business value and work toward adopting it
in their organization. Those engineers usually find small ways to use Rust, to
prove it out in their organization, before getting more ambitious. It&amp;rsquo;s a great
strategy.&lt;/p&gt;

&lt;p&gt;However, as we seek to push further into larger, more conservative
organizations, we need to supplement this bottom-up approach with a top-down
one: make Rust appealing to CTOs. The primary way to do this is by making Rust
look &lt;em&gt;boring&lt;/em&gt; and &lt;em&gt;safe&lt;/em&gt; as a technology choice. And we do &lt;em&gt;that&lt;/em&gt; by showcasing
our successes (we&amp;rsquo;ve commissioned some white papers to do this), being clear
about where Rust makes sense and where it doesn&amp;rsquo;t, and projecting maturity,
stability, and sustainability.&lt;/p&gt;

&lt;p&gt;In 2018, we should take all of these efforts to the next level. We should have a
polished web site that works for both engineers &lt;em&gt;and&lt;/em&gt; CTOs, offering white
papers and directing companies to sources of training, consulting, and
support. And we should have a large and growing list of sponsors, like Mozilla,
&lt;a href=&quot;http://bouyant.io/&quot;&gt;Bouyant&lt;/a&gt;, and &lt;a href=&quot;http://tilde.io/&quot;&gt;Tilde&lt;/a&gt; and many others, who are funding Rust work in one way or
another, either by paying their staff to contribute to Rust OSS, or by helping
pay for project infrastructure, conferences, and the like.&lt;/p&gt;

&lt;p&gt;Finally, we should do more to get production users engaged, at some level, in
the RFC process. When we&amp;rsquo;ve talked to production users, the feeling is usually
&amp;ldquo;we&amp;rsquo;re too busy writing Rust code and we trust you to get it right&amp;rdquo;. But the
result is that RFC threads don&amp;rsquo;t present a picture fully inclusive of the
production context.&lt;/p&gt;

&lt;h2 id=&quot;connect-rusts-global-community&quot;&gt;Connect Rust&amp;rsquo;s global community&lt;/h2&gt;

&lt;p&gt;While we talk about &amp;ldquo;the Rust community&amp;rdquo;, the reality is that there are &lt;em&gt;many&lt;/em&gt;
Rust communities, separated by geography and by language. We need to do much
more to connect these communities, again in terms of both contributors and
customers. What are the important use-cases for Rust in India? What are the
interests of volunteers in Brazil? What are the opportunities for Rust in China?
How can we support each other, and communicate our respective values and needs?&lt;/p&gt;

&lt;p&gt;Connecting these communities is not a small task, and I&amp;rsquo;m not sure what the
right goal is for 2018. But I would love to see a greater awareness of and focus
on this issue.&lt;/p&gt;

&lt;h2 id=&quot;serve-intermediate-rustaceans&quot;&gt;Serve intermediate Rustaceans&lt;/h2&gt;

&lt;p&gt;In 2017, we put a strong emphasis on early-stage productivity and learning
curve, which has consistently been the top issue raised by the &lt;a href=&quot;https://blog.rust-lang.org/2017/09/05/Rust-2017-Survey-Results.html&quot;&gt;Rust
survey&lt;/a&gt;. But last year, we&amp;rsquo;ve &lt;em&gt;also&lt;/em&gt; heard an increasing plea for more
&amp;ldquo;intermediate&amp;rdquo; level materials, focused on people who have learned the basic
mechanics of the language and have written some code, but are looking for help
on how to be &lt;em&gt;effective&lt;/em&gt; as a Rust programmer. How should you organize a
library? An app? When should you use traits? What about trait objects versus
generics? And what libraries and tools should you be highly familiar with?&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve made some strides on this front in 2017 with efforts like the &lt;a href=&quot;https://github.com/rust-lang-nursery/api-guidelines&quot;&gt;API
guidelines&lt;/a&gt; and the &lt;a href=&quot;https://github.com/rust-lang-nursery/rust-cookbook&quot;&gt;cookbook&lt;/a&gt;. But there&amp;rsquo;s still a lot more to do in terms of
(1) surfacing crates and tools that &amp;ldquo;every working Rustacean should know&amp;rdquo; and
(2) fleshing out more guidance for how to wield Rust effectively, after you
understand the features it provides.&lt;/p&gt;

&lt;h2 id=&quot;treat-each-other-with-empathy&quot;&gt;Treat each other with empathy&lt;/h2&gt;

&lt;p&gt;One of the most amazing things about Rust is that it brings together grizzled
C++ hackers, Raspberry Pi hobbyists, and JS pros and more into a single
community. Rust offers something to all of us, despite that our goals, values,
and interests sometimes diverge. Its ambition is to democratize robust, high
performance code, to make systems programming better and more accessible to
everyone.&lt;/p&gt;

&lt;p&gt;The secret sauce has been a certain unwillingness to compromise: to find a way
to take this diverse set of goals, backgrounds and contexts, and serve them all
simultaneously by digging deep and thinking creatively. To keep that up, it&amp;rsquo;s
vital that we don&amp;rsquo;t descend into tribalism or us-versus-them thinking, but
instead to respect each other&amp;rsquo;s constraints, and trust that our constraints will
be heard and respected as well.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Revisiting Rust’s modules, part 2</title>
   <link href="http://aturon.github.io/blog/2017/08/02/modules-part-2/"/>
   <updated>2017-08-02T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2017/08/02/modules-part-2</id>
   <content type="html">&lt;p&gt;It&amp;rsquo;s been a week since my &lt;a href=&quot;http://aturon.github.io/blog/2017/07/26/revisiting-rusts-modules/&quot;&gt;last post&lt;/a&gt; on Rust&amp;rsquo;s module system. Unsurprisingly,
the strawman proposal in that post garnered a lot of commentary&amp;ndash;174 comments in
one week!&amp;ndash;with sentiments ranging from&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now &lt;em&gt;this&lt;/em&gt; is a proposal I can get behind&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve rarely hated anything as much as I hate the module system proposal&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and everything in between :-)&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://internals.rust-lang.org/t/revisiting-rusts-modules/5628/&quot;&gt;discussion&lt;/a&gt; has raised a number of very interesting points; thanks to
everyone who has participated so far!. I won&amp;rsquo;t try to give a comprehensive
summary here. What I want to do instead is focus on one particular critique of
the earlier proposal, and present a quite different strawman design that
embraces a different set of priorities.&lt;/p&gt;

&lt;p&gt;For ease of discussion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I&amp;rsquo;ll call the strawman in my &lt;a href=&quot;http://aturon.github.io/blog/2017/07/26/revisiting-rusts-modules/&quot;&gt;last post&lt;/a&gt; the &amp;ldquo;directories-as-modules&amp;rdquo; proposal.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ll call the strawman in this post the &amp;ldquo;use-universally&amp;rdquo; proposal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-critique-of-the-directories-as-modules-proposal&quot;&gt;A critique of the directories-as-modules proposal&lt;/h2&gt;

&lt;p&gt;There were a number of concerns about the directories-as-modules proposal
(including its fairly radical nature), but the one that struck me was that the
proposal was very heavily weighted toward a particular subset of the problems
the original post raised, and didn&amp;rsquo;t help much with some of the others.&lt;/p&gt;

&lt;p&gt;To recap briefly: the original post talked about obstacles both for learning the
module system, and for using it at scale. It ultimately focused a lot on the
issue of how much we have to employ &lt;code&gt;pub use&lt;/code&gt; (aka the &amp;ldquo;facade pattern&amp;rdquo;) when
setting things up today, and I think the proposal clearly streamlines that
story. (There are also variants like &amp;ldquo;inline&amp;rdquo; aka &amp;ldquo;anonymous&amp;rdquo; modules that bring
in just part of the proposal).&lt;/p&gt;

&lt;p&gt;On the other hand, the proposal didn&amp;rsquo;t do much to help with issues around &amp;ldquo;path
confusion&amp;rdquo;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The fact that &lt;code&gt;use&lt;/code&gt; declarations work with absolute paths while other items do not is confusing, and even experienced Rust programmers (myself included) often confuse the two. To make matters worse, the top-level namespace contains all of the external &lt;em&gt;crates&lt;/em&gt;, but also the &lt;em&gt;contents&lt;/em&gt; of the current crate. Unless, of course, you’re writing an external test or binary. And finally, when you’re working at the top level, the absolute/relative distinction doesn’t matter, which means that you can have the wrong mental model and only find it when trying to expand out into submodules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many on the thread cited &lt;em&gt;this&lt;/em&gt; as the core problematic issue with the module
system; I&amp;rsquo;ve collected &lt;a href=&quot;https://gist.github.com/aturon/2f10f19f084f39330cfe2ee028b2ea0c&quot;&gt;some data&lt;/a&gt; about confusion around Rust modules which
also supports that to a degree.&lt;/p&gt;

&lt;p&gt;My goal in this post is to float a quite different proposal that emphasizes
these issues, de-emphasizes the facading issues, and overall is more
conservative. Similarly to last time, the idea here is to present a coherent,
plausible &amp;ldquo;spike&amp;rdquo; with ideas that could be useful, and seek feedback on the
broad direction without getting too bogged down in the fine details.&lt;/p&gt;

&lt;h2 id=&quot;one-other-bit-of-framing&quot;&gt;One other bit of framing&lt;/h2&gt;

&lt;p&gt;Before giving the proposal, though, I want to record one other insight I&amp;rsquo;ve had
along the way, in terms of where people sometimes go wrong when learning the
module system.&lt;/p&gt;

&lt;p&gt;Coming from other languages, there&amp;rsquo;s often an expectation that adding a &lt;code&gt;.rs&lt;/code&gt;
file to the source tree, or a dependency to &lt;code&gt;Cargo.toml&lt;/code&gt;, should be all that&amp;rsquo;s
needed to set up the naming hierarchy. From that perspective, you&amp;rsquo;d expect to be
able to use &lt;code&gt;use&lt;/code&gt; to pull items out of any of these. Instead, you &lt;em&gt;sometimes&lt;/em&gt;
can, but need to write the correct incantation (&lt;code&gt;extern crate&lt;/code&gt; or &lt;code&gt;mod&lt;/code&gt;) in the
right place first. It requires a shift in mental model. And the fact that &lt;code&gt;use&lt;/code&gt;
is much more common than &lt;code&gt;mod&lt;/code&gt; can make this all the more confusing.&lt;/p&gt;

&lt;p&gt;@kornel put together a &lt;a href=&quot;https://gist.github.com/pornel/0f7ebcec230117ab52c959fe0b090335&quot;&gt;really great chart comparing module systems&lt;/a&gt; that makes
this point quite strongly.&lt;/p&gt;

&lt;p&gt;Part of the reason I&amp;rsquo;m labeling this proposal as &amp;ldquo;use-universally&amp;rdquo; is that it
sets up &lt;code&gt;use&lt;/code&gt; declarations as the &lt;em&gt;only&lt;/em&gt; thing you need to write in your Rust
source to bring items into scope. The items that are &lt;em&gt;available&lt;/em&gt;, by contrast,
are determined by Cargo (or another build system), together with your file
system. This is one aspect that mirrors the earlier proposal, part of which is
now &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2088&quot;&gt;an RFC&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-basic-ingredients&quot;&gt;The basic ingredients&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s a quick summary of the proposal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with today&amp;rsquo;s module system.&lt;/li&gt;
&lt;li&gt;Deprecate &lt;code&gt;extern crate&lt;/code&gt;, along the lines of
the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2088&quot;&gt;in-progress RFC&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Deprecate &lt;code&gt;mod foo;&lt;/code&gt; and instead determine module structure from the file system.

&lt;ul&gt;
&lt;li&gt;However, unlike the previous proposal, this determination is the same as
today, i.e. files are modules, and directories are used to introduce nested
modules.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Improve &lt;code&gt;use&lt;/code&gt; for greater clarity around paths, which I&amp;rsquo;ll explain below.&lt;/li&gt;
&lt;li&gt;Modules are &lt;code&gt;pub(crate)&lt;/code&gt; unless they are &lt;code&gt;pub use&lt;/code&gt;d (so &lt;code&gt;pub mod foo;&lt;/code&gt; becomes
&lt;code&gt;pub use foo;&lt;/code&gt; &amp;ndash; note that this is using &lt;em&gt;relative&lt;/em&gt; paths, as I&amp;rsquo;ll explain next).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The meat is in making two adjustments for &lt;code&gt;use&lt;/code&gt; declarations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduce a &lt;code&gt;from &amp;lt;crate_name&amp;gt; use &amp;lt;path&amp;gt;;&lt;/code&gt; form for importing items from
external crates.&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;use &amp;lt;path&amp;gt;;&lt;/code&gt; to treat the path as &lt;em&gt;relative to the current module&lt;/em&gt;
(i.e. as if it started with &lt;code&gt;self::&lt;/code&gt;).

&lt;ul&gt;
&lt;li&gt;A leading &lt;code&gt;::&lt;/code&gt; takes you to the root &lt;em&gt;of the current crate&lt;/em&gt;, but is &lt;em&gt;not&lt;/em&gt; a
way to reference items from other crates.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Similar adjustments are needed for referencing paths in function signatures
etc., which I&amp;rsquo;ll elide here.)&lt;/p&gt;

&lt;p&gt;This is, of course, a breaking change. However, it has some properties that make
it a reasonable fit for the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2052&quot;&gt;checkpoint&lt;/a&gt; model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s trivial to write a &lt;code&gt;rustfix&lt;/code&gt; tool that mechanically switches today&amp;rsquo;s
&lt;code&gt;use&lt;/code&gt; declarations to this new setup, and likewise deals with &lt;code&gt;mod&lt;/code&gt; and
&lt;code&gt;extern crate&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We could introduce and stabilize the &lt;code&gt;from/use&lt;/code&gt; syntax, then deprecate use of
absolute paths in &lt;code&gt;use&lt;/code&gt; (without a leading &lt;code&gt;::&lt;/code&gt;), and employ &lt;code&gt;rustfix&lt;/code&gt; at that
point &amp;ndash; all before a new checkpoint is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, the full migration story needs to be significantly fleshed out, but
this is just meant to sketch plausibility.&lt;/p&gt;

&lt;h3 id=&quot;what-does-it-look-like&quot;&gt;What does it look like?&lt;/h3&gt;

&lt;p&gt;Before talking about the rationale, I want to show an example for
clarity. First, the parts that don&amp;rsquo;t change.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a &lt;code&gt;Cargo.toml&lt;/code&gt; excerpt:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;petgraph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;0.4.5&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A directory structure excerpt:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;src/
  lib.rs
  coherence/
    mod.rs
    solve.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;code-in-todays-module-system&quot;&gt;Code in today&amp;rsquo;s module system&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;lib.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;petgraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;coherence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;mod.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;petgraph&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;prelude&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ir&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Program&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ItemId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;solve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;solve&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;solve.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;sync&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Itertools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ir&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;code-in-the-proposed-system&quot;&gt;Code in the proposed system:&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;lib.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coherence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// note relative path; this makes `coherence` pub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;mod.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;petgraph&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prelude&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;ir&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Program&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ItemId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solve&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// note use of relative path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;solve.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sync&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Itertools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;ir&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;rationale&quot;&gt;Rationale&lt;/h3&gt;

&lt;p&gt;Each piece of this proposal has a rationale, but in some cases they&amp;rsquo;re tied
together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Introducing &lt;code&gt;from&lt;/code&gt;/&lt;code&gt;use&lt;/code&gt;&lt;/strong&gt;. This form provides a much more clear distinction
between imports from external crates and those from the local crate, which can
be helpful when exploring a codebase. Splitting out this form also means we
eliminate the very confusing issue that extern crates are &amp;ldquo;mounted&amp;rdquo; in the
current crate&amp;rsquo;s module hierarchy, usually at root. (In this analogy, the
&lt;code&gt;from&lt;/code&gt; form is more like addressing an entirely separate volume.)
Incidentally, grepping for this declaration will tell you which external
crates are in use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changing &lt;code&gt;use&lt;/code&gt; to take paths relative to the current module&lt;/strong&gt;. There are two
main reasons to do this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If submodules are always in scope for their parent module, things like
function signatures &lt;em&gt;feel&lt;/em&gt; like they are taking relative paths. (In actuality,
they are resolving names based on what&amp;rsquo;s in scope). In any case, making paths
everywhere relative to the current module reduces confusion.&lt;/li&gt;
&lt;li&gt;We want to use &lt;code&gt;pub use&lt;/code&gt; to export submodules publicly, but with absolute
paths this would be &lt;code&gt;pub use self::my_submodule&lt;/code&gt; which is awkward and
confusing; people are almost certain to forget &lt;code&gt;self&lt;/code&gt; much of the time.&lt;/li&gt;
&lt;li&gt;Note that there are often arguments that &lt;code&gt;use&lt;/code&gt;-like mechanisms should employ
absolute paths by default because that&amp;rsquo;s the common case. However, for Rust
I think that&amp;rsquo;s at least partly based on the current use for pulling in items
from external crates, and would be more evenly split in this new setup.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;pub use&lt;/code&gt; for exporting modules&lt;/strong&gt;. If the module hierarchy is
determined from the file system, we need &lt;em&gt;some&lt;/em&gt; way to say whether a module is
public. While we could say this in the module itself, doing so is
syntactically awkward, and also means that a module&amp;rsquo;s exports are spread over
multiple files. At the same time, &lt;code&gt;pub use&lt;/code&gt; still exists as a form you need to
use for re-exporting items, and it provides a reasonable mental model when using
it to export your child module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The general privacy setup&lt;/strong&gt;. A basic premise is that the visibility of a
module &lt;em&gt;name&lt;/em&gt; is not terribly important by itself; what really matters is the
visibility of &lt;em&gt;items&lt;/em&gt; within the module. Thus we simplify matters by making
&lt;em&gt;all&lt;/em&gt; modules have at least crate visibility&amp;mdash;though this does mean that
marking an item &lt;code&gt;pub&lt;/code&gt; in a module means it, in reality, has &lt;em&gt;at least&lt;/em&gt;
&lt;code&gt;pub(crate)&lt;/code&gt; visibility (and perhaps more, if it&amp;rsquo;s exported in a public
module). This is arguably a good thing; today, the fact that you can write
&lt;code&gt;pub&lt;/code&gt; but the &lt;em&gt;actual&lt;/em&gt; visibility is determined by a complex nest of
re-exports and module visibilities can make it quite hard to reason about
unfamiliar code. As has been argued on thread, the vast majority of the time
you only need visibility at one of three levels: the current module, the
crate, or the world. This proposal makes those cases all easy to express, and
requires a more explicit &lt;code&gt;pub(super)&lt;/code&gt; etc to get other privacy granularities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TL;DR: writing &lt;code&gt;pub&lt;/code&gt; on an item means &lt;code&gt;pub(crate)&lt;/code&gt; unless (re)exported in a
public module (which itself is done via re-exporting).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deprecating &lt;code&gt;mod&lt;/code&gt;/&lt;code&gt;extern crate&lt;/code&gt;&lt;/strong&gt;. This was already explained
above. There&amp;rsquo;s already been some discussion around the downsides (and ways to
mitigate them), so I&amp;rsquo;m not going to spend time on that here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note, however, that one of the alternatives below may help further mitigate
these concerns.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h2&gt;

&lt;p&gt;This design pulls together choices I believe cohere well, but there are many
possible variations that are also quite plausible. These can be broken down into
&lt;em&gt;largely&lt;/em&gt; orthogonal knobs. I&amp;rsquo;ll take a brief look at each, and the tradeoffs as
I see them.&lt;/p&gt;

&lt;h3 id=&quot;knob-from-use-ordering&quot;&gt;Knob: &lt;code&gt;from&lt;/code&gt;/&lt;code&gt;use&lt;/code&gt; ordering&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;from&lt;/code&gt;/&lt;code&gt;use&lt;/code&gt; syntax follows precedent from Python, but we could instead use the
&lt;code&gt;use&lt;/code&gt;/&lt;code&gt;from&lt;/code&gt; ordering from JS.&lt;/p&gt;

&lt;p&gt;Possible benefits of &lt;code&gt;use&lt;/code&gt;/&lt;code&gt;from&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes it easier to read at a glance, when the item name makes obvious what the
crate is.&lt;/li&gt;
&lt;li&gt;Avoids &amp;ldquo;jagged edges&amp;rdquo; of imported names.&lt;/li&gt;
&lt;li&gt;Arguably more &amp;ldquo;natural&amp;rdquo; reading (as a sentence).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Possible benefits of &lt;code&gt;from&lt;/code&gt;/&lt;code&gt;use&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More natural for autocomplete in Ides.&lt;/li&gt;
&lt;li&gt;Gives you the crate name first when reading left-to-right (better if you often
need that information to understand the import)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&amp;rsquo;s interesting to consider the choices when it comes to multi-line imports:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collections&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// versus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collections&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are of course plenty of other possible syntactic choices, but these are
relatively intuitive and descend from very commonly-used languages.&lt;/p&gt;

&lt;h3 id=&quot;knob-pub-use-foo-vs-pub-mod-foo&quot;&gt;Knob: &lt;code&gt;pub use foo&lt;/code&gt; vs &lt;code&gt;pub mod foo&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Rather than using re-exports to make a module public, we could say that the file
system determines module structure, but you use &lt;code&gt;pub mod foo;&lt;/code&gt; to make a child
module &lt;code&gt;foo&lt;/code&gt; public.&lt;/p&gt;

&lt;p&gt;The main advantage would be that it&amp;rsquo;s more plausible to continue to make &lt;code&gt;use&lt;/code&gt;
take absolute paths, which reduces breakage. On the other hand, it seems to
double down on some aspects of &amp;ldquo;path confusion&amp;rdquo;, and doesn&amp;rsquo;t achieve the
unification around &lt;code&gt;use&lt;/code&gt; that the main proposal does.&lt;/p&gt;

&lt;h3 id=&quot;knob-absolute-vs-relative-paths&quot;&gt;Knob: absolute vs relative paths&lt;/h3&gt;

&lt;p&gt;We could keep other elements of this proposal, but have &lt;code&gt;use&lt;/code&gt; continue to use
absolute paths. (We could then, for example, only allow you to reference
external crates that were brought in through &lt;code&gt;extern crate&lt;/code&gt; in &lt;code&gt;use&lt;/code&gt;, but ones
implied from &lt;code&gt;Cargo.toml&lt;/code&gt; would go through &lt;code&gt;from&lt;/code&gt;/&lt;code&gt;use&lt;/code&gt;, potentially making the
whole system backwards compatible).&lt;/p&gt;

&lt;p&gt;If we go that route, then to make a module public we&amp;rsquo;d most likely wind up with
one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pub use self::my_submodule;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pub mod my_submodule;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And again, as above, some path confusion issues remain.&lt;/p&gt;

&lt;h3 id=&quot;knob-include-on-use&quot;&gt;Knob: include on &lt;code&gt;use&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Rather than determining the module hierarchy from the file system immediately,
we could follow many other languages which add modules to the name hierarchy
only if they are in some way referenced (e.g. via &lt;code&gt;use&lt;/code&gt;); only at that point
would we examine the file system for resolution.&lt;/p&gt;

&lt;p&gt;Such an approach makes the Rust source somewhat more independent of the precise
state of the file system, and may thereby address some of the concerns people
have raised about previous proposals.&lt;/p&gt;

&lt;p&gt;A downside, though: sometimes modules contain nothing but &lt;code&gt;impl&lt;/code&gt; blocks, in
which case they are not naturally referenced elsewhere. You&amp;rsquo;d have to explicitly
&lt;code&gt;use&lt;/code&gt; such modules, and forgetting to do so could lead to some head-scratching
errors. (That said, we could generate a warning if the directory contains unused
&lt;code&gt;.rs&lt;/code&gt; files).&lt;/p&gt;

&lt;h3 id=&quot;knob-useing-submodules&quot;&gt;Knob: &lt;code&gt;use&lt;/code&gt;ing submodules&lt;/h3&gt;

&lt;p&gt;The proposal assumes that submodules are &lt;em&gt;always&lt;/em&gt; in scope for their parents. We
could instead require you to &lt;code&gt;use&lt;/code&gt; them before referring to them. I can&amp;rsquo;t see a
lot of advantage to doing that, though.&lt;/p&gt;

&lt;h2 id=&quot;extensions&quot;&gt;Extensions&lt;/h2&gt;

&lt;p&gt;Finally, while the proposal as-is only marginally helps with facades (by
removing the need for &lt;code&gt;self::&lt;/code&gt; that&amp;rsquo;s currently common when facading), it&amp;rsquo;s
compatible with future extensions that do more.&lt;/p&gt;

&lt;p&gt;For example, we could draw from earlier proposals involving &amp;ldquo;anonymous modules&amp;rdquo;
(aka &amp;ldquo;inline modules&amp;rdquo;) &amp;ndash; say, files beginning with a leading &lt;code&gt;_&lt;/code&gt; &amp;ndash; which do
not affect the module hierarchy, and where all non-private items are
automatically re-exported by the parent module. This has some of the flavor of
the previous proposal, but with a more opt-in form.&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;Just like last time around, please take this proposal as charting out one more
plausible point in the design space, and see whether there are big-picture
aspects to like or dislike, or ideas that might have promise. I&amp;rsquo;m looking
forward to your feedback!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Revisiting Rust’s modules</title>
   <link href="http://aturon.github.io/blog/2017/07/26/revisiting-rusts-modules/"/>
   <updated>2017-07-26T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2017/07/26/revisiting-rusts-modules</id>
   <content type="html">&lt;p&gt;As part of the &lt;a href=&quot;https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html&quot;&gt;Ergonomics Initiative&lt;/a&gt;, I, @withoutboats and several others on the Rust language team have been taking a hard look at Rust’s module system; you can see some earlier thoughts &lt;a href=&quot;https://withoutboats.github.io/blog/rust/2017/01/04/the-rust-module-system-is-too-confusing.html&quot;&gt;here&lt;/a&gt; and discussion &lt;a href=&quot;https://internals.rust-lang.org/t/lang-team-minutes-the-module-system-and-inverting-the-meaning-of-public/4804/66&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are two related perspectives for improvement here: learnability and productivity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modules are not a place that Rust was trying to innovate at 1.0, but they are nevertheless often reported as one of the major stumbling blocks to learning Rust. We should fix that.&lt;/li&gt;
&lt;li&gt;Even for seasoned Rustaceans, the module system has several deficiencies, as we’ll dig into below. Ideally, we can solve these problems while &lt;em&gt;also&lt;/em&gt; making modules easier to learn.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post is going to explore some of the known problems, give a few insights, and then explore the design space afresh. It does &lt;em&gt;not&lt;/em&gt; contain a specific favored proposal, but rather a collection of ideas with various tradeoffs.&lt;/p&gt;

&lt;p&gt;I want to say at the outset that, for this post, &lt;strong&gt;I’m going to completely ignore backwards-compatibility&lt;/strong&gt;. Not for lack of importance, but rather because I think it’s a useful exercise to explore the full design space in an unconstrained way, and then separately to see how best to fit those lessons back into today’s Rust.&lt;/p&gt;

&lt;h2 id=&quot;learnability-issues&quot;&gt;Learnability issues&lt;/h2&gt;

&lt;p&gt;It’s hard to nail down the precise blockers to learnability, but here are a few of the obstacles we’ve heard repeatedly in feedback from a variety of venues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Too many declaration forms&lt;/strong&gt;. Module-related declarations include &lt;code&gt;extern crate&lt;/code&gt;, &lt;code&gt;mod foo;&lt;/code&gt;, &lt;code&gt;use&lt;/code&gt;, &lt;code&gt;pub use&lt;/code&gt;, &lt;code&gt;mod { }&lt;/code&gt; and more, and each one has somewhat subtle effects on what is in scope where. For someone just starting out, this array of choices can be bewildering and stand in the way of writing “actual code” to feel out the language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Path confusion&lt;/strong&gt;. The fact that &lt;code&gt;use&lt;/code&gt; declarations work with absolute paths while other items do not is confusing, and even experienced Rust programmers (myself included) often confuse the two. To make matters worse, the top-level namespace contains all of the external &lt;em&gt;crates&lt;/em&gt;, but also the &lt;em&gt;contents&lt;/em&gt; of the current crate. Unless, of course, you’re writing an external test or binary. And finally, when you’re working at the top level, the absolute/relative distinction doesn’t matter, which means that you can have the wrong mental model and only find it when trying to expand out into submodules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filesystem organization&lt;/strong&gt;. The &lt;code&gt;foo.rs&lt;/code&gt; versus &lt;code&gt;foo/mod.rs&lt;/code&gt; distinction, together with &lt;code&gt;mod foo;&lt;/code&gt;, can be an intimidating amount of machinery just to incorporate a file into your project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy&lt;/strong&gt;. A module’s private items are always visible to its submodules. But private items &lt;em&gt;within&lt;/em&gt; its submodules aren’t visible to each other. Moreover, it’s an error to expose a private item in a public interface, but it’s common to define public items within a private module and re-export them elsewhere. Learning the ropes of the privacy system is not easy, and even experienced Rust programmers sometimes grate against it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can be hard, when more experienced with Rust, to empathize with these concerns—we suffer from the “Curse of Knowledge” here. But it’s important to recognize that all of these distinctions that are hard to learn in the first place also impose a small, but non-trivial mental tax even when you know them well. So the goal is not to make things easier for newcomers &lt;em&gt;at the expense&lt;/em&gt; of those with more experience, but rather to make things easier for everyone.&lt;/p&gt;

&lt;h2 id=&quot;productivity-issues&quot;&gt;Productivity issues&lt;/h2&gt;

&lt;p&gt;Once you’ve gotten the hang of the module system, there are still annoyances, ranging in importance from code readability concerns to minor papercuts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Who can see this item? And how?&lt;/strong&gt; It’s pretty common to find items within modules that are marked &lt;code&gt;pub&lt;/code&gt;, but are not in fact visible through the module defining them—or even visible outside the crate at all! This tends to happen when you want to organize code within the file system differently from the API hierarchy you expose to the rest of the crate or to the outside world. It generally means you have to look at several files to figure out how to access an item (or even whether you can).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pub use&lt;/code&gt; &lt;strong&gt;abuse&lt;/strong&gt;. More generally, re-exports are ubiquitous in idiomatic Rust code. The result is that the “apparent” module hierarchy (as seen from the file system) often tells you very little about the &lt;em&gt;actual&lt;/em&gt; module hierarchy, as seen from inside or outside the crate. This can make it difficult to jump into a new code base, or back into one you haven’t worked on in a while.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repetition&lt;/strong&gt;. The module system often requires two steps to do something, when a single step would suffice to convey all the necessary information:

&lt;ul&gt;
&lt;li&gt;When you add a dependency to &lt;code&gt;Cargo.toml&lt;/code&gt;, you also need to add an &lt;code&gt;extern crate&lt;/code&gt; declaration.&lt;/li&gt;
&lt;li&gt;When you add a new &lt;code&gt;.rs&lt;/code&gt; file, you also need to write a corresponding &lt;code&gt;mod&lt;/code&gt; declaration.&lt;/li&gt;
&lt;li&gt;When you have a file that exists solely for organization and you add a &lt;code&gt;pub&lt;/code&gt; item to it, you also have to &lt;code&gt;pub use&lt;/code&gt; that item elsewhere in the hierarchy.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These issues may not seem like a big deal at first, but at least in my experience, after thinking deeply about modules and surfacing these problems, I find myself noticing them &lt;em&gt;all the time&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-module-system-anyway&quot;&gt;What is a module system, anyway?&lt;/h2&gt;

&lt;p&gt;With the critique of today’s module system out of the way, I want to talk a bit about the core concerns of a module system, at least from Rust’s perspective:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bringing names into scope, including from external crates&lt;/li&gt;
&lt;li&gt;Defining the crate’s internal namespace hierarchy&lt;/li&gt;
&lt;li&gt;Defining the crate’s external namespace hierarchy&lt;/li&gt;
&lt;li&gt;Determining how code is arranged in the file system&lt;/li&gt;
&lt;li&gt;Visibility (aka privacy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things seem to work most smoothly when these concerns are closely aligned. Conversely, the places where the module system becomes hard to work with and reason about tend to be misalignments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An example of misalignment: facades in &lt;code&gt;futures&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a concrete example from the &lt;code&gt;futures&lt;/code&gt; crate. Futures, like iterators, have a large number of methods that produce “adapters”, i.e. concrete types that are also futures:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each of these concrete types (&lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Then&lt;/code&gt; and so on) involve a page or so of code, often with some helper functions. Thus, there was a strong desire to define each in a separate file, with the helper functions private to that file.&lt;/p&gt;

&lt;p&gt;However, in Rust each file is a distinct module, and it was &lt;em&gt;not&lt;/em&gt; desirable to have a large number of submodules each defining a single type. So, instead, the &lt;code&gt;future&lt;/code&gt; module has code like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flatten_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;fuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;into_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;map_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;from_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;or_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;select2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;either&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;AndThen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;flatten_stream&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;FlattenStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;fuse&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Fuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;into_stream&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;IntoStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;map_err&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;MapErr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_err&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;FromErr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;or_else&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;OrElse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SelectNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;select2&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Select2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;then&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;either&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This kind of setup is known generally as the &lt;em&gt;facade pattern&lt;/em&gt;, and it’s pretty ubiquitous in Rust code.&lt;/p&gt;

&lt;p&gt;The facade boilerplate is needed to deal with a misalignment: each adapter is defined in its own file with its own privacy boundary, but we don’t actually want that to entail a distinct &lt;em&gt;module&lt;/em&gt; for each (in the internal or external namespace hierarchy). That means we have to do two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make the modules private, despite that they contain public items&lt;/li&gt;
&lt;li&gt;Manually re-export each of the public items at a higher level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When first trying to navigate the &lt;code&gt;futures&lt;/code&gt; codebase, you have to read the &lt;code&gt;future&lt;/code&gt; module to understand how its submodules are being used, due to these re-exports. For the &lt;code&gt;futures&lt;/code&gt; crate, this is a relatively small annoyance. But it can be a real source of confusion for crates that have more of a &lt;em&gt;mixture&lt;/em&gt; of submodules, some of which are significant for the namespace hierarchy, other of which are hidden away.&lt;/p&gt;

&lt;p&gt;Another common confusion: items defined as &lt;code&gt;pub&lt;/code&gt; within a private module which are not, in fact, exported from the crate, but which may be re-exported in another crate-internal module. In this case, &lt;code&gt;pub(crate)&lt;/code&gt; would better convey intent, but today’s module system makes &lt;code&gt;pub&lt;/code&gt; the path of least resistance. That means, in turn, that an item definition alone doesn’t tell you the fully visibility story (though it does give you an &lt;em&gt;upper bound&lt;/em&gt; on visibility); in general you have to crawl through the rest of the code to figure out where the item is ultimately visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expressiveness and the common case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rust’s module system, through things like the facade pattern, gives you a lot of expressiveness: you’re not forced to keep the various concerns of the module system in alignment, and are thus free to craft the organization that you deem best.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The concern isn’t so much having this freedom, but rather how often you must wield it&lt;/strong&gt;. How often does the facade pattern show up in your code? How often do you use re-exports? How often does the directory structure of your crate bear little resemblance to the intended module hierarchy?&lt;/p&gt;

&lt;p&gt;I spent some time &lt;a href=&quot;https://paper.dropbox.com/doc/Module-system-examples-AA2Gj3010ce7XwxHfOAfs&quot;&gt;surveying&lt;/a&gt; some of the most popular and most respected crates to get a qualitative feel for this question, including: &lt;code&gt;futures&lt;/code&gt;, &lt;code&gt;regex&lt;/code&gt;, &lt;code&gt;rayon&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;openssl&lt;/code&gt;, &lt;code&gt;flate2&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;irc&lt;/code&gt;, &lt;code&gt;clap&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;serde&lt;/code&gt;, &lt;code&gt;chalk&lt;/code&gt; , &lt;code&gt;std&lt;/code&gt; and &lt;code&gt;chrono&lt;/code&gt;. Virtually every crate had something “unique” about its organization, and almost all of them used the facade pattern somewhere. In general, &lt;strong&gt;it was impossible to predict anything about the public API surface just by looking at the file system organization; you have to trace re-exports&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In short, in the vast majority of cases the module system necessitated boilerplate and a disconnect between its various concerns, impairing both write- and read-ability.&lt;/p&gt;

&lt;h2 id=&quot;increasing-alignment&quot;&gt;Increasing alignment&lt;/h2&gt;

&lt;p&gt;The question I want to pose now is: can we make the module system work more smoothly for the common case, decreasing boilerplate and increasing predictability/readability? This is a more narrow question than “how do we lower the learning curve”, but I believe that a good answer will help learnability as well.&lt;/p&gt;

&lt;p&gt;A basic strategy is to try to make the various uses of facades more “first class”, i.e. expressed in a more explicit and clear way, rather than encoded via a particular pattern of usage. Let’s take a deeper look at the ways in which facades are commonly used in the examples mentioned above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;To allow breaking code into files&lt;/strong&gt;, with file-private definitions. This is the &lt;code&gt;futures&lt;/code&gt; example discussed above: you’re forced to create submodules in order to split things into files, but you try to “hide” the submodules as much as possible using a facade, and other than the facade definition you never refer to them by name.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;To allow for &lt;code&gt;cfg&lt;/code&gt;-specific implementations&lt;/strong&gt;. For example, the standard library uses a facade-like pattern to have two side-by-side implementation of its core system primitives, for &lt;code&gt;cfg(unix)&lt;/code&gt; and &lt;code&gt;cfg(windows)&lt;/code&gt;. This is set up so that there is no visible impact on the module hierarchy, but there &lt;em&gt;is&lt;/em&gt; an impact on the filesystem hierarchy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For crate-internal organization&lt;/strong&gt;, where you &lt;em&gt;do&lt;/em&gt; want a module hierarchy (for privacy or namespacing purposes), but you don’t want to reveal it to the outside world (or, in some cases, even to other modules in the crate).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How can we make these use cases more explicit, clear, and streamlined?&lt;/p&gt;

&lt;h2 id=&quot;proposal-directories-determine-modules&quot;&gt;Proposal: directories determine modules&lt;/h2&gt;

&lt;p&gt;The central idea in this post is to &lt;strong&gt;make intent more explicit in the file system&lt;/strong&gt; than we do today, while streamlining common facade patterns. Here’s one way we might do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deprecate &lt;code&gt;mod foo;&lt;/code&gt; declarations, instead determining module directly from directory structure.&lt;/li&gt;
&lt;li&gt;Directories (not files!) determine the module hierarchy.

&lt;ul&gt;
&lt;li&gt;A directory with a leading &lt;code&gt;_&lt;/code&gt; gives you a &lt;code&gt;pub(crate)&lt;/code&gt; module.&lt;/li&gt;
&lt;li&gt;All other directories give you &lt;code&gt;pub&lt;/code&gt; modules.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.rs&lt;/code&gt; files in a directory &lt;em&gt;collectively&lt;/em&gt; determine the contents of the corresponding module.

&lt;ul&gt;
&lt;li&gt;Private items are private &lt;em&gt;to the file in which they are defined.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Items with &lt;code&gt;pub(self)&lt;/code&gt; or greater visibility are, in particular, visible to sibling files that are part of the module’s definition.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A basic example&lt;/strong&gt;
Let’s start with an example just showing the mechanics. First, the directory structure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;src/
  foo/
    these.rs
    names.rs
    do_not_matter.rs
    _infer/
      instantiate.rs
      unify.rs
  bar/
    mod.rs // this is fine, but has no special status
    impls.rs
    tests.rs
  baz.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From the directory structure alone, we know the precise module structure (modulo any inline modules; more on that later):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* scoped contents of `these.rs`, `names.rs`, `do_not_matter.rs` */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;infer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* scoped contents of `instantiate.rs` and `unify.rs` */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* scoped contents of `mod.rs`, `impls.rs` and `tests.rs` */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* scoped contents of `baz.rs` */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What do I mean by “scoped contents”? To reiterate from above, fully private definitions are private &lt;em&gt;to that file&lt;/em&gt;, while &lt;code&gt;pub(self)&lt;/code&gt; means private to the current module. To illustrate, imagine we have the following for &lt;code&gt;instantiate.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// private to this file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Instantiator&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;some_helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// private to this module, i.e. visible to all files within `_infer`, i.e.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// `instantiate.rs` and `unify.rs`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instantiate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Fold&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InfTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and then, in &lt;code&gt;unify.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// private to this file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// note: this private definition does *not* clash with the private definition&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// in `instantiate.rs`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;some_helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// visible to the whole crate at `foo::infer::UnificationResult`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UnificationResult&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Zip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InfTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;UnificationResult&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* may invoke `instantiate` */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thus, visibility annotations give you fine-grained control ranging from current file (private) to world-public (&lt;code&gt;pub&lt;/code&gt;) and every module in the hierarchy in between.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breaking code into files without module structure: the futures example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having seen the basics, let’s put this proposal to use in expressing the futures example described above:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;src/
  future/
    mod.rs
    and_then.rs
    flatten.rs
    fuse.rs
    // etc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These files would have exactly the same contents as today, except that we would be able to delete most of &lt;code&gt;mod.rs&lt;/code&gt;. That is, none of the following boilerplate is needed:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// these can go!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;fuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// these too!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;AndThen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;fuse&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Fuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thus, this proposal works particularly smoothly when you want to break a module into multiple files, with potentially file-private items—because that’s exactly how modules work in the proposal! No facade necessary, and the intended (flat) module structure is made clear and explicit via the file system structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform-specific implementations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What if you want to provide distinct implementations by platform? Again, you no longer need a facade:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;src/
  foo/
    unix.rs
    windows.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;unix.rs&lt;/code&gt; starts with &lt;code&gt;#![cfg(unix)]&lt;/code&gt; and similarly for windows. Both files are considered part of the &lt;code&gt;foo&lt;/code&gt; module’s definition, but depending on the platform one of the files will appear to be empty. (Today this pattern is implemented using submodules tagged with &lt;code&gt;cfg&lt;/code&gt;, together with re-exports.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal module structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final mis-alignment was cases where you want a module hierarchy internally, but want to expose some collapsed version of it externally. This is the one place where you still need to use &lt;code&gt;pub(use)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;// excerpted from `clap`

src/
  _app/
    help.rs
    macros.rs
    mod.rs
    parser.rs
    usage.rs
  _args/
    arg.rs
    arg_matcher.rs
    arg_matches.rs
    macros.rs
    settings.rs
  errors.rs
  fmt.rs
  suggestions.rs
  lib.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This directory structure is excepted from &lt;code&gt;clap&lt;/code&gt;, which currently has &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;args&lt;/code&gt; subdirectories but does not export any submodules; these modules are used purely for internal organization and namespacing.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;_app/mod.rs&lt;/code&gt; you might have a definition like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// note that this is `pub`!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The reader can immediately see something interesting happening: this item is defined within an “internal” (&lt;code&gt;pub(crate)&lt;/code&gt;) module, since &lt;code&gt;_app&lt;/code&gt; begins with an underscore. But it has a &lt;em&gt;larger&lt;/em&gt;, world-public visibility. This is an indication that the item will be re-exported somewhere else (and in fact, we could lint against this &lt;em&gt;not&lt;/em&gt; being the case).&lt;/p&gt;

&lt;p&gt;Accordingly, in &lt;code&gt;lib.rs&lt;/code&gt;, we might have:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In short, re-exports are still needed, but the directory structure and item visibility give the reader a strong, localized indication of what’s going on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fine details&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m glossing over a &lt;em&gt;lot&lt;/em&gt; of fine details here, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you provide module docs? One appealing possibility: via a &lt;code&gt;README.md&lt;/code&gt; file, which would have several benefits — most importantly, moving the often very large module-level docs out of band.&lt;/li&gt;
&lt;li&gt;Similarly, what’s the story for module-level attributes in general?&lt;/li&gt;
&lt;li&gt;What about inline modules?&lt;/li&gt;
&lt;li&gt;Backward-compatibility concerns?&lt;/li&gt;
&lt;li&gt;And many more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the moment, I’m going to ask that we avoid getting bogged down in these questions (which are ultimately important), so that we can focus first on whether the &lt;em&gt;broad&lt;/em&gt; direction here is a good one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tradeoffs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Speaking of evaluation: there are some tradeoffs we can see even at this level of detail.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Primary Upsides:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learning the basics of the module system is really easy: each directory defines a module name in the module hierarchy; the &lt;code&gt;.rs&lt;/code&gt; files within that directory collectively define the contents of that module. The end.&lt;/li&gt;
&lt;li&gt;The file system organization gives you a very clear, explicit view into the module structure and programmer intent. Compared to dropping into a random crate’s source code today (an exercise I &lt;a href=&quot;https://paper.dropbox.com/doc/Module-system-examples-AA2Gj3010ce7XwxHfOAfs&quot;&gt;performed repeatedly&lt;/a&gt;), I believe this approach will make it much easier to understand a crate’s overall structure with a quick run of &lt;code&gt;tree&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fewer imports are needed, because module-visible items defined in sibling files are automatically in scope (but see the downside below).&lt;/li&gt;
&lt;li&gt;Most of the common uses of facades (breaking into files/privacy boundaries, platform-specific modules) no longer require any facading, or indeed any boilerplate at all.&lt;/li&gt;
&lt;li&gt;Cases where you want some crate-internal module namespacing are expressed in a natural, obvious way (via the &lt;code&gt;_&lt;/code&gt; prefix), and one that makes it easier for readers to see that a given item will be re-exported elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Primary downsides:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bringing module-visible items into scope from sibling files means that one may have to search in multiple files to discover the definition of some item. In contrast, today every item you can mention in a file is brought into scope somewhere in &lt;em&gt;that&lt;/em&gt; file—assuming you don’t use globs.

&lt;ul&gt;
&lt;li&gt;On the other hand, this proposal eliminates boilerplate &lt;code&gt;use&lt;/code&gt; declarations for definitions that are conceptually part of the same module. And in particular, the fact that such declarations would often be relative (e.g. &lt;code&gt;use self::item;&lt;/code&gt;) may help mitigate confusion around the absolute/relative path issue.&lt;/li&gt;
&lt;li&gt;A variant of this proposal would not bring these items into scope by default, but instead allow you to do so via &lt;code&gt;use self::item;&lt;/code&gt; However, having to use &lt;code&gt;self&lt;/code&gt; here is awkward, and the definition is not helpful—it only serves to tell you that another file in the directory defines &lt;code&gt;item&lt;/code&gt;, which is something you can already determine if the binding isn’t located in the current file. (In contrast, today the required import also gives you a hint as to which file to look at).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Determining module structure from file system structure is problematic for some, due either to stashing stray &lt;code&gt;.rs&lt;/code&gt; files in the project directory, or due to potentially laggy network file access.

&lt;ul&gt;
&lt;li&gt;If this proves to be a problem in practice, we could provide an optional way to specify the desired file list. But in the vast majority of cases today the file system and module hierarchy are aligned.&lt;/li&gt;
&lt;li&gt;Some have also argued that leveraging the file system is too “implicit”, but I don’t think that argument holds water; the file system arrangement itself is a perfectly “explicit” way of providing information, and there’s no particular reason to distinguish that from &lt;code&gt;mod&lt;/code&gt; statements in code. I rather see it as the current setup forcing repetition of information. (I would also &lt;a href=&quot;https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html&quot;&gt;urge&lt;/a&gt; a focus on concrete instances of &lt;em&gt;reasoning about code&lt;/em&gt; in judging this kind of question.)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;There’s a &lt;em&gt;lot&lt;/em&gt; more to say about modules, and this proposal is just one variant of probably a dozen that the language team has been exploring. But I wanted to take the time to at least spike out one plausible option, and see what people think. As I asked above: I strongly urge people to focus only on the big-picture question of whether this avenue is appealing &lt;em&gt;at all&lt;/em&gt;, and not get too bogged down in finer details until later in the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A bit of editorializing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I like about this proposal is that it’s &lt;em&gt;dirt simple&lt;/em&gt;: the correspondence between file system and module hierarchies is very easy to describe, and today’s patterns fall out naturally, usually with significant boilerplate reduction. I think there’s a very real chance that, with this proposal, people will view Rust’s module system as easy to learn. Finally, and most subjectively, compared to some of the other ideas we’ve been exploring, there’s a certain &lt;em&gt;elegance&lt;/em&gt; to this set up; nothing feels bolted on, and the examples drawn from real-world code have a quite pleasing expression.&lt;/p&gt;

&lt;p&gt;I do worry about the sibling scoping question. I know I, for one, often track down bindings by searching purely within the current file. With this proposal, I’d have to change that workflow to &lt;code&gt;grep&lt;/code&gt;ing within the current directory, or using tags more consistently, etc. Yet, I suspect that in the end, these other workflows are an &lt;em&gt;improvement —&lt;/em&gt; e.g., tags allow a more direct jump to definition regardless of where that definition lives, whereas my current workflow often requires following a chain of imports.&lt;/p&gt;

&lt;p&gt;In any case, I think this potential workflow shift is more than made up for by the greater clarity about module structure, which makes it much easier to find your way around a project in the first place.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Shipping specialization: a story of soundness</title>
   <link href="http://aturon.github.io/blog/2017/07/08/lifetime-dispatch/"/>
   <updated>2017-07-08T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2017/07/08/lifetime-dispatch</id>
   <content type="html">&lt;p&gt;Rust&amp;rsquo;s &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;&lt;code&gt;impl&lt;/code&gt; specialization&lt;/a&gt; is a major language feature that appeared
after Rust 1.0, but has yet to be stabilized, despite strong demand.&lt;/p&gt;

&lt;p&gt;Historically, there have been three big blockers to stabilization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The interplay between specialization rules and coherence, which I resovled in
&lt;a href=&quot;http://aturon.github.io/blog/2017/02/06/specialization-and-coherence/&quot;&gt;an earlier blog post&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The precise ways in which specialization employs negative reasoning, which
will be resolved by incorporating ideas from &lt;a href=&quot;https://github.com/nikomatsakis/chalk/&quot;&gt;Chalk&lt;/a&gt; into the compiler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The soundness of specialization&amp;rsquo;s interactions with lifetimes. The &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;RFC&lt;/a&gt; talks
about this issue and proposes a way to address it, but it has never been
implemented, and early attempts to implement it in &lt;a href=&quot;https://github.com/nikomatsakis/chalk/&quot;&gt;Chalk&lt;/a&gt; have revealed
serious problems.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;rsquo;ve been wrestling, together with nmatsakis, withoutboats and others, with
these soundness issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler alert&lt;/strong&gt;: we have not fully solved them yet. But we see a viable way to
ship a sound, useful subset of specialization in the meantime. Feel free to jump
to &amp;ldquo;A modest proposal&amp;rdquo; if you just want to hear about that.&lt;/p&gt;

&lt;p&gt;This blog post is an attempt to write up what we&amp;rsquo;ve learned so far, with the
hopes that it will clarify that thinking, and maybe open the door to &lt;em&gt;you&lt;/em&gt;
cracking the nut!&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;/h2&gt;

&lt;p&gt;In stable Rust, it is &lt;strong&gt;not possible&lt;/strong&gt; for lifetimes to influence runtime
behavior. This is partly an architectural issue, and partly a design issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt;: the compiler erases lifetime information prior to
monomorphization and code generation, meaning that the generated code simply
has no way to depend on lifetimes. That could be changed, but we&amp;rsquo;d have to
work hard to avoid code blowup by generating separate copies of code
for each lifetime it was used within, assuming that the behavior didn&amp;rsquo;t
change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design&lt;/strong&gt;: lifetime inference generally chooses the &lt;em&gt;smallest&lt;/em&gt; lifetime that
fits the constraints at any given moment. That means that you can have a piece
of data that is valid for the &lt;code&gt;&amp;#39;static&lt;/code&gt; lifetime, yet is viewed as having a
shorter lifetime. Having runtime behavior depend on these choices seems bound
to result in confusion and bugs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, specialization makes the story more difficult:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&amp;#39;t know if T: &amp;#39;static&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;specialized&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What does this program print? Since the string literal &lt;code&gt;&amp;quot;test&amp;quot;&lt;/code&gt; has type
&lt;code&gt;&amp;amp;&amp;#39;static str&lt;/code&gt;, you might expect the second, specialized &lt;code&gt;impl&lt;/code&gt; to be used (and
hence to get &lt;code&gt;specialized&lt;/code&gt; as the output). But, as explained above, from the
perspective of trans this type will look like &lt;code&gt;&amp;amp;&amp;#39;erased str&lt;/code&gt;, making it
impossible to know whether the more specialized &lt;code&gt;impl&lt;/code&gt; can safely be used.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s another, less obvious example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&amp;#39;t know if two refs have equal lifetimes&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, the second &lt;code&gt;impl&lt;/code&gt; is requiring that two lifetimes are the same, and once
more for trans we can&amp;rsquo;t tell whether the &lt;code&gt;impl&lt;/code&gt; safely applies.&lt;/p&gt;

&lt;p&gt;On the other hand, simply &lt;em&gt;naming&lt;/em&gt; a lifetime that must exist, without
&lt;em&gt;constraining&lt;/em&gt; it, is fine:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Good&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Good&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Fine: specializes based on being *any* reference, regardless of lifetime&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Good&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In addition, it&amp;rsquo;s in principle okay for lifetime constraints to show up as long
as they don&amp;rsquo;t influence specialization:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Potentially fine: *all* impls impose the &amp;#39;static requirement; the dispatch is&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// happening purely based on `Clone`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;why-does-this-lead-to-unsoundness&quot;&gt;Why does this lead to unsoundness?&lt;/h3&gt;

&lt;p&gt;So far, it might seem like we can just be conservative in trans, which could
lead to confusing behavior but is otherwise alright.&lt;/p&gt;

&lt;p&gt;Sadly, it&amp;rsquo;s not, at least given the original design of specialization:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Uh oh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// typeck and trans disagree about the type of `s`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem here: specialization as originally designed will allow the
typechecker to conclude that &lt;code&gt;T::Assoc&lt;/code&gt; is &lt;code&gt;String&lt;/code&gt; if it knows that &lt;code&gt;T&lt;/code&gt; is
&lt;code&gt;&amp;amp;&amp;#39;static str&lt;/code&gt;. That&amp;rsquo;s because the impl for &lt;code&gt;&amp;amp;&amp;#39;static str&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; use the
&lt;code&gt;default&lt;/code&gt; keyword when defining its associated type, meaning that no further
specialization is allowed (so the type checker knows everything there is to
know).&lt;/p&gt;

&lt;p&gt;But trans, of course, sees &lt;code&gt;&amp;amp;&amp;#39;erased str&lt;/code&gt; instead, and so cannot safely use the
specialized &lt;code&gt;impl&lt;/code&gt;. That means that trans will make the call to &lt;code&gt;build&lt;/code&gt; return
&lt;code&gt;()&lt;/code&gt;, but the rest of the code assumed that a &lt;code&gt;String&lt;/code&gt; was returned.&lt;/p&gt;

&lt;p&gt;Oops.&lt;/p&gt;

&lt;p&gt;(Spoiler alert: the &amp;ldquo;as originally designed&amp;rdquo; bit above is a give-away of where
we&amp;rsquo;re ultimately going to end up&amp;hellip;)&lt;/p&gt;

&lt;h2 id=&quot;some-solutions-that-dont-work&quot;&gt;Some &amp;ldquo;solutions&amp;rdquo; that don&amp;rsquo;t work&lt;/h2&gt;

&lt;p&gt;Before giving my proposed way forward, let me explain why some of the solution
that are probably coming to mind don&amp;rsquo;t work out.&lt;/p&gt;

&lt;h3 id=&quot;cant-we-just-rule-out-bad-specializations&quot;&gt;Can&amp;rsquo;t we just rule out &amp;ldquo;bad&amp;rdquo; specializations?&lt;/h3&gt;

&lt;p&gt;It&amp;rsquo;s very tempting to blame the specialized &lt;code&gt;impl&lt;/code&gt;s for &lt;code&gt;Bad1&lt;/code&gt; and &lt;code&gt;Bad2&lt;/code&gt; above,
since they clearly impose lifetime constraints. Maybe we could just make it an
error to do so.&lt;/p&gt;

&lt;p&gt;Unfortunately, the trait system is very powerful, and you can &amp;ldquo;hide&amp;rdquo; lifetime
constraints within other trait impls that don&amp;rsquo;t involve specialization. Worse
still: the problem can arise from two independent crates, each of which is doing
something seemingly reasonable.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Crate marker&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Crate foo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;marker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Default impl&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;marker&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Marker impl&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Crate bar&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;marker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;marker&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Crate client&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// prints: Marker impl&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// prints: ???&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// the relevant specialization depends on the &amp;#39;static lifetime&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Activate the marker!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem here is that all of the crates in isolation look perfectly innocent.
The code in &lt;code&gt;marker&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;client&lt;/code&gt; is accepted today. It&amp;rsquo;s only when these
crates are plugged together that a problem arises &amp;ndash; you end up with a
specialization based on a &lt;code&gt;&amp;#39;static&lt;/code&gt; lifetime. And the &lt;code&gt;client&lt;/code&gt; crate may not
even be aware of the existence of the &lt;code&gt;marker&lt;/code&gt; crate.&lt;/p&gt;

&lt;p&gt;If we make this kind of situation a hard error, we could easily end up with a
scenario in which plugging together otherwise-unrelated crates is
&lt;em&gt;impossible&lt;/em&gt;. Or where a minor version bump in one dependency could irrevocably
break your code.&lt;/p&gt;

&lt;h3 id=&quot;can-we-make-a-knob-lifetime-dependent-vs-specializable&quot;&gt;Can we make a knob: &amp;ldquo;lifetime-dependent&amp;rdquo; vs &amp;ldquo;specializable&amp;rdquo;?&lt;/h3&gt;

&lt;p&gt;Thinking more about the previous example, you might imagine the problem is that
the &lt;code&gt;Marker&lt;/code&gt; trait ends up being used in two incompatible ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s used in a specialization, the second &lt;code&gt;Foo&lt;/code&gt; &lt;code&gt;impl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s used in &lt;code&gt;impl&lt;/code&gt;s that constrain lifetimes (the &lt;code&gt;Bar&lt;/code&gt; &lt;code&gt;impl&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&amp;rsquo;s the combination of these things that gets us into trouble. And each one
arises from a different crate. So you might be tempted to add an attribute, say
&lt;code&gt;#[lifetime_sensitive]&lt;/code&gt;, which allows for &lt;code&gt;impl&lt;/code&gt;s that constrain lifetimes but
prevents use in specialization.&lt;/p&gt;

&lt;p&gt;In other words, the &lt;code&gt;Marker&lt;/code&gt; trait could say, in advance, whether the &lt;code&gt;Foo&lt;/code&gt;
impls or the &lt;code&gt;Bar&lt;/code&gt; impl are acceptable.&lt;/p&gt;

&lt;p&gt;There are several downsides to this idea, but the real death-knell is that
&amp;ldquo;constraining lifetimes&amp;rdquo; is a surprisingly easy thing to do. To wit:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sneaky&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sneaky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sneaky&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sneaky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sneaky&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sneaky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;specialized&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// what does this print?&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sneaky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we have a specialized &lt;code&gt;impl&lt;/code&gt; that doesn&amp;rsquo;t mention any lifetimes or any
other traits; it just talks about the type &lt;code&gt;(T, T)&lt;/code&gt;. The problem is that it&amp;rsquo;s
asking for the two tuple components to have the &lt;em&gt;same&lt;/em&gt; type, which means that
&lt;em&gt;if&lt;/em&gt; a lifetime appears, it must be the same in both.&lt;/p&gt;

&lt;p&gt;Once more, when we go to trans the &lt;code&gt;main&lt;/code&gt; function, we&amp;rsquo;ll be invoking &lt;code&gt;sneaky&lt;/code&gt;
on the type &lt;code&gt;(&amp;amp;&amp;#39;erased str, &amp;amp;&amp;#39;erased str)&lt;/code&gt;, and we can&amp;rsquo;t tell for sure whether
the more specialized impl applies.&lt;/p&gt;

&lt;p&gt;But saying that you can never repeat a type within a specialization would be
very restrictive. And there&amp;rsquo;s always the worry that we&amp;rsquo;ve missed other sneaky
ways to constrain lifetimes&amp;hellip;&lt;/p&gt;

&lt;h3 id=&quot;can-we-make-trans-smarter&quot;&gt;Can we make trans smarter?&lt;/h3&gt;

&lt;p&gt;At this point it becomes tempting to start blaming trans. After all, if we
tracked lifetime information all the way through, wouldn&amp;rsquo;t that solve
everything?&lt;/p&gt;

&lt;p&gt;It would solve &lt;em&gt;some&lt;/em&gt; things: it would make specialization sound. But at a high
cost.&lt;/p&gt;

&lt;p&gt;As explained at the outset, tracking information through trans would involve a
massive overhaul of the compiler, and we&amp;rsquo;d have to be very smart about
coalescing code with different lifetimes but identical behavior. There&amp;rsquo;s no
guarantee we could do this without making the compiler significantly slower
and/or creating more code bloat.&lt;/p&gt;

&lt;p&gt;More fundamentally, though, it would lead to highly unpredictable behavior:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Arbitrary str: {}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;static str: {}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hello, world!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Does this program print &lt;code&gt;&amp;#39;static str: hello, world!&lt;/code&gt; twice?&lt;/p&gt;

&lt;p&gt;No! Because the call to &lt;code&gt;print_str&lt;/code&gt; will &lt;em&gt;reborrow&lt;/em&gt; the string slice at a
shorter lifetime, and so trans will monomorphize it differently.&lt;/p&gt;

&lt;p&gt;Making program behavior sensitive to the exact rules around lifetime inference
and reborrowing seems extremely risky.&lt;/p&gt;

&lt;h2 id=&quot;a-modest-proposal&quot;&gt;A modest proposal&lt;/h2&gt;

&lt;p&gt;Hopefully the above gives you some taste of the challenge here. Later in this
post we&amp;rsquo;ll look at some more promising, clever solutions. But none of them have
worked out completely, so I want to pause here and propose an incremental step
forward.&lt;/p&gt;

&lt;p&gt;First off, we add a new feature gate, &lt;code&gt;assoc_specialization&lt;/code&gt;, which is needed
whenever you use &lt;code&gt;default type&lt;/code&gt; in an impl. We then focus on stabilizing just
the core &lt;code&gt;specialization&lt;/code&gt; feature, i.e. &lt;em&gt;without&lt;/em&gt; being able to specialize
associated types. That immediately means we can stop worrying about making type
checking and trans agree, since type checking will essentially no longer care
about specialization.&lt;/p&gt;

&lt;p&gt;Many uses of specialization, including most of the original motivating examples,
do not need to be able to specialize associated types.&lt;/p&gt;

&lt;p&gt;With that out of the way, we still have work to do at the trans level. In
particular, we must ensure that trans is conservative when it comes to lifetime
constraints. The proposal here is twofold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Any time a specialized impl imposes &lt;em&gt;any&lt;/em&gt; lifetime constraints not present in
the more general impl, trans uses the more general impl instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, in these cases, we trigger an error-by-default lint to warn that a
possibly-applicable specialization is not being used. (This needs to be a
lint, not a hard error, because the relevant impls aren&amp;rsquo;t always under your
crate&amp;rsquo;s control.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&amp;rsquo;s revisit some of the earlier examples in this light:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&amp;#39;t know if T: &amp;#39;static:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;specialized&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// prints `generic`, but also generates a warning&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bad1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For this example, trans would pick the generic implementation, but issue a
warning that a specialization &lt;em&gt;might&lt;/em&gt; have applied. You could imagine going
further and detecting simple cases like this where a given impl will &lt;em&gt;never&lt;/em&gt; be
used (as in the second impl of &lt;code&gt;Bad1&lt;/code&gt;) and issuing errors. But as explained
above, we cannot catch them all.&lt;/p&gt;

&lt;p&gt;On the other hand, consider this case:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, both impls impose &lt;code&gt;&amp;#39;static&lt;/code&gt; constraints, so the second impl doesn&amp;rsquo;t impose
any &lt;em&gt;new&lt;/em&gt; lifetime constraints, and trans can choose it.&lt;/p&gt;

&lt;p&gt;To make this work, in trans, when we query the trait system we replace each
instance of &lt;code&gt;&amp;#39;erased&lt;/code&gt; with a &lt;em&gt;distinct, fresh&lt;/em&gt; lifetime variable, which is a
simple way to encode that anything we deduce in the query must be valid for
&lt;em&gt;all&lt;/em&gt; sets of unerased lifetimes. The &lt;a href=&quot;https://github.com/nikomatsakis/chalk/&quot;&gt;Chalk&lt;/a&gt; approach will make this quite easy
to do.&lt;/p&gt;

&lt;p&gt;Even for the cases we&amp;rsquo;re covering, though, it&amp;rsquo;s possible to do better (we&amp;rsquo;ll see
more on that later). That means we might want to &amp;ldquo;improve&amp;rdquo; the behavior of trans
after stabilizing the core of specialization. Fortunately, we should be able to
statically detect all cases where the behavior of trans would change, and issue
a different warning that the behavior will improve. That gives us leverage to
use something like &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2052&quot;&gt;epochs&lt;/a&gt; to make trans smarter over time, while still
shipping some version of specialization relatively soon.&lt;/p&gt;

&lt;p&gt;The only alternative seems to be to continue to pursue increasingly clever
solutions before shipping anything&amp;mdash;which is a worrying approach to take when
it comes to soundness. Better, in my opinion, to ship a sound 80% of the feature
now, with some rough edges, and improve it over time.&lt;/p&gt;

&lt;h2 id=&quot;going-deeper&quot;&gt;Going deeper&lt;/h2&gt;

&lt;p&gt;Before I close out this post, I want to write out some of the further
explorations we&amp;rsquo;ve done, and what we&amp;rsquo;ve learned.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s an interesting example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;specialized&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using the strategy outlined above, trans will go from &lt;code&gt;(&amp;amp;&amp;#39;erased str, &amp;amp;&amp;#39;erased
str)&lt;/code&gt; to &lt;code&gt;(&amp;amp;&amp;#39;a str, &amp;amp;&amp;#39;b str)&lt;/code&gt; and hence use the generic implementation (and
issue a lint that the more specific impl is being ignored). However, &lt;em&gt;type
check&lt;/em&gt; could deduce that the more specialized impl always applies when invoking
&lt;code&gt;special&lt;/code&gt; in &lt;code&gt;pair&lt;/code&gt;, and you could imagine communicating that information down
to trans.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s going on here is that type check sees things before monomorphization, and
trans sees them afterward. In this particular case, that ends up making trans
more conservative, since it can&amp;rsquo;t tell that two appearances of &lt;code&gt;&amp;#39;erased&lt;/code&gt; always
come from the same, single lifetime.&lt;/p&gt;

&lt;p&gt;The story changes if we add one layer of &amp;ldquo;indirection&amp;rdquo; around trait dispatch:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;specialized&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;use_special&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Special&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now at type checking time, the actual use of &lt;code&gt;special&lt;/code&gt; occurs in a context where
we &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know that we&amp;rsquo;ll always be using the more specialized version.&lt;/p&gt;

&lt;p&gt;Why harp on this point? Well, for one, it&amp;rsquo;s the main issue in allowing for sound
specialization of associated types. We can see this in a variant of the &lt;code&gt;Bomb&lt;/code&gt;
example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Uh oh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// typeck and trans disagree about the type of `s`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, again, type check knows that the relevant uses of &lt;code&gt;Bomb&lt;/code&gt; all involve types
of the form &lt;code&gt;(T, T)&lt;/code&gt; and therefore can use the specialized version, and that
could be communicated to trans. But, once more, adding a layer of indirection
makes that much harder:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;indirect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indirect&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Uh oh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// typeck and trans disagree about the type of `s`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is that type check can no longer tell trans to use the specialized
impl in the call to &lt;code&gt;Assoc::default&lt;/code&gt;, &lt;em&gt;but&lt;/em&gt; it is still assuming that the
specialized impl is used externally (i.e., in the &lt;code&gt;build&lt;/code&gt; function).&lt;/p&gt;

&lt;p&gt;To sum up, there are two inter-related places where type check and trans differ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lifetime erasure&lt;/li&gt;
&lt;li&gt;Monomorphization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can partly deal with the first of these by introducing fresh lifetime
variables for each lifetime that appears in type check, just as we do for
trans&amp;mdash;basically asking for the trait system to only find answers that would
apply for arbitrary lifetime choices.&lt;/p&gt;

&lt;p&gt;The monomorphization issue, though, appears much harder to cope with. One
possible avenue is to track impl choices in a way that crosses functions, in
other words allowing the knowledge from &lt;code&gt;build&lt;/code&gt; that the specialized impl of
&lt;code&gt;Bomb&lt;/code&gt; can be used to be used when monomorphizing and generating code for
&lt;code&gt;indirect&lt;/code&gt;. Niko tells me that, in ancient times, the compiler used to do
something much like this&amp;mdash;and that it was incredibly painful and complicated.&lt;/p&gt;

&lt;p&gt;In any case, taking these further steps would appear to require substantial
additional work, and it seems hard to achieve confidence in their soundness. So
dropping associated type specialization for now, where it&amp;rsquo;s relatively easy to
argue for soundness, seems like the right step to take (@arielb1, here&amp;rsquo;s where
you prove me wrong).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Negative reasoning in Chalk</title>
   <link href="http://aturon.github.io/blog/2017/04/24/negative-chalk/"/>
   <updated>2017-04-24T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2017/04/24/negative-chalk</id>
   <content type="html">&lt;p&gt;I&amp;rsquo;ve had the pleasure in recent weeks of working
on &lt;a href=&quot;https://github.com/nikomatsakis/chalk/&quot;&gt;Chalk&lt;/a&gt;, the project that Niko&amp;rsquo;s
been blogging about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2017/01/26/lowering-rust-traits-to-logic/&quot;&gt;Lowering Rust traits to logic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/&quot;&gt;Unification in Chalk, part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2017/04/23/unification-in-chalk-part-2/&quot;&gt;Unification in Chalk, part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project has a few goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Recast Rust&amp;rsquo;s trait system explicitly in terms of logic programming, by
&amp;ldquo;lowering&amp;rdquo; Rust code into a kind of logic program we can then execute queries
against.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a prototype for an implementation based on these principles in rustc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide an executable, highly readable specification for the trait system.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We expect &lt;em&gt;many&lt;/em&gt; benefits from this work. It will consolidate our existing,
somewhat ad hoc implementation into something far more principled and
expressive, which should behave better in corner cases, and be much easier to
extend. For example, the current implementation &lt;em&gt;already&lt;/em&gt;
supports
&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/11/02/associated-type-constructors-part-1-basic-concepts-and-introduction/&quot;&gt;associated type constructors&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It also makes it much easier to gain confidence in what the trait system is
doing, because we can understand it in relatively simple logical terms.&lt;/p&gt;

&lt;h2 id=&quot;open-problems-in-paradise&quot;&gt;Open problems in paradise&lt;/h2&gt;

&lt;p&gt;All that said, Chalk isn&amp;rsquo;t finished, and it&amp;rsquo;s currently missing some of the core
pieces of the real trait system.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been trying to puzzle out a tangle of related such open problems for
Chalk. In particular, I want to work out how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Give a very precise and principled meaning for the Yes, No, and Maybe
results you can receive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Account for the various &amp;ldquo;mode switches&amp;rdquo; we employ in today&amp;rsquo;s trait
system, which control the degree of negative reasoning permitted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Account for rustc&amp;rsquo;s precedence rules that e.g. give more weight to &lt;code&gt;where&lt;/code&gt;
clauses than to blanket &lt;code&gt;impl&lt;/code&gt;s when it comes to type inference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support coherence checking, which requires (constrained) negative reasoning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leverage the orphan rules for reasoning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incorporate specialization soundly (ruling out lifetime dispatch).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The theme that ties all of these topics together is &lt;em&gt;negative reasoning&lt;/em&gt;, i.e
the ability to conclude definitively that something is &lt;em&gt;not true&lt;/em&gt;. For the trait
system, that usually means that a type definitively does not implement a
trait. And what we&amp;rsquo;ve learned over time is, relying on this kind of reasoning
can make your code brittle to changes in other crates: new impls are added all
the time, and can invalidate these kinds of negative
conclusions. We&amp;rsquo;ve
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1023&quot;&gt;carefully designed&lt;/a&gt; the existing
trait system to strike the right balance between the ability to reason
negatively and the ability of other crates to evolve, but the current
implementation feels ad hoc and incomplete. The challenge is putting all of this
on much firmer footing, by understanding it in terms of explicit logic
programming, and keeping the underlying logic grounded in well-understood
logical principles. (And that, by the way, would be a huge win, since we&amp;rsquo;ve
often been quite fearful about negative reasoning in rustc, since it&amp;rsquo;s so easy
to do it incorrectly.)&lt;/p&gt;

&lt;p&gt;It turns out that Prolog has similar concerns about negation. In particular, the
natural way of implementing negation in a Prolog engine is through &lt;em&gt;failure&lt;/em&gt;:
&lt;code&gt;not P&lt;/code&gt; means you tried but failed to prove &lt;code&gt;P&lt;/code&gt; &lt;em&gt;given the facts currently
present in the Prolog program&lt;/em&gt;. For this to be valid as logical negation, we
have to view the program under a &amp;ldquo;closed world assumption&amp;rdquo;: the facts that
follow from the program&amp;rsquo;s clauses, and &lt;em&gt;only&lt;/em&gt; those facts, are true.&lt;/p&gt;

&lt;p&gt;To understand the rest of this post, you&amp;rsquo;ll want to have read at least the first
of Niko&amp;rsquo;s series.&lt;/p&gt;

&lt;h2 id=&quot;negative-reasoning-in-rust-today&quot;&gt;Negative reasoning in Rust today&lt;/h2&gt;

&lt;p&gt;To get more clarity about the negative reasoning issues, let&amp;rsquo;s look at the
various places they come into play in the current trait system.&lt;/p&gt;

&lt;p&gt;The current system has two distinct &amp;ldquo;mode switches&amp;rdquo;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rust/blob/4ed95009d8d5d50c4f7aee35ad89c30a2258ffa9/src/librustc/traits/select.rs#L75-L89&quot;&gt;Intercrate mode&lt;/a&gt;,
which forces the trait system to account for the possibility that (1)
downstream crates using this crate can introduce new types and trait impls
that we can&amp;rsquo;t know about and (2) upstream crates could be &lt;em&gt;changed&lt;/em&gt; to
introduce new trait impls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rust/blob/4ed95009d8d5d50c4f7aee35ad89c30a2258ffa9/src/librustc/traits/project.rs#L41-L63&quot;&gt;User-facing projection mode&lt;/a&gt;,
which forces the trait system to account for the possibility that upstream
crates could be changed to introduce new specializations (and thus alter the
definition of an associated type).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll see what this means concretely in a moment, but one observation right off
the bat: these switches are &lt;em&gt;not&lt;/em&gt; used orthogonally today. In particular, there
is no code today that uses intercrate mode without also using user-facing
projection mode.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s go through the three major areas of the compiler that use the trait system
and see how they employ these modes, and what the implications are.&lt;/p&gt;

&lt;h3 id=&quot;overlap-checking-and-intercrate-mode&quot;&gt;Overlap checking and intercrate mode&lt;/h3&gt;

&lt;p&gt;Part of trait coherence is checking impls for &lt;em&gt;overlap&lt;/em&gt;. Consider the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do these two impls overlap? It depends on whether &lt;code&gt;(): Error&lt;/code&gt; &amp;ndash; or more
precisely, whether we can definitively conclude &lt;code&gt;not { (): Error }&lt;/code&gt;. If we are
allowed to conclude that &lt;code&gt;not { (): Error }&lt;/code&gt;, then we can conclude that the two
impls don&amp;rsquo;t overlap.&lt;/p&gt;

&lt;p&gt;Should we be able to draw such a conclusion? On the one hand, &lt;em&gt;currently&lt;/em&gt; &lt;code&gt;()&lt;/code&gt;
does not implement the &lt;code&gt;Error&lt;/code&gt; trait (both are defined in &lt;code&gt;std&lt;/code&gt;), and hence the
two impls here do not overlap. However, if &lt;code&gt;std&lt;/code&gt; was ever changed so that &lt;code&gt;()&lt;/code&gt;
implemented &lt;code&gt;Error&lt;/code&gt;, these impls &lt;em&gt;would&lt;/em&gt; overlap and could not be allowed. In
other words, &lt;code&gt;std&lt;/code&gt; adding such an impl would irrevocably break this code! And
we&amp;rsquo;d like for &lt;code&gt;std&lt;/code&gt; to be able to add trait implementations without requiring a
new major version of Rust.&lt;/p&gt;

&lt;p&gt;Part of
the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1023&quot;&gt;rebalancing coherence RFC&lt;/a&gt; was
a decision that &lt;strong&gt;these kinds of negative conclusions can only be drawn about
type/trait combinations that are fully under the current crate&amp;rsquo;s control&lt;/strong&gt;.  In
other words, it connects negative reasoning to the &lt;em&gt;orphan rule&lt;/em&gt;, which says
which impls a crate is allowed to provide. (There is also a mechanism, called
&lt;code&gt;fundamental&lt;/code&gt;, to promise that certain impls won&amp;rsquo;t be provided in the future,
but we&amp;rsquo;ll ignore that for now.) By limiting negative reasoning in this way, we
can &amp;ldquo;future proof&amp;rdquo; crates against changes their dependencies will likely make,
such as introducing impls. While such changes can still cause type inference
ambiguities, they can never cause irrevocable breakage.&lt;/p&gt;

&lt;p&gt;To illustrate where we &lt;em&gt;do&lt;/em&gt; allow negative reasoning for overlap checking,
consider the following variant:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyStruct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// does not implement Error&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyStruct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we allow the trait system to conclude that &lt;code&gt;not { MyStruct: Error }&lt;/code&gt;,
because whether or not &lt;code&gt;MyStruct: Error&lt;/code&gt; is &lt;strong&gt;entirely under this crate&amp;rsquo;s
control&lt;/strong&gt;, so there is no risk of an innocent upstream change breaking this
crate.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a more subtle case:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Aux&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// no impls in this crate&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// no impl for Error in this crate&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This example has a lot going on. The key point is that the current crate defines
an &lt;code&gt;Aux&lt;/code&gt; trait, but does not implement it for &lt;em&gt;any&lt;/em&gt; types. Hence, there is no
&lt;code&gt;T&lt;/code&gt; you could mention in this crate such that &lt;code&gt;T: Aux&lt;/code&gt;, and hence no type &lt;code&gt;T&lt;/code&gt;
such that &lt;code&gt;MyStruct&amp;lt;T&amp;gt;: Error&lt;/code&gt;. Can we thus conclude that for &lt;em&gt;all&lt;/em&gt; &lt;code&gt;T&lt;/code&gt;, &lt;code&gt;not {
MyStruct&amp;lt;T&amp;gt;: Error }&lt;/code&gt;? No! Because a downstream crate using this one could
define a new type &lt;code&gt;Foo&lt;/code&gt; and implement &lt;code&gt;Aux&lt;/code&gt; for it, and then suddenly
&lt;code&gt;MyStruct&amp;lt;Foo&amp;gt;&lt;/code&gt; would have &lt;em&gt;two&lt;/em&gt; applicable impls of &lt;code&gt;MyTrait&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For that reason, we consider not only the way that existing, upstream crates
could provide new impls over time, but also consider that downstream crates can
introduce new types, and new trait impls for them, that we will never be able to
know about here.&lt;/p&gt;

&lt;p&gt;All of the above restrictions on negative reasoning are part of &lt;em&gt;intercrate
mode&lt;/em&gt;, which is only used by overlap checking.&lt;/p&gt;

&lt;h3 id=&quot;type-checking-and-user-facing-projection-mode&quot;&gt;Type checking and user-facing projection mode&lt;/h3&gt;

&lt;p&gt;Another case of negative reasoning arises through specialization. Consider:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Crate A&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Crate B&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Should this compile? More specifically, is it valid for crate B to conclude that
the associated type &lt;code&gt;T&lt;/code&gt; for &lt;code&gt;bool&lt;/code&gt;&amp;lsquo;s implementation of &lt;code&gt;Foo&lt;/code&gt; is &lt;code&gt;bool&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It would be sound to make that assumption, since we know that crate A is the
only crate that can implement &lt;code&gt;Foo&lt;/code&gt; for &lt;code&gt;bool&lt;/code&gt; (due to the orphan rules), and
chose not to specialize the impl. However, in the future, crate A could be
modified with an additional impl:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that change would break crate B. So this is again a question of what changes
an upstream crate should be able to make in a minor revision.&lt;/p&gt;

&lt;p&gt;Currently, we tilt things in favor of crate A being able to add such an impl,
and thus &lt;em&gt;do not&lt;/em&gt; allow the original example to compile. This is again a form of
constraining negative reasoning: we do not allow crate B to conclude that there
is not a more specialized impl that applies, because there could be one in the
future.&lt;/p&gt;

&lt;p&gt;Interestingly, in the current implementation you could not write &lt;code&gt;fn main&lt;/code&gt; even
in crate A, where all of the relevant impls are under the crate&amp;rsquo;s direct
control. I consider this a bug.&lt;/p&gt;

&lt;p&gt;In any case, this negative reasoning restriction is called &amp;ldquo;user-facing
projection mode&amp;rdquo; (as opposed to &amp;ldquo;trans-facing&amp;rdquo;, which we&amp;rsquo;ll see below). It&amp;rsquo;s
turned on during both type checking and overlap checking.&lt;/p&gt;

&lt;h4 id=&quot;why-type-checking-does-not-turn-on-intercrate-mode&quot;&gt;Why type checking does not turn on intercrate mode&lt;/h4&gt;

&lt;p&gt;Today, type checking and overlap checking differ in one (big) way with respect
to negative reasoning: type checking does &lt;em&gt;not&lt;/em&gt; turn on intercrate mode. Why?&lt;/p&gt;

&lt;p&gt;Consider the following, quite contrived example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code compiles and prints &amp;ldquo;Local&amp;rdquo;. That&amp;rsquo;s because, from what this crate can
see, &lt;em&gt;no&lt;/em&gt; type implements &lt;code&gt;Bar&amp;lt;T&amp;gt;&lt;/code&gt;, so only the second impl of &lt;code&gt;Foo&lt;/code&gt; is viable.
That conclusion is then fed into type inference, which decides to interpret
&lt;code&gt;&amp;lt;()&amp;gt;::make()&lt;/code&gt; as &lt;code&gt;&amp;lt;() as Foo&amp;lt;Local&amp;gt;&amp;gt;::make()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is all kosher because, for soundness, the only thing that matters about
type inference is that, in the end, we get something that typechecks. And we&amp;rsquo;ve
made a &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2014/09/30/multi-and-conditional-dispatch-in-traits/#crate-concatenability-and-inference&quot;&gt;deliberate decision&lt;/a&gt; to &lt;em&gt;not&lt;/em&gt; make type inference future-proofed against
changes in other crates, since that creates serious ergonomic problems (see the
linked post, particularly the section on conditional impls).&lt;/p&gt;

&lt;h3 id=&quot;trans&quot;&gt;Trans&lt;/h3&gt;

&lt;p&gt;On the other hand, when it comes time to actually generate code, we are no
longer interested in future-proofing (which has already been taken care of in
the static checking described above), and instead expect to get a clear-cut
answer to all questions we ask of the trait system&amp;ndash;in part because all of the
questions will involve fully monomorphized types. In particular, we need to
allow &lt;code&gt;default&lt;/code&gt; associated types to be revealed, so that we can generate code.&lt;/p&gt;

&lt;p&gt;Thus, when using the trait system within trans, we allow full-blown negative
reasoning.&lt;/p&gt;

&lt;h2 id=&quot;modal-logic&quot;&gt;Modal logic&lt;/h2&gt;

&lt;p&gt;So, putting together all of the above: the trait system engages in various forms
of negative reasoning, but at different times this reasoning is restricted in
different ways. Only the trans point of view correlates directly with Prolog&amp;rsquo;s
&amp;ldquo;negation as failure&amp;rdquo;/closed world view. The question now is, can we understand
the restricted forms of negative reasoning in logical terms as well?&lt;/p&gt;

&lt;p&gt;It turns out that there&amp;rsquo;s a very satisfying answer: use a &lt;em&gt;modal&lt;/em&gt; logic.&lt;/p&gt;

&lt;p&gt;Modal logic makes truth relative to a &lt;em&gt;possible world&lt;/em&gt;, rather than being an
absolute thing. In one world, the sky is blue; in another world, it&amp;rsquo;s
red. That&amp;rsquo;s the story for &amp;ldquo;facts&amp;rdquo;. But the basic rules of logic apply no matter
what world you&amp;rsquo;re talking about: 1+1 = 2 in every possible world.&lt;/p&gt;

&lt;p&gt;An important aspect of modal logics is &lt;em&gt;modalities&lt;/em&gt;, which are basically ways of
qualifying a statement by what world(s) you are talking about. The statement I
just made above is an example of a modal statement: 1+1 = 2 &lt;em&gt;in every possible
world&lt;/em&gt;. There are lots of possible modalities, like &amp;ldquo;in every &lt;em&gt;future&lt;/em&gt; world&amp;rdquo; or
&amp;ldquo;in &lt;em&gt;some possible&lt;/em&gt; world&amp;rdquo; and so on.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a &lt;em&gt;lot&lt;/em&gt; more to say about modal logic, but this post is going to tell
the story in a Rust-centric way. You can find more
background &lt;a href=&quot;https://plato.stanford.edu/entries/logic-modal/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;possible-worlds-in-rust&quot;&gt;Possible worlds in Rust&lt;/h3&gt;

&lt;p&gt;What does all this mean for Rust? We can give a rational reconstruction of what
the compiler currently does via modal logic, and use it to guide the development
of Chalk, resolving a number of open questions along the way.&lt;/p&gt;

&lt;p&gt;First off, a &amp;ldquo;possible world&amp;rdquo; for us will be a full crate graph, with a
particular crate being considered &amp;ldquo;the current crate&amp;rdquo; (the one actively being
compiled). In the simplest case, there&amp;rsquo;s just one crate, like in the following
two examples:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Program A&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Program B&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both crates define &lt;code&gt;MyType&lt;/code&gt; and &lt;code&gt;MyTrait&lt;/code&gt;, but in the first one &lt;code&gt;MyType:
MyTrait&lt;/code&gt;, while in the second one, &lt;code&gt;not { MyType: MyTrait }&lt;/code&gt;. The facts on the
ground depend on the crate you&amp;rsquo;re compiling. And when you&amp;rsquo;re asking Chalk a
question, that question is normally grounded in the particular crate graph
you&amp;rsquo;ve lowered to Chalk&amp;rsquo;s logic. In other words, statements made &lt;em&gt;directly about
the current world&lt;/em&gt; are interpreted in, well, a &amp;ldquo;closed world&amp;rdquo; way: we know
precisely what the world is, and can give firm answers on that basis. That&amp;rsquo;s the
appropriate interpretation for trans, as we saw above.&lt;/p&gt;

&lt;p&gt;Second&amp;ndash;and this is really the key idea&amp;ndash;&lt;strong&gt;we add a modality to Chalk to make
statements about &lt;em&gt;all compatible worlds&lt;/em&gt; to the one we&amp;rsquo;re currently in&lt;/strong&gt;. This
is how we capture the idea of &amp;ldquo;future proofed&amp;rdquo; reasoning of the kind we want in
type and coherence checking. A world is &lt;em&gt;compatible&lt;/em&gt; with the current world if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current crate is unchanged.&lt;/li&gt;
&lt;li&gt;All dependencies of the current crate still exist, but may be extended in
&lt;em&gt;semver-compatible&lt;/em&gt; ways (i.e., ways that would only require a minor version bump).&lt;/li&gt;
&lt;li&gt;Downstream crates (that use the current crate) can come, go, and otherwise
change in arbitrary ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&amp;rsquo;s see an example. Suppose we have a two crate dependency graph:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// WORLD 1&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&amp;rsquo;s a compatible world, one that extends crate A in a minor-bump kind of way:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// WORLD 2&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;- changed&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, here&amp;rsquo;s an interesting thing: in the world 1, &lt;code&gt;not { CrateAType: Foo
}&lt;/code&gt;. But in this new, compatible world 2, &lt;code&gt;CrateAType: Foo&lt;/code&gt;! The facts on the
ground have changed in a meaningful way.&lt;/p&gt;

&lt;p&gt;Could we go the other way around? That is, if we&amp;rsquo;re currently talking about the
world 2, is world 1 considered compatible? No. Because &lt;em&gt;removing&lt;/em&gt; a
trait impl is not a semver-compatible change. What that means in practice is
that, when jumping to a compatible world, you can go from &lt;code&gt;not { Foo: Bar }&lt;/code&gt; to
&lt;code&gt;Foo: Bar&lt;/code&gt;, but not the other way around.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a world that is incompatible with the world 1:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// World 3&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;- changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The change here is very similar to the change in world 2, but the key difference
is &lt;em&gt;which crate&lt;/em&gt; was changed: crate B, the &amp;ldquo;current crate&amp;rdquo;, is different in this
world, and that makes it incompatible with world 1. This is how we get a
distinction for the &amp;ldquo;local&amp;rdquo; crate, which we control and therefore don&amp;rsquo;t need to
future-proof against. So if &lt;code&gt;not { CrateBType: Foo }&lt;/code&gt; and crate B is the current
crate, we know that in any compatible world, &lt;code&gt;not { CrateBType: Foo }&lt;/code&gt; will
still be true.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s talk about the other kind of change allowed to the world:
arbitrary changes to downstream crates. In world 1, we didn&amp;rsquo;t have any crates
downstream from crate B. Here&amp;rsquo;s a world that does:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// WORLD 4&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate C -- a downstream crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateCType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CrateCType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, in world 1 we could conclude &lt;code&gt;not { exists&amp;lt;T&amp;gt; { T: Foo } }&lt;/code&gt;. But in world 4
here, we have &lt;code&gt;CrateCType: Foo&lt;/code&gt;. That&amp;rsquo;s the kind of thing that we assume can
happen during coherence checking, but today we &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; in typechecking. As we&amp;rsquo;ll
see later, though, this single notion of compatible worlds will end up sufficing
for both.&lt;/p&gt;

&lt;p&gt;Finally, let&amp;rsquo;s look at one more world, this time involving downstream crates:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// WORLD 5&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate C -- a downstream crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_b&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;- Note the type here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This world is not just incompatible with world 1&amp;ndash;it&amp;rsquo;s not even a possible
world! That&amp;rsquo;s because crate C violates the orphan rule by providing an impl for
a type and trait it does not define (&lt;code&gt;Foo&lt;/code&gt; for &lt;code&gt;CrateBType&lt;/code&gt;). In other words,
when we consider &amp;ldquo;all compatible worlds&amp;rdquo;, we take into account the orphan rules
when doing so. And that&amp;rsquo;s why, starting from world 1, we know that in all
compatible worlds, &lt;code&gt;not { CrateBType: Foo }&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-compat-modality&quot;&gt;The &lt;code&gt;compat&lt;/code&gt; modality&lt;/h3&gt;

&lt;p&gt;The discussion for Rust so far has focused on the underlying meaning of
worlds. But we want to &amp;ldquo;surface&amp;rdquo; that meaning through a modality that we can use
when making statements or asking questions in Chalk. We&amp;rsquo;ll do this via the
&lt;em&gt;&lt;code&gt;compat&lt;/code&gt; modality&lt;/em&gt;. (For modal logic aficionados, this is basically the &amp;ldquo;box&amp;rdquo;
modality, where the reachable worlds are the &amp;ldquo;compatible&amp;rdquo; ones, described
below.)&lt;/p&gt;

&lt;p&gt;The basic idea is that if we pose a query &lt;code&gt;Q&lt;/code&gt;, that&amp;rsquo;s understood in terms of the
current world, but if we ask &lt;code&gt;compat { Q }&lt;/code&gt;, we&amp;rsquo;re asking if &lt;code&gt;Q&lt;/code&gt; is true &lt;em&gt;in all
compatible worlds&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Revisiting our example above, if world 1 is the current world, here are some
fact&amp;rsquo;s we&amp;rsquo;ll be able to deduce&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;not { CrateAType: Foo }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;not { CrateBType: Foo }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;not { exists&amp;lt;T&amp;gt; { T: Foo } }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compat { not { CrateBType: Foo } }&lt;/code&gt; &amp;ndash; in every compatible world, we &lt;em&gt;still&lt;/em&gt; know that &lt;code&gt;CrateBType&lt;/code&gt; does not implement &lt;code&gt;Foo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here are some statements that will &lt;em&gt;not&lt;/em&gt; hold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;compat { not { CrateAType: Foo } }&lt;/code&gt;, because of examples like world 2.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compat { CrateAType: Foo }&lt;/code&gt;, because of world 1 itself.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compat { not { exists&amp;lt;T&amp;gt; { T: Foo } } }&lt;/code&gt;, for similar reasons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that for a given query &lt;code&gt;Q&lt;/code&gt;, we might not be able to show &lt;code&gt;compat { Q }&lt;/code&gt;
&lt;em&gt;or&lt;/em&gt; &lt;code&gt;compat { not { Q } }&lt;/code&gt;, because some compatible worlds satisfy &lt;code&gt;Q&lt;/code&gt;, and
some don&amp;rsquo;t. So, within the &lt;code&gt;compat&lt;/code&gt; modality, you don&amp;rsquo;t get
the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Law_of_excluded_middle&quot;&gt;law of the excluded middle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s more to say about this modality and how it&amp;rsquo;s implemented, but we can
already put some cards on the table: when we&amp;rsquo;re type or coherence checking, the
queries we pose to Chalk will be placed within a &lt;code&gt;compat&lt;/code&gt; modality, which
essentially &amp;ldquo;future proofs&amp;rdquo; their conclusions. For trans, we&amp;rsquo;ll pose queries
directly about the current world.&lt;/p&gt;

&lt;p&gt;In other words, having the &lt;code&gt;compat&lt;/code&gt; modality means we can decide whether to make
a &amp;ldquo;closed world assumption&amp;rdquo; or not, depending on what we&amp;rsquo;re trying to do.&lt;/p&gt;

&lt;h2 id=&quot;not-taking-yes-or-no-for-an-answer&quot;&gt;Not taking Yes or No for an answer&lt;/h2&gt;

&lt;p&gt;To finish telling the story around modalities in Chalk, as well as to fully
capture the current trait system&amp;rsquo;s behavior, we need to talk a little bit about
what kinds of answers you can get when you pose a query to Chalk.&lt;/p&gt;

&lt;p&gt;Traditional logic programming gives you two kinds of answers: Yes (with some
information about how the query was resolved) and No. So for example, take the
following Rust program:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Display&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you ask &lt;code&gt;exists&amp;lt;T&amp;gt; { T: Foo }&lt;/code&gt; in a traditional Prolog engine, you&amp;rsquo;ll get
something like &amp;ldquo;Yes, T = u8&amp;rdquo;; if you ask again, you&amp;rsquo;ll get &amp;ldquo;Yes, T = bool&amp;rdquo;, and
if you ask a final time, you&amp;rsquo;ll get &amp;ldquo;No&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s not quite what we want for Rust. There, &amp;ldquo;existential&amp;rdquo; questions come up
primarily when we&amp;rsquo;re in the middle of type inference and we don&amp;rsquo;t know what a
particular type is yet. Think about a program using the &lt;code&gt;Foo&lt;/code&gt; trait like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we go to type check this function, we don&amp;rsquo;t immediately know what the type
returned by &lt;code&gt;Foo::new()&lt;/code&gt; is going to be, or which &lt;code&gt;impl&lt;/code&gt; to use. While it&amp;rsquo;s true
that there &lt;em&gt;do exist&lt;/em&gt; types we could use, we don&amp;rsquo;t want to pick one at random
for type inference. Instead, we want an error asking the programmer to clarify
which type they wanted to use.&lt;/p&gt;

&lt;p&gt;On the other hand, when there&amp;rsquo;s &lt;em&gt;only one choice&lt;/em&gt; of type given other
constraints, we allow type inference to assume the programmer must have meant
that type:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// prints `true`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Similarly, when it comes time to generate code, we expect there to be a &lt;em&gt;unique&lt;/em&gt;
choice of impl to draw each method call from!&lt;/p&gt;

&lt;p&gt;These considerations have led both rustc and Chalk to adopt a kind of three-way
answer system: Yes, No, and Maybe. The &lt;em&gt;precise&lt;/em&gt; meaning of these outcomes has
been a bit muddy, but part of what I want to advocate for is the following
setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Yes: in the current world, there is a &lt;em&gt;unique&lt;/em&gt; way of choosing the
existentials (inference variables) to make the query true; here&amp;rsquo;s what it is.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No: the query does not hold in the current world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maybe: the query may or may not hold in the current world; optionally, here&amp;rsquo;s
a suggestion of what to choose for the existentials if you get stuck.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is this business about getting stuck? In general, when we&amp;rsquo;re type checking
a function body, we don&amp;rsquo;t always know the type of everything at the time we
encounter it. Take, for example, the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we are typechecking the first line, we know that &lt;code&gt;opt&lt;/code&gt; will have type
&lt;code&gt;Option&amp;lt;?T&amp;gt;&lt;/code&gt;, but we don&amp;rsquo;t know what &lt;code&gt;?T&lt;/code&gt; is; it&amp;rsquo;s an inference variable. Later
on in checking, as we encounter further constraints, we&amp;rsquo;ll learn that &lt;code&gt;?T&lt;/code&gt; must
be &lt;code&gt;bool&lt;/code&gt;. By the time we finish typechecking a function body, &lt;em&gt;all&lt;/em&gt; inference
variables must be so resolved; otherwise, we wouldn&amp;rsquo;t know how to generate the
code!&lt;/p&gt;

&lt;p&gt;This inference process is interleaved with querying the trait system, as in the
&lt;code&gt;Convert&lt;/code&gt; example above. So in general we need the trait system to feed back
information about unknown types. But for the case of &lt;code&gt;Maybe&lt;/code&gt;, the trait system
is saying that there &lt;em&gt;might&lt;/em&gt; be multiple ways of implementing the trait, and the
suggested types being returned should only be used as a &amp;ldquo;fallback&amp;rdquo; if type
checking otherwise can&amp;rsquo;t make any progress.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take a look at a couple of ways that this version of Maybe helps.&lt;/p&gt;

&lt;h3 id=&quot;leveraging-maybe-for-where-clause-precedence&quot;&gt;Leveraging Maybe for &lt;code&gt;where&lt;/code&gt; clause precedence&lt;/h3&gt;

&lt;p&gt;In the current trait system, &lt;code&gt;where&lt;/code&gt; clauses are given precedence over other
impls when it comes to type inference:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The program prints &lt;code&gt;false&lt;/code&gt;. What&amp;rsquo;s happening here is that the call to &lt;code&gt;foo&lt;/code&gt;
within &lt;code&gt;println!&lt;/code&gt; does not provide enough information by itself to know whether
we want the &lt;code&gt;Foo&amp;lt;bool&amp;gt;&lt;/code&gt; impl or the &lt;code&gt;Foo&amp;lt;()&amp;gt;&lt;/code&gt; impl, both of which apply. In
other words, there&amp;rsquo;s not a unique way to resolve the type. &lt;em&gt;However&lt;/em&gt;, the
current trait system assumes that if you have an explicit &lt;code&gt;where&lt;/code&gt; clause, it
should take precedence over impls, and hence influence type inference.&lt;/p&gt;

&lt;p&gt;It wasn&amp;rsquo;t initially clear how this would carry over to Chalk, where we&amp;rsquo;re trying
to take a &amp;ldquo;pure logic&amp;rdquo; stance on things, and hence would prefer not to bake in
various notions of precedence and so on.&lt;/p&gt;

&lt;p&gt;However, with the reading of Maybe given above, we can yield a Maybe answer here
and &lt;em&gt;recommend&lt;/em&gt; to type inference that it choose &lt;code&gt;bool&lt;/code&gt; if it gets stuck, but
we&amp;rsquo;ve made clear that this is a sort of &amp;ldquo;extra-logical&amp;rdquo; step.&lt;/p&gt;

&lt;h3 id=&quot;leveraging-maybe-for-type-checking-under-compat&quot;&gt;Leveraging Maybe for type checking under &lt;code&gt;compat&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Similarly, recall that in the current trait system, there are &lt;em&gt;two&lt;/em&gt; different
mode switches, but so far we&amp;rsquo;ve only talked about a single &lt;code&gt;compat&lt;/code&gt; modality to
add to Chalk.&lt;/p&gt;

&lt;p&gt;The key, again, is to leverage Maybe. In particular, we can have both type
checking and coherence checking make queries to Chalk within the &lt;code&gt;compat&lt;/code&gt;
modality. But if they get a Maybe answer back, they will interpret it
differently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Coherence, which is trying to be conservative, will consider a Maybe to mean
&amp;ldquo;Yes, these could potentially overlap&amp;rdquo;, and hence produce an error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type checking, as explained above, will take the fallbacks suggested by Maybe
under advisement, and if it gets stuck, will apply them and see whether it can
make further progress.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here again was the example that distinguished the modes that type checking and
coherence used:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The key point was: can you deduce that &lt;code&gt;not { exists&amp;lt;T&amp;gt; { (): Bar&amp;lt;T&amp;gt; } }&lt;/code&gt;, and
hence that only the second impl of &lt;code&gt;Foo&lt;/code&gt; could possibly apply?&lt;/p&gt;

&lt;p&gt;In the system proposed by this post, we&amp;rsquo;d follow a chain of events like the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type checker asks: &lt;code&gt;exists&amp;lt;T&amp;gt; { compat { (): Make&amp;lt;T&amp;gt; } }&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;We check the first impl, and end up asking: &lt;code&gt;compat { (): Bar&amp;lt;?T&amp;gt; }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;We return &lt;code&gt;Maybe&lt;/code&gt;, since we&amp;rsquo;re within &lt;code&gt;compat&lt;/code&gt; and there are indeed some
compatible worlds for which &lt;code&gt;(): Bar&amp;lt;?T&amp;gt;&lt;/code&gt; for some &lt;code&gt;?T&lt;/code&gt;; but we have no
idea what that &lt;code&gt;?T&lt;/code&gt; should be.&lt;/li&gt;
&lt;li&gt;We check the second impl, and get &lt;code&gt;Yes&lt;/code&gt; with &lt;code&gt;?T = Local&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Since there were multiple possibilities, we don&amp;rsquo;t have a &lt;em&gt;unique&lt;/em&gt; answer;
but only one of the possibilities gave us a suggestion for the inference variables.
So we return &lt;code&gt;Maybe&lt;/code&gt; with &lt;code&gt;?T = Local&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The type checker takes under advisement that &lt;code&gt;?T&lt;/code&gt; should be unified with
&lt;code&gt;Local&lt;/code&gt; if nothing else constrains it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, unlike with the current trait implementation, we don&amp;rsquo;t have to
&lt;em&gt;pretend&lt;/em&gt; that we actually get a unique answer here; we can work within the
future-proofed &lt;code&gt;compat&lt;/code&gt; modality, and get back a &lt;code&gt;Maybe&lt;/code&gt; answer with the
suggestion we wanted.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s quite nice that all of the static checking takes place under the &amp;ldquo;future
proofing&amp;rdquo; of the &lt;code&gt;compat&lt;/code&gt; modality, whereas trans talks only about the world as
it is, under a closed world assumption.&lt;/p&gt;

&lt;h2 id=&quot;implementing-not-and-compat-in-chalk&quot;&gt;Implementing &lt;code&gt;not&lt;/code&gt; and &lt;code&gt;compat&lt;/code&gt; in Chalk&lt;/h2&gt;

&lt;p&gt;Before we close out this post, it&amp;rsquo;s worth being a bit more concrete about how
&lt;code&gt;not&lt;/code&gt; and &lt;code&gt;compat&lt;/code&gt; would be implemented in Chalk (neither exists today).&lt;/p&gt;

&lt;h3 id=&quot;negation&quot;&gt;Negation&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;not { Q }&lt;/code&gt;, we basically follow Prolog-style negation-as-failure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attempt to solve Q, then dispatch on the answer we got:

&lt;ul&gt;
&lt;li&gt;If we got &lt;code&gt;Yes&lt;/code&gt;, return &lt;code&gt;No&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If we got &lt;code&gt;No&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;If there are no existential variables within &lt;code&gt;Q&lt;/code&gt;, return &lt;code&gt;Yes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Otherwise, return &lt;code&gt;Maybe&lt;/code&gt;, with no type suggestions&lt;/li&gt;
&lt;li&gt;If we got &lt;code&gt;Maybe&lt;/code&gt;, return &lt;code&gt;Maybe&lt;/code&gt;, with no type suggestions&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, with negation we don&amp;rsquo;t get information about existential
variables, which is the same in traditional Prolog.&lt;/p&gt;

&lt;h3 id=&quot;the-compat-modality&quot;&gt;The &lt;code&gt;compat&lt;/code&gt; modality&lt;/h3&gt;

&lt;p&gt;The implementation of &lt;code&gt;compat { Q }&lt;/code&gt; is a bit more complex. First of all, it&amp;rsquo;s
important to realize that Chalk already operates on an explicit &amp;ldquo;world&amp;rdquo;, namely
the program you&amp;rsquo;ve lowered to it. When you ask questions, it will use this world
as one source of facts (together with &lt;code&gt;where&lt;/code&gt; clauses, basically). So the
question is: how do we tweak this setup to capture the idea of &amp;ldquo;Evaluate this in
any world compatible with the current one&amp;rdquo;?&lt;/p&gt;

&lt;p&gt;We certainly can&amp;rsquo;t literally construct every such world, as there are an
infinite number of them. But fortunately, we don&amp;rsquo;t have to. The role of the
world in Chalk, as I said above, is to provide a core source of facts. To model
&amp;ldquo;some arbitrary compatible world&amp;rdquo;, we just need to capture the various facts
that might be true in such a world. This can be done in a &amp;ldquo;lazy&amp;rdquo; kind of way: in
the &lt;code&gt;compat&lt;/code&gt; modality, whenever we are seeing whether a particular fact is true
by virtue of the current world, we see whether it&amp;rsquo;s a fact that &lt;em&gt;could&lt;/em&gt; be made
true in some compatible world, and if so yield &lt;code&gt;Maybe&lt;/code&gt; (with no suggested types).&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at this concretely, revisiting world 1:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// WORLD 1&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate A&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// crate B -- the current crate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crate_a&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we ask &lt;code&gt;CrateAType: Foo&lt;/code&gt;, we&amp;rsquo;ll get No. But if we ask &lt;code&gt;compat { CrateAType:
Foo }&lt;/code&gt;, then Chalk should switch into &amp;ldquo;compatible world&amp;rdquo; mode, so that when it&amp;rsquo;s
consulting the world whether &lt;code&gt;CrateAType: Foo&lt;/code&gt;, it will determine that such an
impl could be added by crate A, and hence return Maybe. But &lt;code&gt;compat {
CrateBType: Foo }&lt;/code&gt; will return No, because we know the current crate controls
the existence of such an impl. And hence, &lt;code&gt;compat { not { CrateBType: Foo } }&lt;/code&gt;
returns Yes. (Other than turning on &amp;ldquo;compatible world&amp;rdquo; mode, the &lt;code&gt;compat&lt;/code&gt;
modality just re-invokes the solver and returns up whatever was found.)&lt;/p&gt;

&lt;p&gt;This strategy has much in common with the current rustc implementation, but now
we have explicit negation (which does the right thing both inside and outside
the modality), and we can get away with just this &lt;em&gt;single&lt;/em&gt; modality, versus
rustc&amp;rsquo;s two different &amp;ldquo;global switches&amp;rdquo;. Moreover, we&amp;rsquo;ve rationally
reconstructed the behavior by connecting it to modal logic, which puts us on
better footing for exploring extensions (like negative trait impls and so on).&lt;/p&gt;

&lt;p&gt;A word about associated types:
as
&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2017/04/23/unification-in-chalk-part-2/&quot;&gt;Niko&amp;rsquo;s latest post&lt;/a&gt; discusses,
when we lower impls we separately lower the fact that the impl &lt;em&gt;exists&lt;/em&gt; from the
various projections it provides. For &lt;code&gt;compat&lt;/code&gt;, we only need to handle &lt;code&gt;Type:
Trait&lt;/code&gt; kinds of facts; the &amp;ldquo;applicative fallback&amp;rdquo; for associated type projection
takes care of the rest.&lt;/p&gt;

&lt;p&gt;Altogether, we avoid actually &lt;em&gt;constructing&lt;/em&gt; some particular compatible world,
and avoid having to guess meaningful facts about it; we just say &amp;ldquo;Maybe&amp;rdquo; to any
question that could have a different answer in some compatible world.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What&amp;rsquo;s next&lt;/h2&gt;

&lt;p&gt;Putting together everything proposed in this post, we&amp;rsquo;ve achieved quite a bit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A clear meaning for Yes/No/Maybe.&lt;/li&gt;
&lt;li&gt;A story for the various &amp;ldquo;modes&amp;rdquo; in today&amp;rsquo;s trait system, which means we can
support type checking, coherence checking, and trans.&lt;/li&gt;
&lt;li&gt;A story for integrating the orphan rules into Chalk.&lt;/li&gt;
&lt;li&gt;A story for integrating the &lt;code&gt;where&lt;/code&gt; clause precedence rules into Chalk.&lt;/li&gt;
&lt;li&gt;A clear treatment of negative reasoning in general, which will allow us to
much more confidently employ it in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What&amp;rsquo;s missing to achieve parity with rustc is specialization. It turns out that
the modal foundation laid here provides most of what we need for
specialization. However, there are some additional concerns around &amp;ldquo;lifetime
dispatch&amp;rdquo;, which render rustc&amp;rsquo;s implementation of specialization unsound. The
Chalk implementation should provide a testbed for finally solving those issues.
I plan to have a follow-up post about that in the near future.&lt;/p&gt;

&lt;p&gt;The design presented here is also just an &amp;ldquo;on paper&amp;rdquo; design. I&amp;rsquo;ll be working to
implement it over the coming weeks.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Specialization, coherence, and API evolution</title>
   <link href="http://aturon.github.io/blog/2017/02/06/specialization-and-coherence/"/>
   <updated>2017-02-06T00:00:00-08:00</updated>
   <id>http://aturon.github.io/2017/02/06/specialization-and-coherence</id>
   <content type="html"></content>
 </entry>
 
 <entry>
   <title>Designing futures for Rust</title>
   <link href="http://aturon.github.io/blog/2016/09/07/futures-design/"/>
   <updated>2016-09-07T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2016/09/07/futures-design</id>
   <content type="html">&lt;p&gt;I &lt;a href=&quot;http://aturon.github.io/blog/2016/08/11/futures/&quot;&gt;recently wrote&lt;/a&gt; about the
importance of asynchronous I/O in Rust and the aims of the new
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs&quot;&gt;futures&lt;/a&gt; library. This post deepens
the story by explaining the core &lt;em&gt;design&lt;/em&gt; of that library. If you&amp;rsquo;re looking for
more on the &lt;em&gt;use&lt;/em&gt; of the library, you&amp;rsquo;ll have to wait; we&amp;rsquo;re very actively
working on the &lt;a href=&quot;http://aturon.github.io/blog/2016/08/26/tokio/&quot;&gt;Tokio stack&lt;/a&gt; and
will have more to say once that&amp;rsquo;s settled down a bit.&lt;/p&gt;

&lt;p&gt;To recap, &lt;strong&gt;the aim is robust and ergonomic async I/O with no performance
penalty&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Robust&lt;/strong&gt;: the library should have a strong story for error handling,
cancellation, timeouts, backpressure, and other typical concerns for writing
robust servers. This being Rust, we&amp;rsquo;ll also of course
&lt;a href=&quot;https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html&quot;&gt;guarantee thread safety&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ergonomic&lt;/strong&gt;: the library should make writing asynchronous code as painless
as possible—ideally, as easy as writing synchronous code, but with greater
expressivity. While the latter will require
&lt;a href=&quot;https://en.wikipedia.org/wiki/Await&quot;&gt;&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;&lt;/a&gt; to fully achieve, the
futures library provides a high-level way of expressing and combining
asynchronous computation, similar to Rust&amp;rsquo;s successful
&lt;a href=&quot;https://static.rust-lang.org/doc/master/std/iter/trait.Iterator.html&quot;&gt;&lt;code&gt;Iterator&lt;/code&gt; API&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero cost&lt;/strong&gt;: code written using the library should compile down to something
equivalent (or better than) &amp;ldquo;hand-rolled&amp;rdquo; server implementations, which would
typically use manual state machines and careful memory management.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Achieving these goals requires a mix of existing techniques in Rust, and some
new ideas about how to build a futures library; this post will cover both. In a
nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage Rust&amp;rsquo;s traits and closures for ergonomics and cost-avoidance&lt;/strong&gt;.
Traits and closures in Rust do &lt;em&gt;not&lt;/em&gt; require heap allocation or dynamic
dispatch—facts we take heavy advantage of. We also use the trait system to
package up the futures API in a simple and convenient way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design the core &lt;code&gt;Future&lt;/code&gt; abstraction to be &lt;em&gt;demand-driven&lt;/em&gt;, rather than callback-oriented&lt;/strong&gt;.
(In async I/O terms, follow the &amp;ldquo;readiness&amp;rdquo; style rather than the &amp;ldquo;completion&amp;rdquo; style.)
That means that composing futures together does not involve creating
intermediate callbacks. As we&amp;rsquo;ll see, the approach also has benefits for
backpressure and cancellation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Provide a &lt;em&gt;task&lt;/em&gt; abstraction, similar to a green thread, that drives a future to completion&lt;/strong&gt;.
Housing futures within a task is what enables the library code to compile down
to the traditional model, i.e., with big state machines that can serve as a
callback for a large number of underlying events.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&amp;rsquo;s dive in!&lt;/p&gt;

&lt;h2 id=&quot;background-traits-in-rust&quot;&gt;Background: traits in Rust&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;ll start with a quick review of traits in Rust. If you want more reading on
these topics, you might check out the longer
&lt;a href=&quot;https://blog.rust-lang.org/2015/05/11/traits.html&quot;&gt;overview of traits&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand how the futures design works, you need to have a basic grasp on
Rust&amp;rsquo;s traits. I won&amp;rsquo;t attempt a complete introduction here, but I&amp;rsquo;ll try to hit
the most relevant highlights for making sense of what&amp;rsquo;s going on.&lt;/p&gt;

&lt;p&gt;Traits provide Rust&amp;rsquo;s sole notion of &lt;em&gt;interface&lt;/em&gt;, meaning that a trait
is an abstraction that can apply to many concrete types. For example, here&amp;rsquo;s a
simplified trait for hashing:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This trait stipulates that the type implementing it must provide a &lt;code&gt;hash&lt;/code&gt;
method, which
&lt;a href=&quot;http://blog.skylight.io/rust-means-never-having-to-close-a-socket/&quot;&gt;borrows&lt;/a&gt;
&lt;code&gt;self&lt;/code&gt; and produces a &lt;code&gt;u64&lt;/code&gt;. To implement the trait, you have to give a concrete
definition for the method, like the following simple-minded one:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;u64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once these implementations are in place, you can make calls like &lt;code&gt;true.hash()&lt;/code&gt;
to invoke the method directly. But often the methods are called via &lt;em&gt;generics&lt;/em&gt;,
which is where traits truly act as an abstraction:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print_hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;The hash is {}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;print_hash&lt;/code&gt; function is generic over an unknown type &lt;code&gt;T&lt;/code&gt;, but requires that
&lt;code&gt;T&lt;/code&gt; implements the &lt;code&gt;Hash&lt;/code&gt; trait. That means we can use it with &lt;code&gt;bool&lt;/code&gt; and &lt;code&gt;i32&lt;/code&gt;
values:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// instantiates T = bool&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;print_hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// instantiates T = i32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Generics are compiled away, resulting in static dispatch&lt;/strong&gt;. That is, as with
C++ templates, the compiler will generate &lt;em&gt;two copies&lt;/em&gt; of the &lt;code&gt;print_hash&lt;/code&gt;
method to handle the above code, one for each concrete argument type.  That in
turn means that the internal call to &lt;code&gt;t.hash()&lt;/code&gt;—the point where the
abstraction is actually used—has zero cost: it will be compiled to a direct,
static call to the relevant implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// The compiled code:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;__print_hash_bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// invoke specialized bool version directly&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;__print_hash_i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// invoke specialized i32 version directly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Compiling down to non-generic code is essential for making an abstraction like
futures work without overhead: most of the time, that non-generic code will also
be inlined, letting the compiler produce and optimize large blocks of code that
resemble what you might have written in a low-level, &amp;ldquo;hand-rolled&amp;rdquo; style.&lt;/p&gt;

&lt;p&gt;Closures in Rust work the same way—in fact, they&amp;rsquo;re just traits. That means, in
particular, that creating a closure does not entail heap allocation, and calling
a closure can be statically-dispatched, just like the &lt;code&gt;hash&lt;/code&gt; method above.&lt;/p&gt;

&lt;p&gt;Finally, traits can &lt;em&gt;also&lt;/em&gt; be used as &amp;ldquo;objects&amp;rdquo;, which cause the trait methods
to be &lt;em&gt;dynamically&lt;/em&gt; dispatched (so the compiler doesn&amp;rsquo;t immediately know what
implementation a call will use). The benefit to trait objects is for
&lt;em&gt;heterogeneous collections&lt;/em&gt;, where you need to group together a number of
objects which may have different underlying types but all implement the same
trait. Trait objects must always be behind a pointer, which in practice usually
requires heap allocation.&lt;/p&gt;

&lt;h2 id=&quot;defining-futures&quot;&gt;Defining futures&lt;/h2&gt;

&lt;p&gt;Now, let&amp;rsquo;s turn to futures. The
&lt;a href=&quot;http://aturon.github.io/blog/2016/08/11/futures/&quot;&gt;earlier post&lt;/a&gt; gave an
informal definition of a future:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In essence, a future represents a value that might not be ready yet. Usually,
the future becomes &lt;em&gt;complete&lt;/em&gt; (the value is ready) due to an event happening
somewhere else.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clearly, we&amp;rsquo;ll want futures to be some kind of trait, since there will be many
different kinds of &amp;ldquo;values that aren&amp;rsquo;t ready yet&amp;rdquo; (e.g. data on a socket, the
return value from an RPC call, etc.). But how do we represent the &amp;ldquo;not ready
yet&amp;rdquo; part?&lt;/p&gt;

&lt;h3 id=&quot;false-start-the-callback-aka-completion-based-approach&quot;&gt;False start: the callback (aka completion-based) approach&lt;/h3&gt;

&lt;p&gt;There&amp;rsquo;s a very standard way to describe futures, which we found in every
existing futures implementation we inspected: as a function that subscribes a
&lt;em&gt;callback&lt;/em&gt; for notification that the future is complete.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Note&lt;/strong&gt;: In the async I/O world, this kind of interface is sometimes referred
to as &lt;em&gt;completion-based&lt;/em&gt;, because events are signaled on completion of
operations;
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx&quot;&gt;Windows&amp;rsquo;s IOCP&lt;/a&gt;
is based on this model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Rust terms, the callback model leads to a trait like the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// The type of value produced by the future&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Tell the future to invoke the given callback on completion&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;FnOnce&lt;/code&gt; here is a trait for closures that will be invoked at most
once. Because &lt;code&gt;schedule&lt;/code&gt; is using generics, it will statically dispatch any
calls to that closure.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;strong&gt;this approach nevertheless forces allocation at almost every
point of future composition, and often imposes dynamic dispatch&lt;/strong&gt;, despite our
best efforts to avoid such overhead.&lt;/p&gt;

&lt;p&gt;To see why, let&amp;rsquo;s consider a basic way of combining two futures:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function takes two futures, &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt;, and returns a new future that
yields a pair with results from both. The &lt;code&gt;join&lt;/code&gt;ed future completes only when
&lt;em&gt;both&lt;/em&gt; of the underlying futures complete, but allows the underlying futures to
execute concurrently until then.&lt;/p&gt;

&lt;p&gt;How would we implement &lt;code&gt;join&lt;/code&gt; using the above definition of &lt;code&gt;Future&lt;/code&gt;? The
&lt;code&gt;join&lt;/code&gt;ed future will be given a single callback &lt;code&gt;both_done&lt;/code&gt; which expects a
pair. But the underlying futures each want their own callbacks &lt;code&gt;f_done&lt;/code&gt; and
&lt;code&gt;g_done&lt;/code&gt;, taking just their own results. Clearly, we need some kind of &lt;em&gt;sharing&lt;/em&gt;
here: we need to construct &lt;code&gt;f_done&lt;/code&gt; and &lt;code&gt;g_done&lt;/code&gt; so that either can invoke
&lt;code&gt;both_done&lt;/code&gt;, and make sure to include appropriate synchronization as well. Given
the type signatures involved, there&amp;rsquo;s simply no way to do this without
allocating (in Rust, we&amp;rsquo;d use an &lt;code&gt;Arc&lt;/code&gt; here).&lt;/p&gt;

&lt;p&gt;This kind of problem was repeated in many of the future combinators.&lt;/p&gt;

&lt;p&gt;Another problem is that event sources like event loops need to invoke callbacks
of arbitrary, different types—a case of the heterogeneity mentioned above. As a
concrete example, when a socket is ready for reading, that event will need to be
dispatched to &lt;em&gt;some&lt;/em&gt; callback, and in general you&amp;rsquo;ll need a mix of different
futures to be in play with different sockets. To make this work, you end up
needing to heap-allocate callbacks for the event loop &lt;em&gt;at every point the future
wants to listen for an event&lt;/em&gt;, and dynamically dispatch notifications to those
callbacks.&lt;/p&gt;

&lt;p&gt;TL;DR, we were unable to make the &amp;ldquo;standard&amp;rdquo; future abstraction provide
zero-cost composition of futures, and we know of no &amp;ldquo;standard&amp;rdquo; implementation
that does so.&lt;/p&gt;

&lt;h3 id=&quot;what-worked-the-demand-driven-aka-readiness-based-approach&quot;&gt;What worked: the demand-driven (aka readiness-based) approach&lt;/h3&gt;

&lt;p&gt;After much soul-searching, we arrived at a new &amp;ldquo;demand-driven&amp;rdquo; definition of
futures. Here&amp;rsquo;s a &lt;strong&gt;simplified&lt;/strong&gt; version that ignores the error handling of
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html&quot;&gt;the real trait&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// A *simplified* version of the trait, without error-handling&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// The type of value produced on success&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Polls the future, resolving to a value if possible&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;/// Represents that a value is immediately ready.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;/// Represents that a value is not ready yet, but may be so later.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NotReady&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The API shift here is straightforward: rather than the future proactively
invoking a callback on completion, an external party must &lt;em&gt;poll&lt;/em&gt; the future to
drive it to completion. The future can signal that it&amp;rsquo;s not yet ready and must
be polled again at some later point by returning &lt;code&gt;Async::NotReady&lt;/code&gt; (an
abstraction of &lt;code&gt;EWOULDBLOCK&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Note&lt;/strong&gt;: In the async I/O world, this kind of interface is sometimes referred
to as &lt;em&gt;readiness-based&lt;/em&gt;, because events are signaled based on &amp;ldquo;readiness&amp;rdquo; of
operations (e.g. bytes on a socket being ready) followed by an attempt to
complete an operation;
&lt;a href=&quot;http://man7.org/linux/man-pages/man7/epoll.7.html&quot;&gt;Linux&amp;rsquo;s epoll&lt;/a&gt; is based on
this model. (This model can also express completion, by treating the
completion of an operation as the signal that the future is ready for
polling.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By eliminating all the intermediate callbacks, we&amp;rsquo;ve addressed some of the key
problems of the previous version of the trait. But we&amp;rsquo;ve introduced a new one:
after &lt;code&gt;NotReady&lt;/code&gt; is returned, who polls the future, and when do they do so?&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take a concrete example. If a future is attempting to read bytes from a
socket, that socket may not be ready for reading, in which case the future can
return &lt;code&gt;NotReady&lt;/code&gt;. &lt;em&gt;Somehow&lt;/em&gt;, we must arrange for the future to later be &amp;ldquo;woken
up&amp;rdquo; (by calling &lt;code&gt;poll&lt;/code&gt;) once the socket becomes ready. That kind of wakeup is
the job of the event loop. But now we need some way to connect the signal at the
event loop back to continuing to poll the future.&lt;/p&gt;

&lt;p&gt;The solution forms the other main component of the design: tasks.&lt;/p&gt;

&lt;h3 id=&quot;the-cornerstone-tasks&quot;&gt;The cornerstone: tasks&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A &lt;em&gt;task&lt;/em&gt; is a future that is being executed&lt;/strong&gt;. That future is almost always
made up of a chain of other futures, as in the example from the original post:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id_rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The key point is that there&amp;rsquo;s a difference between functions like &lt;code&gt;and_then&lt;/code&gt;,
&lt;code&gt;map&lt;/code&gt; and &lt;code&gt;join&lt;/code&gt;, which combine futures into bigger futures, and functions that
&lt;em&gt;execute&lt;/em&gt; futures, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;wait&lt;/code&gt; method, which simply runs the future as a task pinned to the
current thread, blocking that thread until a result is produced and returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;spawn&lt;/code&gt; method on a thread pool, which launches a future as an independent
task on the pool.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These &lt;em&gt;execution&lt;/em&gt; functions create a task that contains the future and is
responsible for polling it. In the case of &lt;code&gt;wait&lt;/code&gt;, polling takes place
immediately; for &lt;code&gt;spawn&lt;/code&gt;, polling happens once the task is &lt;em&gt;scheduled&lt;/em&gt; onto a
worker thread.&lt;/p&gt;

&lt;p&gt;However polling begins, if any of the interior futures produced a &lt;code&gt;NotReady&lt;/code&gt;
result, it can grind the whole task to a halt—the task may need to wait for
some event to occur before it can continue. In synchronous I/O, this is where a
thread would block. Tasks provide an equivalent to this model: the task &amp;ldquo;blocks&amp;rdquo;
by yielding back to its executor, &lt;strong&gt;after installing itself as a callback for
the events it&amp;rsquo;s waiting on&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Returning to the example of reading from a socket, on a &lt;code&gt;NotReady&lt;/code&gt; result the
task can be added to the event loop&amp;rsquo;s dispatch table, so that it will be woken
up when the socket becomes ready, at which point it will re-&lt;code&gt;poll&lt;/code&gt; its future.
Crucially, though, the task instance stays fixed for the lifetime of the future
it is executing—&lt;strong&gt;so no allocation is needed to create or install this callback&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Completing the analogy with threads, tasks provide a &lt;code&gt;park&lt;/code&gt;/&lt;code&gt;unpark&lt;/code&gt; API for
&amp;ldquo;blocking&amp;rdquo; and wakeup:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;/// Returns a handle to the current task to call unpark at a later date.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;park&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;/// Indicate that the task should attempt to poll its future in a timely fashion.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unpark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Blocking a future is a matter of using &lt;code&gt;park&lt;/code&gt; to get a handle to its task,
putting the resulting &lt;code&gt;Task&lt;/code&gt; in some wakeup queue for the event of interest, and
returning &lt;code&gt;NotReady&lt;/code&gt;. When the event of interest occurs, the &lt;code&gt;Task&lt;/code&gt; handle can
be used to wake back up the task, e.g. by rescheduling it for execution on a
thread pool. The precise mechanics of &lt;code&gt;park&lt;/code&gt;/&lt;code&gt;unpark&lt;/code&gt; vary by task executor.&lt;/p&gt;

&lt;p&gt;In a way, the task model is an instance of &amp;ldquo;green&amp;rdquo; (aka lightweight) threading:
we schedule a potentially large number of asynchronous tasks onto a much smaller
number of real OS threads, and most of those tasks are blocked on some event
most of the time. There&amp;rsquo;s an essential difference from Rust&amp;rsquo;s
&lt;a href=&quot;https://github.com/aturon/rfcs/blob/remove-runtime/active/0000-remove-runtime.md&quot;&gt;old green threading model&lt;/a&gt;,
however: &lt;strong&gt;tasks do not require their own stack&lt;/strong&gt;. In fact, all of the data
needed by a task is contained within its future. That means we can neatly
sidestep problems of dynamic stack growth and stack swapping, giving us truly
lightweight tasks without any runtime system implications.&lt;/p&gt;

&lt;p&gt;Perhaps surprisingly, &lt;strong&gt;the future within a task compiles down to a state
machine&lt;/strong&gt;, so that every time the task wakes up to continue polling, it
continues execution from the current state—working just like hand-rolled code
based on &lt;a href=&quot;http://github.com/carllerche/mio&quot;&gt;mio&lt;/a&gt;. This point is most easily seen
by example, so let&amp;rsquo;s revisit &lt;code&gt;join&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;example-join-in-the-demand-driven-model&quot;&gt;Example: &lt;code&gt;join&lt;/code&gt; in the demand-driven model&lt;/h3&gt;

&lt;p&gt;To implement the &lt;code&gt;join&lt;/code&gt; function, we&amp;rsquo;ll introduce a new concrete type, &lt;code&gt;Join&lt;/code&gt;,
that tracks the necessary state:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;BothRunning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BothRunning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstDone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SecondDone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// navigate the state machine&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first thing to notice is that &lt;code&gt;Join&lt;/code&gt; is an &lt;em&gt;enum&lt;/em&gt;, whose variants represent
states in the &amp;ldquo;join state machine&amp;rdquo;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BothRunning&lt;/code&gt;: the two underlying futures are both still executing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FirstDone&lt;/code&gt;: the first future has yielded a value, but the second is still executing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SecondDone&lt;/code&gt;: the second future has yielded a value, but the first is still executing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Done&lt;/code&gt;: both futures completed, and their values have been returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enums in Rust are represented without requiring any pointers or heap allocation;
instead, the size of the enum is the size of the largest variant. That&amp;rsquo;s exactly
what we want—that size represents the &amp;ldquo;high water mark&amp;rdquo; of this little state
machine.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;poll&lt;/code&gt; method here will attempt to make progress through the state machine
by &lt;code&gt;poll&lt;/code&gt;ing the underlying futures as appropriate.&lt;/p&gt;

&lt;p&gt;Recall that the aim of &lt;code&gt;join&lt;/code&gt; is to allow its two futures to proceed
concurrently, racing to finish. For example, the two futures might each
represent subtasks running in parallel on a thread pool. When those subtasks are
still running, &lt;code&gt;poll&lt;/code&gt;ing their futures will return &lt;code&gt;NotReady&lt;/code&gt;, effectively
&amp;ldquo;blocking&amp;rdquo; the &lt;code&gt;Join&lt;/code&gt; future, while stashing a handle to the ambient &lt;code&gt;Task&lt;/code&gt; for
waking it back up when they finish. The two subtasks can then race to &lt;em&gt;wake up&lt;/em&gt;
the &lt;code&gt;Task&lt;/code&gt;, but that&amp;rsquo;s fine: &lt;strong&gt;the &lt;code&gt;unpark&lt;/code&gt; method for waking a task is
threadsafe, and guarantees that the task will &lt;code&gt;poll&lt;/code&gt; its future at least once
after any &lt;code&gt;unpark&lt;/code&gt; call&lt;/strong&gt;. Thus, synchronization is handled once and for all at
the task level, without requiring combinators like &lt;code&gt;join&lt;/code&gt; to allocate or handle
synchronization themselves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You may have noticed that &lt;code&gt;poll&lt;/code&gt; takes &lt;code&gt;&amp;amp;mut self&lt;/code&gt;, which means that a given
future cannot be &lt;code&gt;poll&lt;/code&gt;ed concurrently—the future has unique access to its
contents while polling. The &lt;code&gt;unpark&lt;/code&gt; synchronization guarantees it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One final point. Combinators like &lt;code&gt;join&lt;/code&gt; embody &amp;ldquo;small&amp;rdquo; state machines, but
because some of those states involve additional futures, they allow additional
state machines to be &lt;em&gt;nested&lt;/em&gt;. In other words, &lt;code&gt;poll&lt;/code&gt;ing one of the underlying
futures for &lt;code&gt;join&lt;/code&gt; may involve stepping through &lt;em&gt;its&lt;/em&gt; state machine, before
taking steps in the &lt;code&gt;Join&lt;/code&gt; state machine. &lt;strong&gt;The fact that the use of the
&lt;code&gt;Future&lt;/code&gt; trait does not entail heap allocation or dynamic dispatch is key to
making this work efficiently.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In general, the &amp;ldquo;big&amp;rdquo; future being run by a task—made up of a large chain of
futures connected by combinators—embodies a &amp;ldquo;big&amp;rdquo; nested state machine in just
this way. Once more, Rust&amp;rsquo;s enum representation means that the space required is
the size of the state in the &amp;ldquo;big&amp;rdquo; machine with the largest footprint. The space
for this &amp;ldquo;big&amp;rdquo; future is allocated in &lt;em&gt;one shot&lt;/em&gt; by the task, either on the
stack (for the &lt;code&gt;wait&lt;/code&gt; executor) or on the heap (for &lt;code&gt;spawn&lt;/code&gt;). After all, the
data has to live &lt;em&gt;somewhere&lt;/em&gt;—but the key is to avoid constant allocations as
the state machine progresses, by instead making space for the entire thing up
front.&lt;/p&gt;

&lt;h2 id=&quot;futures-at-scale&quot;&gt;Futures at scale&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve seen the basics of demand-driven futures, but there are a number of
concerns about &lt;em&gt;robustness&lt;/em&gt; that we also want to cover. It turns out that these
concerns are addressed naturally by the demand-driven model. Let&amp;rsquo;s take a look
at a few of the most important.&lt;/p&gt;

&lt;h3 id=&quot;cancellation&quot;&gt;Cancellation&lt;/h3&gt;

&lt;p&gt;Futures are often used to represent substantial work that is running
concurrently. Sometimes it will become clear that this work is no longer
needed, perhaps because a timeout occurred, or the client closed a connection,
or the needed answer was found in some other way.&lt;/p&gt;

&lt;p&gt;In situations like these, you want some form of &lt;em&gt;cancellation&lt;/em&gt;: the ability to
tell a future to stop executing because you&amp;rsquo;re no longer interested in its
result.&lt;/p&gt;

&lt;p&gt;In the demand-driven model, cancellation largely &amp;ldquo;falls out&amp;rdquo;. All you have to do
is stop polling the future, instead &amp;ldquo;dropping&amp;rdquo; it (Rust&amp;rsquo;s term for destroying
the data). And doing so is usually a natural consequence of nested state
machines like &lt;code&gt;Join&lt;/code&gt;. Futures whose computation requires some special effort to
cancel (such as canceling an RPC call) can provide this logic as part of their
&lt;code&gt;Drop&lt;/code&gt; implementation.&lt;/p&gt;

&lt;h3 id=&quot;backpressure&quot;&gt;Backpressure&lt;/h3&gt;

&lt;p&gt;Another essential aspect of at-scale use of futures (and their close relative,
streams) is &lt;em&gt;backpressure&lt;/em&gt;: the ability of an overloaded component in one part
of a system to slow down input from other components. For example, if a server
has a backlog of database transactions for servicing outstanding requests, it
should slow down taking new requests.&lt;/p&gt;

&lt;p&gt;Like cancellation, backpressure largely falls out of our model for futures and
streams. That&amp;rsquo;s because tasks can be indefinitely &amp;ldquo;blocked&amp;rdquo; by a future/stream
returning &lt;code&gt;NotReady&lt;/code&gt;, and notified to continue polling at a later time. For the
example of database transactions, if enqueuing a transaction is itself
represented as a future, the database service can return &lt;code&gt;NotReady&lt;/code&gt; to slow down
requests. Often, such &lt;code&gt;NotReady&lt;/code&gt; results cascade backward through a system,
e.g. allowing backpressure to flow from the database service back to a
particular client connection then back to the overall connection manager. Such
cascades are a natural consequence of the demand-driven model.&lt;/p&gt;

&lt;h3 id=&quot;communicating-the-cause-of-a-wakeup&quot;&gt;Communicating the cause of a wakeup&lt;/h3&gt;

&lt;p&gt;If you&amp;rsquo;re familiar with interfaces like
&lt;a href=&quot;http://man7.org/linux/man-pages/man7/epoll.7.html&quot;&gt;epoll&lt;/a&gt;, you may have noticed
something missing from the &lt;code&gt;park&lt;/code&gt;/&lt;code&gt;unpark&lt;/code&gt; model: it provides no way for a task
to know &lt;em&gt;why&lt;/em&gt; it was woken up.&lt;/p&gt;

&lt;p&gt;That can be a problem for certain kinds futures that involve polling a large
number of other futures concurrently—you don&amp;rsquo;t want to have to re-poll
&lt;em&gt;everything&lt;/em&gt; to discover which sub-future is actually able to make progress.&lt;/p&gt;

&lt;p&gt;To deal with this problem, the library offers a kind of &amp;ldquo;epoll for everyone&amp;rdquo;:
the ability to associate &amp;ldquo;unpark events&amp;rdquo; with a given &lt;code&gt;Task&lt;/code&gt; handle. That is,
there may be various handles to the same task floating around, all of which can
be used to wake the task up, but each of which carries different unpark events.
When woken, the future within the task can inspect these unpark events to
determine what happened. See
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/task/fn.with_unpark_event.html&quot;&gt;the docs&lt;/a&gt;
for more detail.&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve now seen the core design principles behind the Rust futures and streams
library. To recap, it boils down to a few key ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Encapsulate running futures into &lt;em&gt;tasks&lt;/em&gt;, which serve as a single, permanent
&amp;ldquo;callback&amp;rdquo; for the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement futures in a demand-driven, rather than callback-oriented, style.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Rust&amp;rsquo;s trait system to allow composed futures to flatten into big state
machines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these ideas yield a robust, ergonomic, zero cost futures library.&lt;/p&gt;

&lt;p&gt;As I mentioned at the outset of the post, we&amp;rsquo;re very actively working on the
layers above the basic futures library—layers that incorporate particular I/O
models (like &lt;a href=&quot;http://github.com/carllerche/mio&quot;&gt;mio&lt;/a&gt;) and also provide
yet-higher-level tools for building servers. These layers are part of the Tokio
project, and you can read more about the overall vision in
&lt;a href=&quot;http://aturon.github.io/blog/2016/08/26/tokio/&quot;&gt;my earlier post&lt;/a&gt;. As those APIs
stabilize, expect to see more posts describing them!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Expanding the Tokio project</title>
   <link href="http://aturon.github.io/blog/2016/08/26/tokio/"/>
   <updated>2016-08-26T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2016/08/26/tokio</id>
   <content type="html">&lt;p&gt;If you&amp;rsquo;ve been following Rust in the last month, you&amp;rsquo;ve probably seen the
announcements of the &lt;a href=&quot;http://aturon.github.io/blog/2016/08/11/futures/&quot;&gt;Futures&lt;/a&gt; library and the &lt;a href=&quot;https://medium.com/@carllerche/announcing-tokio-df6bb4ddb34&quot;&gt;Tokio&lt;/a&gt; framework that sits on
top of it. There&amp;rsquo;s been some confusion about how these projects fit together,
and what the overall story is shaping up to be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today, we&amp;rsquo;re happy to announce the formation of the Tokio Core Team, as well
as an overall plan for the two projects and how they fit together&lt;/strong&gt;. The team
consists of Carl Lerche, Alex Crichton, and myself; more on that below.&lt;/p&gt;

&lt;h2 id=&quot;an-early-vision-of-the-i-o-stack&quot;&gt;An early vision of the I/O stack&lt;/h2&gt;

&lt;p&gt;There are three primary levels of abstraction in Tokio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the highest level is a &lt;em&gt;service&lt;/em&gt;, which is where you write a server
application. Following the &lt;a href=&quot;http://finagle.github.io/&quot;&gt;Finagle&lt;/a&gt; model, a service is a simple thing: it&amp;rsquo;s
a function from requests to &lt;em&gt;futures&lt;/em&gt; of responses. This simple model is
incredibly powerful: it separates the implementation of request processing
from the implementation of the underlying protocol, and makes it possible to
factor out an ecosystem of &lt;em&gt;middleware&lt;/em&gt;. All of this seamlessly support async
I/O via futures. Middleware runs the gamut from connection pooling to
retry/timeout logic to logging to load balancing &amp;ndash; all of which can be
written independently from any particular service or protocol. Read
&lt;a href=&quot;https://monkey.org/%7Emarius/funsrv.pdf&quot;&gt;Your Server as a Function&lt;/a&gt; for the inspiration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/tokio-rs/tokio-service&quot;&gt;tokio-service&lt;/a&gt; crate provides core trait definitions for
  services. Servers that can process particular request/response types (like
  HTTP) are offered as standalone crates. &lt;strong&gt;Building an http server is just a
  matter of writing a function from http requests to futures of http
  responses.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the middle are &lt;em&gt;protocols&lt;/em&gt;, like HTTP or Mux. Here, too, there is a lot of
complexity worth factoring out, both at the transport layer and in the
protocol &amp;ldquo;dispatch&amp;rdquo; layer. &lt;strong&gt;The &lt;a href=&quot;https://github.com/tokio-rs/tokio-proto&quot;&gt;tokio-proto&lt;/a&gt; crate provides re-usable
components for building new protocol implementations&lt;/strong&gt;. We expect for there to
be a similar kind of &amp;ldquo;middleware&amp;rdquo; ecosystem at these lower levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the lowest level is the &lt;em&gt;event loop&lt;/em&gt;, which is where we bridge the OS&amp;rsquo;s I/O
facilities into the world of futures. &lt;strong&gt;The &lt;a href=&quot;https://github.com/tokio-rs/tokio-core&quot;&gt;tokio-core&lt;/a&gt; crate provides a
generic event loop for doing async I/O with futures&lt;/strong&gt;. If you want complete
control, that&amp;rsquo;s the entry point for you; it&amp;rsquo;s particularly useful for cases
that don&amp;rsquo;t fit so nicely into the service model, such as proxy servers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In short, we want the Tokio project to be a &amp;ldquo;one stop shop&amp;rdquo; for doing
futures-based I/O&lt;/strong&gt;, whether at the highest level of prebuilt protocols, or
the lowest level of the core event loop.&lt;/p&gt;

&lt;p&gt;In our view, the lowest layers should strive to be zero cost and fully general,
allowing them to be used in a large number of contexts. As you go up the stack,
getting closer to an actual application, things tend to get more specific and
opinionated, and may impose some cost. &lt;a href=&quot;http://aturon.github.io/blog/2016/08/11/futures/&quot;&gt;Futures&lt;/a&gt; themselves are a zero-cost and
very general abstraction in Rust, and the &lt;a href=&quot;https://github.com/tokio-rs/tokio-core&quot;&gt;tokio-core&lt;/a&gt; crate imposes very little
cost. Particular protocol implementations and middleware, on the other hand, can
be more opinionated.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll have a lot more to say about all of these layers (and the ones beneath
them, like futures) in the coming weeks on our various blogs. Stay tuned!&lt;/p&gt;

&lt;h2 id=&quot;a-note-on-project-management&quot;&gt;A note on project management&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;re following a Rust-like model, starting with a core team that reaches major
decisions through a consensus process. At the moment, this process is fairly
informal: it plays out on the issue tracker, PRs, and gitter channels. But as
the library begins to mature, we plan to move toward an RFC-like process for
major changes. We are eager for the Tokio project to truly be a Rust community
project. It&amp;rsquo;s going to have a lot of stakeholders, and we want to make sure
those stakeholders have a voice just as we do in the Rust project itself.&lt;/p&gt;

&lt;p&gt;As for the core futures library, it remains separate from the Tokio project, in
part because we imagine it heading toward ownership by the rust-lang org in the
relatively near future. (That&amp;rsquo;s a possible eventual path for Tokio as well, but
the road will be much longer.)&lt;/p&gt;

&lt;h2 id=&quot;jumping-in&quot;&gt;Jumping in&lt;/h2&gt;

&lt;p&gt;Tokio is an ambitious project, and it&amp;rsquo;s going to take a strong community to
really get it off the ground.  Many from the Rust community have already jumped
in to contribute, even in these extremely early days; that&amp;rsquo;s helped us get some
of our early-stage integrations going, including &lt;a href=&quot;https://github.com/tokio-rs/tokio-curl&quot;&gt;curl&lt;/a&gt;, &lt;a href=&quot;https://github.com/tokio-rs/tokio-tls&quot;&gt;tls&lt;/a&gt; and
&lt;a href=&quot;https://github.com/tokio-rs/tokio-redis&quot;&gt;redis&lt;/a&gt;. We&amp;rsquo;re also working with Sean McArthur to get a Tokio-integrated &lt;a href=&quot;https://github.com/hyperium/hyper/&quot;&gt;Hyper&lt;/a&gt;
off the ground. If you&amp;rsquo;re interested in any of this, any other integrations, or
the core libraries, we&amp;rsquo;d love to &lt;a href=&quot;https://gitter.im/tokio-rs/tokio&quot;&gt;hear from you&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re coming to RustConf, we&amp;rsquo;ll see you there, either at the
&lt;a href=&quot;https://tokiohacknight.splashthat.com/&quot;&gt;Tokio hack night&lt;/a&gt; or at the talk about futures at RustConf itself. Come say
hello, and join in the fun!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Zero-cost futures in Rust</title>
   <link href="http://aturon.github.io/blog/2016/08/11/futures/"/>
   <updated>2016-08-11T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2016/08/11/futures</id>
   <content type="html">&lt;p&gt;One of the key gaps in Rust&amp;rsquo;s ecosystem has been a strong story for fast and
productive &lt;em&gt;asynchronous I/O&lt;/em&gt;. We have solid foundations, like the
&lt;a href=&quot;http://github.com/carllerche/mio&quot;&gt;mio&lt;/a&gt; library, but they&amp;rsquo;re very low level: you
have to wire up state machines and juggle callbacks directly.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve wanted something higher level, with better ergonomics, but also better
&lt;em&gt;composability&lt;/em&gt;, supporting an ecosystem of asynchronous abstractions that all
work together. This story might sound familiar: it&amp;rsquo;s the same goal that&amp;rsquo;s led to
the introduction of &lt;em&gt;futures&lt;/em&gt; (aka promises) in
&lt;a href=&quot;https://en.wikipedia.org/wiki/Futures_and_promises#List_of_implementations&quot;&gt;many languages&lt;/a&gt;,
with some supporting &lt;em&gt;async/await&lt;/em&gt; sugar on top.&lt;/p&gt;

&lt;p&gt;A major tenet of Rust is the ability to build
&lt;a href=&quot;https://blog.rust-lang.org/2015/05/11/traits.html&quot;&gt;zero-cost abstractions&lt;/a&gt;, and
that leads to one additional goal for our async I/O story: ideally, an
abstraction like futures should compile down to something equivalent to the
state-machine-and-callback-juggling code we&amp;rsquo;re writing today (with no additional
runtime overhead).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over the past couple of months, Alex Crichton and I have developed a
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs&quot;&gt;&lt;em&gt;zero-cost futures library&lt;/em&gt;&lt;/a&gt; for
Rust, one that we believe achieves these goals&lt;/strong&gt;. (Thanks to Carl Lerche, Yehuda
Katz, and Nicholas Matsakis for insights along the way.)&lt;/p&gt;

&lt;p&gt;Today, we&amp;rsquo;re excited to kick off a blog series about the new library. This post
gives the highlights, a few key ideas, and some preliminary
benchmarks. Follow-up posts will showcase how Rust&amp;rsquo;s features come together in
the design of this zero-cost abstraction. And there&amp;rsquo;s already a
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/TUTORIAL.md&quot;&gt;tutorial&lt;/a&gt;
to get you going.&lt;/p&gt;

&lt;h2 id=&quot;why-async-i-o&quot;&gt;Why async I/O?&lt;/h2&gt;

&lt;p&gt;Before delving into futures, it&amp;rsquo;ll be helpful to talk a bit about the past.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start with a simple piece of I/O you might want to perform: reading a
certain number of bytes from a socket. Rust provides a function,
&lt;a href=&quot;https://static.rust-lang.org/doc/master/std/io/trait.Read.html#method.read_exact&quot;&gt;&lt;code&gt;read_exact&lt;/code&gt;&lt;/a&gt;,
to do this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// reads 256 bytes into `my_vec`&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_exact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quick quiz: what happens if we haven&amp;rsquo;t received enough bytes from the socket yet?&lt;/p&gt;

&lt;p&gt;In today&amp;rsquo;s Rust, the answer is that the current thread blocks, sleeping until
more bytes are available. But that wasn&amp;rsquo;t always the case.&lt;/p&gt;

&lt;p&gt;Early on, Rust had a &amp;ldquo;green threading&amp;rdquo; model, not unlike Go&amp;rsquo;s. You could spin up
a large number of lightweight &lt;em&gt;tasks&lt;/em&gt;, which were then scheduled onto real OS
threads (sometimes called &amp;ldquo;M:N threading&amp;rdquo;). In the green threading model, a
function like &lt;code&gt;read_exact&lt;/code&gt; blocks the current &lt;em&gt;task&lt;/em&gt;, but not the
underlying OS thread; instead, the task scheduler switches to another
task. That&amp;rsquo;s great, because you can scale up to a very large number of tasks,
most of which are blocked, while using only a small number of OS threads.&lt;/p&gt;

&lt;p&gt;The problem is that green threads were
&lt;a href=&quot;https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html&quot;&gt;at odds&lt;/a&gt;
with Rust&amp;rsquo;s ambitions to be a true C replacement, with no imposed runtime system
or FFI costs: we were unable to find an implementation strategy that didn&amp;rsquo;t
impose serious global costs. You can read more
&lt;a href=&quot;https://github.com/aturon/rfcs/blob/remove-runtime/active/0000-remove-runtime.md&quot;&gt;in the RFC that removed green threading&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So if we want to handle a large number of simultaneous connections, many of
which are waiting for I/O, but we want to keep the number of OS threads to a
minimum, what else can we do?&lt;/p&gt;

&lt;p&gt;Asynchronous I/O is the answer &amp;ndash; and in fact, it&amp;rsquo;s used to implement green
threading as well.&lt;/p&gt;

&lt;p&gt;In a nutshell, with async I/O you can &lt;em&gt;attempt&lt;/em&gt; an I/O operation without
blocking. If it can&amp;rsquo;t complete immediately, you can retry at some later
point. To make this work, the OS provides tools like
&lt;a href=&quot;https://en.wikipedia.org/wiki/Epoll&quot;&gt;epoll&lt;/a&gt;, allowing you to query which of a
large set of I/O objects are &lt;em&gt;ready&lt;/em&gt; for reading or writing &amp;ndash; which is
essentially the API that &lt;a href=&quot;http://github.com/carllerche/mio&quot;&gt;mio&lt;/a&gt; provides.&lt;/p&gt;

&lt;p&gt;The problem is that there&amp;rsquo;s a lot of painful work tracking all of the I/O events
you&amp;rsquo;re interested in, and dispatching those to the right callbacks (not to
mention programming in a purely callback-driven way). That&amp;rsquo;s one of the key
problems that futures solve.&lt;/p&gt;

&lt;h2 id=&quot;futures&quot;&gt;Futures&lt;/h2&gt;

&lt;p&gt;So what &lt;em&gt;is&lt;/em&gt; a future?&lt;/p&gt;

&lt;p&gt;In essence, a future represents a value that might not be ready yet. Usually,
the future becomes &lt;em&gt;complete&lt;/em&gt; (the value is ready) due to an event happening
somewhere else. While we&amp;rsquo;ve been looking at this from the perspective of basic
I/O, you can use a future to represent a wide range of events, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A database query&lt;/strong&gt; that&amp;rsquo;s executing in a thread pool. When the query finishes,
the future is completed, and its value is the result of the query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An RPC invocation&lt;/strong&gt; to a server. When the server replies, the future is
completed, and its value is the server&amp;rsquo;s response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A timeout&lt;/strong&gt;. When time is up, the future is completed, and its value is just
&lt;code&gt;()&lt;/code&gt; (the &amp;ldquo;unit&amp;rdquo; value in Rust).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A long-running CPU-intensive task&lt;/strong&gt;, running on a thread pool. When the task
finishes, the future is completed, and its value is the return value of the
task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reading bytes from a socket&lt;/strong&gt;. When the bytes are ready, the future is completed
&amp;ndash; and depending on the buffering strategy, the bytes might be returned
directly, or written as a side-effect into some existing buffer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on. The point is that futures are applicable to asynchronous
events of all shapes and sizes. The asynchrony is reflected in the fact that you
get a &lt;em&gt;future&lt;/em&gt; right away, without blocking, even though the &lt;em&gt;value&lt;/em&gt; the future
represents will become ready only at some unknown time in the&amp;hellip; future.&lt;/p&gt;

&lt;p&gt;In Rust, we represent futures as a
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html&quot;&gt;trait&lt;/a&gt; (i.e., an
interface), roughly:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ... lots more elided ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;Item&lt;/code&gt; type says what kind of value the future will yield once it&amp;rsquo;s complete.&lt;/p&gt;

&lt;p&gt;Going back to our earlier list of examples, we can write several functions
producing different futures (using
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1522&quot;&gt;&lt;code&gt;impl&lt;/code&gt; syntax&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Lookup a row in a table by the given id, yielding the row when finished&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;: &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Makes an RPC call that will yield an i32&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;id_rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RpcServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Writes an entire string to a TcpStream, yielding back the stream when finished&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;TcpStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TcpStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of these functions will return their future &lt;em&gt;immediately&lt;/em&gt;, whether or not
the event the future represents is complete; the functions are
non-blocking.&lt;/p&gt;

&lt;p&gt;Things really start getting interesting with futures when you combine
them. There are endless ways of doing so, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html#method.and_then&quot;&gt;&lt;strong&gt;Sequential composition&lt;/strong&gt;&lt;/a&gt;:
&lt;code&gt;f.and_then(|val| some_new_future(val))&lt;/code&gt;. Gives you a future that executes the
future &lt;code&gt;f&lt;/code&gt;, takes the &lt;code&gt;val&lt;/code&gt; it produces to build another future
&lt;code&gt;some_new_future(val)&lt;/code&gt;, and then executes that future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html#method.map&quot;&gt;&lt;strong&gt;Mapping&lt;/strong&gt;&lt;/a&gt;:
&lt;code&gt;f.map(|val| some_new_value(val))&lt;/code&gt;. Gives you a future that
executes the future &lt;code&gt;f&lt;/code&gt; and yields the result of &lt;code&gt;some_new_value(val)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html#method.join&quot;&gt;&lt;strong&gt;Joining&lt;/strong&gt;&lt;/a&gt;:
&lt;code&gt;f.join(g)&lt;/code&gt;. Gives you a future that executes the futures &lt;code&gt;f&lt;/code&gt; and
&lt;code&gt;g&lt;/code&gt; in parallel, and completes when &lt;em&gt;both&lt;/em&gt; of them are complete, returning
both of their values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/trait.Future.html#method.select&quot;&gt;&lt;strong&gt;Selecting&lt;/strong&gt;&lt;/a&gt;:
&lt;code&gt;f.select(g)&lt;/code&gt;. Gives you a future that executes the futures &lt;code&gt;f&lt;/code&gt;
and &lt;code&gt;g&lt;/code&gt; in parallel, and completes when &lt;em&gt;one of&lt;/em&gt; them is complete, returning
its value and the other future. (Want to add a timeout to any future? Just do
a &lt;code&gt;select&lt;/code&gt; of that future and a timeout future!)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a simple example using the futures above, we might write something like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id_rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/futures-minihttp/techempower2/src/main.rs&quot;&gt;this code&lt;/a&gt;
for a more fleshed out example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is non-blocking code that moves through several states: first we do an RPC
call to acquire an ID; then we look up the corresponding row; then we encode it
to json; then we write it to a socket. &lt;strong&gt;Under the hood, this code will compile
down to an actual state machine which progresses via callbacks (with no
overhead)&lt;/strong&gt;, but we get to write it in a style that&amp;rsquo;s not far from simple
&lt;em&gt;blocking&lt;/em&gt; code. (Rustaceans will note that this story is very similar to
&lt;code&gt;Iterator&lt;/code&gt; in the standard library.)  Ergonomic, high-level code that compiles
to state-machine-and-callbacks: that&amp;rsquo;s what we were after!&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also worth considering that each of the futures being used here might come
from a different library. The futures abstraction allows them to all be combined
seamlessly together.&lt;/p&gt;

&lt;h2 id=&quot;streams&quot;&gt;Streams&lt;/h2&gt;

&lt;p&gt;But wait &amp;ndash; there&amp;rsquo;s more! As you keep pushing on the future &amp;ldquo;combinators&amp;rdquo;,
you&amp;rsquo;re able to not just reach parity with simple blocking code, but to do things
that can be tricky or painful to write otherwise. To see an example, we&amp;rsquo;ll need one
more concept: streams.&lt;/p&gt;

&lt;p&gt;Futures are all about a &lt;em&gt;single&lt;/em&gt; value that will eventually be produced, but
many event sources naturally produce a &lt;em&gt;stream&lt;/em&gt; of values over time. For
example, incoming TCP connections or incoming requests on a socket are both
naturally streams.&lt;/p&gt;

&lt;p&gt;The futures library includes a
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/stream/trait.Stream.html&quot;&gt;&lt;code&gt;Stream&lt;/code&gt; trait&lt;/a&gt;
as well, which is very similar to futures, but set up to produce a sequence of
values over time. It has a set of combinators, some of which work with
futures. For example, if &lt;code&gt;s&lt;/code&gt; is a stream, you can write:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some_future&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code will give you a new stream that works by first pulling a value &lt;code&gt;val&lt;/code&gt;
from &lt;code&gt;s&lt;/code&gt;, then computing &lt;code&gt;some_future(val)&lt;/code&gt; from it, then executing that future
and yielding its value &amp;ndash; then doing it all over again to produce the next value
in the stream.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see a real example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Given an `input` I/O object create a stream of requests&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseStream&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// For each request, run our service&amp;#39;s `process` function to handle the request&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// and generate a response&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create a new future that&amp;#39;ll write out each response to an `output` I/O object&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we&amp;rsquo;ve written the core of a simple server by operating on streams. It&amp;rsquo;s
not rocket science, but it is a bit exciting to be manipulating values like
&lt;code&gt;responses&lt;/code&gt; that represent the entirety of what the server is producing.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s make things more interesting. Assume the protocol is pipelined, i.e., that
the client can send additional requests on the socket before hearing back from
the ones being processed. We want to actually process the requests sequentially,
but there&amp;rsquo;s an opportunity for some parallelism here: we could read &lt;em&gt;and parse&lt;/em&gt;
a few requests ahead, while the current request is being processed. Doing so is
as easy as inserting one more combinator in the right place:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseStream&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;--&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responsesm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures/stream/trait.Stream.html#method.buffered&quot;&gt;&lt;code&gt;buffered&lt;/code&gt; combinator&lt;/a&gt;
takes a stream of &lt;em&gt;futures&lt;/em&gt; and buffers it by some fixed amount. Buffering the
stream means that it will eagerly pull out more than the requested number of
items, and stash the resulting futures in a buffer for later processing. In this
case, that means that we will read and parse up to 32 extra requests in parallel,
while running &lt;code&gt;process&lt;/code&gt; on the current one.&lt;/p&gt;

&lt;p&gt;These are relatively simple examples of using futures and streams, but hopefully
they convey some sense of how the combinators can empower you to do very
high-level async programming.&lt;/p&gt;

&lt;h2 id=&quot;zero-cost&quot;&gt;Zero cost?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve claimed a few times that our futures library provides a zero-cost
abstraction, in that it compiles to something very close to the state machine
code you&amp;rsquo;d write by hand. To make that a bit more concrete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;None of the future combinators impose any allocation. When we do things like
chain uses of &lt;code&gt;and_then&lt;/code&gt;, not only are we not allocating, we are in fact
building up a big &lt;code&gt;enum&lt;/code&gt; that represents the state machine. (There is one
allocation needed per &amp;ldquo;task&amp;rdquo;, which usually works out to one per connection.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When an event arrives, only one dynamic dispatch is required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are essentially no imposed synchronization costs; if you want to
associate data that lives on your event loop and access it in a
single-threaded way from futures, we give you the tools to do so.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on. Later blog posts will get into the details of these claims and show
how we leverage Rust to get to zero cost.&lt;/p&gt;

&lt;p&gt;But the proof is in the pudding. We wrote a simple HTTP server framework,
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/tree/master/futures-minihttp&quot;&gt;minihttp&lt;/a&gt;,
which supports pipelining and TLS. &lt;strong&gt;This server uses futures at every level of
its implementation, from reading bytes off a socket to processing streams of
requests&lt;/strong&gt;. Besides being a pleasant way to write the server, this provides a
pretty strong stress test for the overhead of the futures abstraction.&lt;/p&gt;

&lt;p&gt;To get a basic assessment of that overhead, we then implemented the
&lt;a href=&quot;https://www.techempower.com/benchmarks/#section=data-r12&amp;hw=peak&amp;test=plaintext&quot;&gt;TechEmpower &amp;ldquo;plaintext&amp;rdquo; benchmark&lt;/a&gt;. This
microbenchmark tests a &amp;ldquo;hello world&amp;rdquo; HTTP server by throwing a huge number of
concurrent and pipelined requests at it. Since the &amp;ldquo;work&amp;rdquo; that the server is
doing to process the requests is trivial, the performance is largely a
reflection of the basic overhead of the server framework (and in our case, the
futures framework).&lt;/p&gt;

&lt;p&gt;TechEmpower is used to compare a very large number of web frameworks across many
different languages. We
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/futures-minihttp/README.md&quot;&gt;compared&lt;/a&gt;
minihttp to a few of the top contenders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Java/rapidoid&quot;&gt;rapidoid&lt;/a&gt;,
a Java framework, which was the top performer in the last round of official benchmarks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Go/go-std&quot;&gt;Go&lt;/a&gt;,
an implementation that uses Go&amp;rsquo;s standard library&amp;rsquo;s HTTP support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Go/fasthttp&quot;&gt;fasthttp&lt;/a&gt;,
a competitor to Go&amp;rsquo;s standard library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/JavaScript/nodejs&quot;&gt;node.js&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the results, in number of &amp;ldquo;Hello world!&amp;quot;s served per second on an 8
core Linux machine:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/public/bench-pipelined.png&quot;&gt;&lt;/p&gt;

&lt;p&gt;It seems safe to say that futures are not imposing significant overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: to provide some extra evidence, we&amp;rsquo;ve
  &lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/futures-minihttp/README.md&quot;&gt;added a comparison&lt;/a&gt;
  of minihttp against a directly-coded state machine version in Rust (see &amp;quot;raw
  mio&amp;rdquo; in the link). The two are within 0.3% of each other.&lt;/p&gt;

&lt;h2 id=&quot;the-future&quot;&gt;The future&lt;/h2&gt;

&lt;p&gt;Thus concludes our whirlwind introduction to zero-cost futures in Rust. We&amp;rsquo;ll
see more details about the design in the posts to come.&lt;/p&gt;

&lt;p&gt;At this point, the library is quite usable, and pretty thoroughly documented; it
comes with a
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/TUTORIAL.md&quot;&gt;tutorial&lt;/a&gt;
and plenty of examples, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a simple &lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/futures-mio/src/bin/echo.rs&quot;&gt;TCP echo server&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;an efficient
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/blob/master/futures-socks5/src/main.rs&quot;&gt;SOCKSv5 proxy server&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;minihttp&lt;/code&gt;, a highly-efficient
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/tree/master/futures-minihttp&quot;&gt;HTTP server&lt;/a&gt;
that supports TLS and uses
&lt;a href=&quot;https://crates.io/crates/httparse&quot;&gt;Hyper&amp;rsquo;s parser&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;an example
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/tree/master/futures-minihttp/tls-example&quot;&gt;use of minihttp&lt;/a&gt;
for TLS connections,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as well as a variety of integrations, e.g. a futures-based interface to
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures_curl&quot;&gt;curl&lt;/a&gt;. We&amp;rsquo;re actively working
with several people in the Rust community to integrate with their work; if
you&amp;rsquo;re interested, please reach out to Alex or myself!&lt;/p&gt;

&lt;p&gt;If you want to do low-level I/O programming with futures, you can use
&lt;a href=&quot;http://alexcrichton.com/futures-rs/futures_mio&quot;&gt;futures-mio&lt;/a&gt; to do so on top of
mio. We think this is an exciting direction to take async I/O programming in
general in Rust, and follow up posts will go into more detail on the mechanics.&lt;/p&gt;

&lt;p&gt;Alternatively, if you just want to speak HTTP, you can work on top of
&lt;a href=&quot;https://github.com/alexcrichton/futures-rs/tree/master/futures-minihttp&quot;&gt;minihttp&lt;/a&gt;
by providing a &lt;em&gt;service&lt;/em&gt;: a function that takes an HTTP request, and returns a
&lt;em&gt;future&lt;/em&gt; of an HTTP response. This kind of RPC/service abstraction opens the
door to writing a lot of reusable &amp;ldquo;middleware&amp;rdquo; for servers, and has gotten a lot
of traction in Twitter&amp;rsquo;s &lt;a href=&quot;https://twitter.github.io/finagle/&quot;&gt;Finagle&lt;/a&gt; library
for Scala; it&amp;rsquo;s also being used in Facebook&amp;rsquo;s
&lt;a href=&quot;https://github.com/facebook/wangle&quot;&gt;Wangle&lt;/a&gt; library. In the Rust world, there&amp;rsquo;s
already a library called
&lt;a href=&quot;https://medium.com/@carllerche/announcing-tokio-df6bb4ddb34#.g9ugbqg71&quot;&gt;Tokio&lt;/a&gt;
in the works that builds a general service abstraction on our futures library,
and could serve a role similar to Finagle.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s an enormous amount of work ahead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First off, we&amp;rsquo;re eager to hear feedback on the core future and stream
abstractions, and there are some specific design details for some combinators
we&amp;rsquo;re unsure about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, while we&amp;rsquo;ve built a number of future abstractions around basic I/O
concepts, there&amp;rsquo;s definitely more room to explore, and we&amp;rsquo;d appreciate help
exploring it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More broadly, there are endless futures &amp;ldquo;bindings&amp;rdquo; for various libraries (both
in C and in Rust) to write; if you&amp;rsquo;ve got a library you&amp;rsquo;d like futures bindings
for, we&amp;rsquo;re excited to help!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thinking more long term, an obvious eventual step would be to explore
&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; notation on top of futures, perhaps in the same way as proposed
in &lt;a href=&quot;https://tc39.github.io/ecmascript-asyncawait/&quot;&gt;Javascript&lt;/a&gt;. But we want to
gain more experience using futures directly as a library, first, before
considering such a step.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whatever your interests might be, we&amp;rsquo;d love to hear from you &amp;ndash; we&amp;rsquo;re &lt;code&gt;acrichto&lt;/code&gt;
and &lt;code&gt;aturon&lt;/code&gt; on Rust&amp;rsquo;s
&lt;a href=&quot;https://www.rust-lang.org/en-US/community.html&quot;&gt;IRC channels&lt;/a&gt;. Come say hi!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Rust Platform</title>
   <link href="http://aturon.github.io/blog/2016/07/27/rust-platform/"/>
   <updated>2016-07-27T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2016/07/27/rust-platform</id>
   <content type="html">&lt;p&gt;A programming language is much more than its compiler and standard library. It&amp;rsquo;s
a community. Tools. Documentation. An ecosystem. All of these elements affect
how a language feels, its productivity, and its applicability.&lt;/p&gt;

&lt;p&gt;Rust is a very young language &amp;ndash;
&lt;a href=&quot;https://blog.rust-lang.org/2016/05/16/rust-at-one-year.html&quot;&gt;barely a year past 1.0&lt;/a&gt;
&amp;ndash; and building out and maturing the full complement of ecosystem and tooling is
crucial to its success. That building is happening, but sometimes at an
explosive rate that makes it hard to track what&amp;rsquo;s going on, to find the right
library for a task, or to choose between several options that show up on a
&lt;a href=&quot;https://crates.io/&quot;&gt;crates.io&lt;/a&gt; search. It can be hard to coordinate versions of
important libraries that all work well together. We also lack tools to push toward
maturity in a community-wide way, or to incentivize work toward a common
quality standard.&lt;/p&gt;

&lt;p&gt;On the other hand, the core parts of Rust get a &lt;em&gt;tremendous&lt;/em&gt; amount of
focus. But we have tended to be pretty conservative in what is considered
&amp;ldquo;core&amp;rdquo;: today, essentially it&amp;rsquo;s &lt;code&gt;rustc&lt;/code&gt;, &lt;code&gt;cargo&lt;/code&gt;, &lt;code&gt;libstd&lt;/code&gt;/&lt;code&gt;libcore&lt;/code&gt;, and a
couple of other crates. The standard library also takes a deliberately
minimalistic approach, to avoid the well-known pitfalls of large standard
libraries that are versioned with the compiler and quickly stagnate, while the
real action happens in the broader ecosystem (&amp;ldquo;&lt;code&gt;std&lt;/code&gt; is where code goes to die&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short, there are batteries out there, but we&amp;rsquo;re failing to include them&lt;/strong&gt; (or
even tell you where to shop for them).&lt;/p&gt;

&lt;p&gt;Can we provide a &amp;ldquo;batteries included&amp;rdquo; experience for Rust that doesn&amp;rsquo;t lead to
stagnation, one that instead works directly with and through the ecosystem,
focusing attention, driving compatibility, and reaching for maturity?&lt;/p&gt;

&lt;p&gt;I think we can, and I want to lay out a plan that&amp;rsquo;s emerged after discussion
with many on the core and subteams.&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-rust-platform&quot;&gt;What is &amp;ldquo;The Rust Platform&amp;rdquo;?&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I want to say right off the bat that the ideas here draw significant inspiration
from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Haskell_Platform&quot;&gt;Haskell Platform&lt;/a&gt;,
which is working toward similar goals for Haskell.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The basic idea of the Rust Platform is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Distribute a wide range of artifacts in a single &amp;ldquo;Rust Platform Package&amp;rdquo;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The compiler, Cargo, rust-lang crates (e.g. &lt;code&gt;std&lt;/code&gt;, &lt;code&gt;libc&lt;/code&gt;), docs&lt;/li&gt;
&lt;li&gt;Libraries drawn from the wider ecosystem (going beyond rust-lang crates)&lt;/li&gt;
&lt;li&gt;Tools drawn from the wider ecosystem (e.g. &lt;code&gt;rustfmt&lt;/code&gt;,
&lt;a href=&quot;https://blog.rust-lang.org/2016/05/13/rustup.html&quot;&gt;NDKs&lt;/a&gt;, editor plugins,
lints)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2016/05/13/rustup.html&quot;&gt;Cross-compilation targets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Periodically curate the ecosystem, determining consensus choices for what
artifacts, and at what versions, to distribute.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, &lt;a href=&quot;https://blog.rust-lang.org/2016/05/13/rustup.html&quot;&gt;rustup&lt;/a&gt; is
intended to be the primary mechanism for distribution; it&amp;rsquo;s expected that it
will soon replace the guts of our official installers, becoming the primary way
to acquire Rust and related artifacts.&lt;/p&gt;

&lt;p&gt;As you&amp;rsquo;d expect, the real meat here is in the details. It&amp;rsquo;s probably unclear
what it even means to &amp;ldquo;distribute&amp;rdquo; a library, given Cargo&amp;rsquo;s approach to
dependency management. Read on!&lt;/p&gt;

&lt;h2 id=&quot;library-mechanics&quot;&gt;Library mechanics&lt;/h2&gt;

&lt;h3 id=&quot;cargo-metapackages&quot;&gt;Cargo metapackages&lt;/h3&gt;

&lt;p&gt;The most novel part of the proposal is the idea of curating and distributing
crates. &lt;strong&gt;The goal is to provide an experience that feels much like &lt;code&gt;std&lt;/code&gt;, but
provides much greater agility, avoiding the typical pitfalls of large standard
libraries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key to making sense of library &amp;ldquo;packaging&amp;rdquo; for Rust is the idea of a
&lt;em&gt;metapackage&lt;/em&gt; for Cargo, which aggregates together a number of library
dependencies as a single name and version. Concretely, this would look like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rust-platform&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2.7&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which is effectively then shorthand for something like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.2&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2.0&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.1&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;serde&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;3.0&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meta packages give technical meaning to curation: we can provide assurance that
the crates within a metapackage will all play well together, at the versions
stated.&lt;/p&gt;

&lt;p&gt;With the platform metapackage, we can talk coherently about the &amp;ldquo;Rust Platform
2.0 Series&amp;rdquo; as a chapter in Rust&amp;rsquo;s evolution. After all, core libraries play a
major role in shaping the idioms of a language at a given point of time.
Evolution in these core libraries can have an effect on the experience of the
language rivaling changes to the language itself.&lt;/p&gt;

&lt;p&gt;With those basics out of the way, let&amp;rsquo;s look at the ways that the platform is,
and is not, like a bigger &lt;code&gt;std&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;stability-without-stagnation&quot;&gt;Stability without stagnation&lt;/h3&gt;

&lt;p&gt;The fact that &lt;code&gt;std&lt;/code&gt; is effectively coupled with &lt;code&gt;rustc&lt;/code&gt; means that upgrading the
compiler entails upgrading the standard library, like it or not. That means that
the two need to provide essentially the same
&lt;a href=&quot;http://blog.rust-lang.org/2014/10/30/Stability.html&quot;&gt;backwards-compatibility guarantees&lt;/a&gt;. TL;DR,
it&amp;rsquo;s simply not feasible to do a new, major version of &lt;code&gt;std&lt;/code&gt; with breaking
changes. Moreover, &lt;code&gt;std&lt;/code&gt; is forcibly tied to the Rust release schedule, meaning
that new versions arrive every six weeks, period. Given these constraints, we&amp;rsquo;ve
chosen to take a minimalist route with &lt;code&gt;std&lt;/code&gt;, to avoid accumulating a mass of
deprecated APIs over time.&lt;/p&gt;

&lt;p&gt;With the platform metapackage, things are quite different. On the one hand, we
can provide an experience that &lt;em&gt;feels&lt;/em&gt; a lot like &lt;code&gt;std&lt;/code&gt; (see below for more on
that). But it doesn&amp;rsquo;t suffer from the deficits of &lt;code&gt;std&lt;/code&gt;. Why? It all comes down
to versioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stability&lt;/strong&gt;: Doing a &lt;code&gt;rustup&lt;/code&gt; to the latest platform will never break your
existing code, for one simple reason: existing &lt;code&gt;Cargo.toml&lt;/code&gt; files will be
pinned to a prior version of the platform metapackage, which is fundamentally
just a collection of normal dependencies. So you can upgrade the compiler and
toolchain, but be using an old version of the platform metapackage in perpetuity.
In short, the metapackage version is &lt;em&gt;orthogonal&lt;/em&gt; to the toolchain version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Without stagnation&lt;/strong&gt;: Because of the versioning orthogonality, we can be
more free to make breaking changes to the platform libraries. That could come
in the form of upgrading to a new major version of one of the platform crates,
or even dropping a crate altogether. These changes are never &lt;em&gt;forced&lt;/em&gt; on users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But we can do even better. In practice, while code will continue working with an
old metapackage version, people are going to want to upgrade. We can smooth that
process by allowing metapackage dependencies to be &lt;em&gt;overridden&lt;/em&gt; if they appear
explicitly in the &lt;code&gt;Cargo.toml&lt;/code&gt; file. So, for example, if you say:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rust-platform&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2.7&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;3.0&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;you&amp;rsquo;re getting the versions stipulated by platform 2.7 in general, but
specifying a different version of &lt;code&gt;regex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are lots of uses for this kind of override. It can allow you to track
progress of a given platform library more aggressively (not just every six
weeks), or to try out a new, experimental major version. Or you can use it to
&lt;em&gt;downgrade&lt;/em&gt; a dependency where you can otherwise transition to a new version of
the platform.&lt;/p&gt;

&lt;h3 id=&quot;approaching-std-ergonomics&quot;&gt;Approaching &lt;code&gt;std&lt;/code&gt; ergonomics&lt;/h3&gt;

&lt;p&gt;There are several steps we can take, above and beyond the idea of a metapackage,
to make the experience of using the Rust Platform libraries approximate using
&lt;code&gt;std&lt;/code&gt; itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cargo new&lt;/code&gt;&lt;/strong&gt;. A simple step: have &lt;code&gt;cargo new&lt;/code&gt; automatically insert a
dependency on the current toolchain&amp;rsquo;s version of the platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global coherence&lt;/strong&gt;. When we assemble a version of the platform, we can do
integration testing against the whole thing, making sure that the libraries
not only compile together, but &lt;em&gt;work&lt;/em&gt; together. Moreover, libraries in the
platform can assume the inclusion of other libraries in the platform, meaning
that example code and documentation can cross-reference between libraries,
with the precise APIs that will be shipped.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Precompilation&lt;/strong&gt;. If we implement metapackages naively, then the first time
you compile something that depends on the platform, you&amp;rsquo;re going to be
compiling some large number of crates that you&amp;rsquo;re not yet using. There are a
few ways we could solve this, but certainly one option would be to provide
binary distribution of the libraries through &lt;code&gt;rustup&lt;/code&gt; &amp;ndash; much like we already
do for &lt;code&gt;std&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No &lt;code&gt;extern crate&lt;/code&gt;&lt;/strong&gt;. Getting a bit more aggressive, we might drop the need
for &lt;code&gt;extern crate&lt;/code&gt; when using platform crates, giving a truly &lt;code&gt;std&lt;/code&gt;-like
feel. (In general, &lt;code&gt;extern crate&lt;/code&gt; is already redundant with &lt;code&gt;Cargo.toml&lt;/code&gt; for
most use cases, so we might want to take this step broadly, anyway.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;versioning-and-release-cadence&quot;&gt;Versioning and release cadence&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve already alluded to &amp;ldquo;major versions&amp;rdquo; of the platform in a few senses. Here&amp;rsquo;s
what I&amp;rsquo;m thinking in more detail:&lt;/p&gt;

&lt;p&gt;First off, &lt;code&gt;rustc&lt;/code&gt; itself is separately versioned. Conceivably, the Rust
Platform 5.0 ships with &lt;code&gt;rustc&lt;/code&gt; 1.89. In other words, &lt;strong&gt;a new major version of
the platform does &lt;em&gt;not&lt;/em&gt; imply breaking changes to the language or standard
library&lt;/strong&gt;. As discussed above, the metapackage approach makes it possible to
release new major versions without forcibly breaking any existing code; people
can upgrade their platform dependency orthogonally from the compiler, at their
own pace, in a fine-grained way.&lt;/p&gt;

&lt;p&gt;With that out of the way, here&amp;rsquo;s a plausible versioning scheme and cadence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A new &lt;strong&gt;minor version&lt;/strong&gt; of the platform is released every six weeks,
essentially subsuming the existing release process. New minor releases should
only include minor version upgrades of libraries and tools (or expansions to
include new libs/tools).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A new &lt;strong&gt;major version&lt;/strong&gt; of the platform is released roughly every 18-24
months. This is the opportunity to move to new major versions of platform
libraries or to drop existing libraries. It also gives us a way to recognize
major shifts in the way you write Rust code, for example by moving to a new
set of libraries that depend on a major new language feature (say,
specialization or HKT).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More broadly, I see major version releases as a way to lay out a &lt;em&gt;narrative arc&lt;/em&gt;
for Rust, recognizing major new chapters in its development. That&amp;rsquo;s helpful
internally, because it provides medium-term focus toward shipping The Next
Iteration of Rust, which we as a community can rally around. It&amp;rsquo;s also helpful
externally, because people less immediately involved in Rust&amp;rsquo;s development will
have a much easier way to understand the accumulation of major changes that make
up each major release. These ideas are closely tied to the recent
&lt;a href=&quot;http://aturon.github.io/blog/2016/07/05/rfc-refinement/&quot;&gt;Roadmap proposal&lt;/a&gt;,
providing a clear &amp;ldquo;north star&amp;rdquo; toward which quarterly plans can head.&lt;/p&gt;

&lt;h2 id=&quot;two-level-curation&quot;&gt;Two-level curation&lt;/h2&gt;

&lt;p&gt;So far I&amp;rsquo;ve focused on artifacts that officially ship as part of the
platform. Curating at that level is going to be a lot of work, and we&amp;rsquo;ll want to
be quite selective about what&amp;rsquo;s included. (For reference, the
&lt;a href=&quot;https://www.haskell.org/platform/&quot;&gt;Haskell Platform&lt;/a&gt; has about 35 libraries
packaged).&lt;/p&gt;

&lt;p&gt;But there are some additional opportunities for curation. What I&amp;rsquo;d love to see
is a kind of &lt;em&gt;two-level&lt;/em&gt; scheme. Imagine that, somewhere on the Rust home page,
we have a listing of major areas of libraries and tools. Think: &amp;ldquo;Parsing&amp;rdquo;,
&amp;ldquo;Networking&amp;rdquo;, &amp;ldquo;Serialization&amp;rdquo;, &amp;ldquo;Debugging&amp;rdquo;. Under each of these categories, we
have a very small number of immediate links to libraries that are part of the
official platform. But we also have a &amp;ldquo;see more&amp;rdquo; link that provides a more
comprehensive list.&lt;/p&gt;

&lt;p&gt;That leads to two tiers of curation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tier one&lt;/strong&gt;: shown on front page; shipped with the platform; highly curated and reviewed; driven
by community consensus; integration tested and cross-referenced with the rest
of the platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tier two&lt;/strong&gt;: shown in &amp;ldquo;see more&amp;rdquo;; lightly curated, according to a clearly
stated set of objective criteria. Things like: platform compatibility; CI;
documentation; API conventions; versioned at 1.0 or above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By providing two tiers, we release some of the pressure around being in the
platform proper, and we provide valuable base-level quality curation and
standardization across the ecosystem. The second tier gives us a way to motivate
the ecosystem toward common quality and consistency goals: anyone is welcome to
get their crate on a &amp;ldquo;see more&amp;rdquo; page, but they have to meet a minimum bar
first.&lt;/p&gt;

&lt;h2 id=&quot;the-rust-lang-crates&quot;&gt;The &lt;code&gt;rust-lang&lt;/code&gt; crates&lt;/h2&gt;

&lt;p&gt;One small note: our previous attempt at a kind of &amp;ldquo;extended &lt;code&gt;std&lt;/code&gt;&amp;rdquo; was the
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1242&quot;&gt;rust-lang crates&lt;/a&gt; concept. These
crates are &amp;ldquo;owned&amp;rdquo; by the Rust community, and governed by the RFC process, much
like &lt;code&gt;std&lt;/code&gt;. They&amp;rsquo;re also held to similar quality standards.&lt;/p&gt;

&lt;p&gt;Ultimately, it&amp;rsquo;s proved pretty heavy weight to require full RFCs and central
control over central crates, and so the set of rust-lang crates has grown
slowly. The platform model is more of a &amp;ldquo;federated&amp;rdquo; approach, providing
decentralized ownership and evolution, while periodically trying to pull
together a coherent global story.&lt;/p&gt;

&lt;p&gt;However, I expect the rust-lang crates to stick around, and for the set to
slowly grow over time; there is definitely scope for some very important crates
to be completely &amp;ldquo;owned by the community&amp;rdquo;. These crates would automatically be
part of the platform, having been approved via the RFC process already.&lt;/p&gt;

&lt;h2 id=&quot;open-questions&quot;&gt;Open questions&lt;/h2&gt;

&lt;p&gt;The biggest open question here is: how does curation work? Obviously, it can&amp;rsquo;t
run entirely through the libs team; that doesn&amp;rsquo;t scale, and the team doesn&amp;rsquo;t
have the needed domain expertise anyway.&lt;/p&gt;

&lt;p&gt;What I envision is something that fits into the
&lt;a href=&quot;http://aturon.github.io/blog/2016/07/05/rfc-refinement/&quot;&gt;Roadmap planning proposal&lt;/a&gt;. In
a given quarter, we set out as an initiative to curate crates in a few areas &amp;ndash;
let&amp;rsquo;s say, networking and parsing. During that quarter, the libs team works
closely with the portion of the community actively working in that space, acting
as API consultants and reviewers, and helping shepherd consensus toward a
reasonable selection. There are a lot of details to sort out, but working in an
incremental way (a sort of quarterly round-robin between areas) seems like a
good balance between focus and coverage. But there are a lot of details to sort out.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also not entirely clear what will need to go into each minor
release. Hopefully it can be kept relatively minimal (e.g., with library/tool
maintainers largely driving the version choice for a given minor release).&lt;/p&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;

&lt;p&gt;Although the mechanics are not all that earth-shattering, I think that
introducing the Rust Platform could have a massive impact on how the Rust
community works, and on what life as a Rust user feels like. It tells a clear
story about Rust&amp;rsquo;s evolution, and lets us rally around that story as we hammer
out the work needed to bring it to life. I&amp;rsquo;m eager to hear what you think!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Refining Rust's RFCs</title>
   <link href="http://aturon.github.io/blog/2016/07/05/rfc-refinement/"/>
   <updated>2016-07-05T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2016/07/05/rfc-refinement</id>
   <content type="html">&lt;p&gt;At the heart of Rust&amp;rsquo;s open development is the &lt;strong&gt;RFC process&lt;/strong&gt;. Every major
change to the language, compiler, core libraries, tooling, and policy go through
an RFC writeup and consensus-building process. The process served us incredibly
well in clarifying our technical direction on the road to 1.0, and has continued
to be highly active since then, with on average about 2 RFCs merged every week.&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s not all roses. There&amp;rsquo;s been a growing sense among both Rust leadership
and the broader community that the RFC process needs some further refinement as
we continue to grow the community. I want to lay out my view of the problems and
sketch some possible solutions, based on extensive discussion and brainstorming
with many others on the team.&lt;/p&gt;

&lt;p&gt;Each idea operates at a different scale (from big-picture to low-level
mechanics), but they are intended to fit together into a whole; each one
supports the others. Ultimately, these should result in a single RFC, but in the
meantime I&amp;rsquo;ll start a discuss thread for each proposal.&lt;/p&gt;

&lt;p&gt;There is a clear common theme to all of the problems I want to raise:
&lt;strong&gt;communication&lt;/strong&gt;. We need to find ways to better scale up lines of
communication around the RFC process, and for Rust core development in general.
There is also a cross-cutting concern: a need to increase our focus
on &lt;strong&gt;mentoring&lt;/strong&gt; and &lt;strong&gt;the path to team membership&lt;/strong&gt;. @wycats has a great saying
about measuring the health of the team structure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Being a very active contributor who is not yet on a subteam should feel very
close to actually being on that subteam.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Shooting for such a state of affairs has many benefits, not least of which
is increasing the scalability of our community.&lt;/p&gt;

&lt;h2 id=&quot;proposal-roadmap&quot;&gt;Proposal: Roadmap&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://internals.rust-lang.org/t/refining-rfcs-part-1-roadmap/3656/1&quot;&gt;Discuss link&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lack of clear rallying points&lt;/strong&gt;. One thing that made the run-up to the 1.0
release so exhilarating was the way the release focused our effort: there was a
big overarching goal we were all working toward, which led to a number of fairly
clear-cut subgoals that everyone could pitch in on.&lt;/p&gt;

&lt;p&gt;Since then, though, we&amp;rsquo;ve never had quite as clear of a &amp;ldquo;north star&amp;rdquo;. We&amp;rsquo;ve
communicated some
&lt;a href=&quot;http://blog.rust-lang.org/2015/08/14/Next-year.html&quot;&gt;very high-level plans&lt;/a&gt;,
and had success rallying efforts around self-contained projects like
&lt;a href=&quot;http://blog.rust-lang.org/2016/04/19/MIR.html&quot;&gt;MIR&lt;/a&gt;. But we don&amp;rsquo;t have a
systematic way of rallying our efforts around important goals on a regular
basis. This gap is a shame, because there are many people eager to contribute,
who we should be directing toward common, important goals with good mentoring
opportunities. Likewise, there are lots of people who could provide useful
perspective on goals, or even provide leadership on initiatives, who don&amp;rsquo;t have
an outlet today.&lt;/p&gt;

&lt;p&gt;Relatedly, it can be difficult to contribute at the RFC level. Is the problem
you want to solve a priority for the relevant team or wider community? When it
comes to the core language, there is only so much design work that can be in
flight at once (since it all needs to fit together), so &lt;strong&gt;greater clarity on
priorities and motivations is essential&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-proposal&quot;&gt;The proposal&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Idea&lt;/strong&gt;: publish a &lt;em&gt;roadmap&lt;/em&gt; on a regular cadence, e.g. every two release
  cycles (12 weeks).&lt;/p&gt;

&lt;p&gt;The roadmap would contain, at a minimum, a &lt;em&gt;small&lt;/em&gt; set of &amp;ldquo;major initiatives&amp;rdquo; for
that period. An initiative might cover any phase of development, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Early investigation&lt;/em&gt;: For example,
&lt;a href=&quot;http://blog.rust-lang.org/2016/05/13/rustup.html&quot;&gt;building out NDK support in rustup&lt;/a&gt;
or exploring implications of various memory model choices.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Design&lt;/em&gt;: For example, working out a revised design for &lt;code&gt;rand&lt;/code&gt; or const generics.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Implementation&lt;/em&gt;: For example, the
&lt;a href=&quot;http://blog.rust-lang.org/2016/04/19/MIR.html&quot;&gt;MIR initiative&lt;/a&gt; or
&lt;a href=&quot;https://internals.rust-lang.org/t/the-rustbuild-feature-thread/3643/&quot;&gt;rustbuild&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Documentation&lt;/em&gt;: For example, focused effort on updating API docs in a portion
of the standard library.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Community&lt;/em&gt;: For example, launching
&lt;a href=&quot;https://github.com/rust-community/rustbridge&quot;&gt;RustBridge&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And potentially many other categories as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initiatives are intended to be a primary rallying point for the community&lt;/strong&gt;,
  and thus should share some basic traits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clear scope&lt;/strong&gt;: an initiative should have clear-cut goals that can actually
be &lt;em&gt;finished&lt;/em&gt;. So, an open-ended goal like &amp;ldquo;MIR&amp;rdquo; doesn&amp;rsquo;t fly, but &amp;ldquo;Get
MIR-trans working on all of crates.io&amp;rdquo; does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeboxed&lt;/strong&gt;: relatedly, an initiative should realistically last at most,
say, 24 weeks (two roadmaps).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commitment&lt;/strong&gt;: There should be some level of commitment from multiple people
to actually work on the initiative. In particular, the initiative should list
some primary points of contact, and ideally mentors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each initiative would have a dedicated status page with this information, links
to issues or other materials, and potentially a FAQ. We&amp;rsquo;ve often found that
there are recurring questions (&amp;ldquo;When is MIR going to be turned on by default?&amp;rdquo;)
about big, ongoing work. The roadmap and status pages give us a highly visible,
central and curated place to put this information.&lt;/p&gt;

&lt;p&gt;The roadmap should be set via an open consensus process in which anyone can
propose or influence initiatives. The initiatives should fit criteria like those
listed above, and should also fit into an overall vision for Rust&amp;rsquo;s evolution
over a longer period.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Details to be worked out&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cadence&lt;/li&gt;
&lt;li&gt;Can initiatives be added mid-stream?&lt;/li&gt;
&lt;li&gt;Full guidelines for initiatives; how many should be in flight at once? Needs
to be a small number to make this practical and useful (it&amp;rsquo;s a form of
curation/rallying).&lt;/li&gt;
&lt;li&gt;What is the process for deciding on the initiatives?&lt;/li&gt;
&lt;li&gt;Do we divvy things up by subteam? That would make the discussion easier, but
doesn&amp;rsquo;t allow for cross-cutting initiatives very easily.&lt;/li&gt;
&lt;li&gt;Can we find less boring terms than &amp;ldquo;Roadmap&amp;rdquo; and &amp;ldquo;Initiative&amp;rdquo;?&lt;/li&gt;
&lt;li&gt;Can we also include the &amp;ldquo;feature pipeline&amp;rdquo; and other long-running concerns
into a roadmap somehow?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;proposal-rfc-staging&quot;&gt;Proposal: RFC staging&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://internals.rust-lang.org/t/refining-rfcs-part-2-rfc-staging/3657/1&quot;&gt;Discuss link&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;RFCs are hard to keep up with in part because reading a full design &amp;ndash; and all
the commentary around it &amp;ndash; can be a lot of work, and there tend to be a large
number of active RFCs in flight at any time. &lt;strong&gt;RFC discussions are often hard to
follow, due to the overwhelming number of comments, sometimes stretching over
multiple forums.&lt;/strong&gt; Naturally, this problem is exacerbated by &amp;ldquo;controversial&amp;rdquo;
RFCs, which is where we most need broad input and careful discussion. It can
also be hard to track RFCs that are in some sense &amp;ldquo;competing&amp;rdquo; (offering
alternative proposals for a common problem), or to correlate discussion between
the discuss forum and github.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also problematic to start off with a full proposal. What we really want is
to get the community on the same page first about the importance of the problem
being solved, and &lt;em&gt;then&lt;/em&gt; to proceed to the design phase, perhaps considering
multiple competing designs.&lt;/p&gt;

&lt;p&gt;Finally, RFCs are sometimes closed as &amp;ldquo;postponed&amp;rdquo;, but ideally that should not
simply &lt;em&gt;terminate&lt;/em&gt; the discussion; instead, the discussion should simply
continue elsewhere, or somehow be marked as being at a different stage.&lt;/p&gt;

&lt;h3 id=&quot;the-proposal&quot;&gt;The proposal&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Idea&lt;/strong&gt;: introduce stages into the RFC process, including one for reaching
  consensus on &lt;em&gt;motivation&lt;/em&gt; prior to considering a design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Idea&lt;/strong&gt;: move the focus away from an RFC PR as the primary venue for RFC
  discussion.&lt;/p&gt;

&lt;p&gt;Put differently, the idea is to orient the RFC process around &lt;em&gt;problems&lt;/em&gt; first,
and solutions second.&lt;/p&gt;

&lt;p&gt;The rough phases I have in mind are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Problem consensus&lt;/li&gt;
&lt;li&gt;RFC drafting&lt;/li&gt;
&lt;li&gt;RFC PR(s)&lt;/li&gt;
&lt;li&gt;FCP&lt;/li&gt;
&lt;li&gt;RFC merged&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Concretely, what this would look like is having some venue for tracking the
problems we might want to solve, perhaps a revamped version of the RFC issue
tracker. Whatever this venue is, it would track the progression through all of
the phases. Let&amp;rsquo;s call this venue the &amp;ldquo;Problem Tracker&amp;rdquo;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Phase 1: Problem consensus&lt;/em&gt;. The initial discussion is essentially about
&lt;strong&gt;reaching consensus on the motivation section of an RFC&lt;/strong&gt;, which should include
examples and make a compelling case that solving the problem is important enough
to warrant expending energy and potential complexity. The subteam would sign off
on that motivation, at which point there is some level of commitment to solve
the problem. That puts the focus where it should be &amp;ndash; solving problems &amp;ndash; and
should make it much easier for subteam members to engage early on in the RFC
lifecycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Phase 2: RFC drafting&lt;/em&gt;. This phase can proceed in parallel with the previous
one. During this phase, people sketch designs and work toward one or more full
RFC drafts. Brainstorming and discussion on specific drafts would happen
within dedicated &amp;ldquo;pre-RFC&amp;rdquo; &lt;a href=&quot;http://internals.rust-lang.org/&quot;&gt;discuss posts&lt;/a&gt;,
which are linked from the Problem Tracker. In particular, newly-opened RFC PRs
today often get an avalanche of comments and early revisions, making it very
hard to join the discussion even a week later. Pushing early feedback to our
forum instead will make the eventual RFC PR discussion more focused and easier
to participate in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Phase 3: RFC PR(s)&lt;/em&gt;. At some point, a &lt;em&gt;shepherd&lt;/em&gt; (see below) can determine
that an RFC draft is of sufficiently high quality and steady state that a PR
should be opened, at which point discussion proceeds as it does
today. Multiple RFC PRs might be open for the same basic problem &amp;ndash; and
indeed, this is a good way to take the &amp;ldquo;Alternatives&amp;rdquo; section more
seriously. All open PRs would be linked from the Problem Tracker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phases 4 and 5 work just as today.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One interesting aspect of this phasing: it&amp;rsquo;s possible to approve a Motivation
section, then get all the way to RFC PR, only to close out the PR for one reason
or another. In such cases, it should be possible to go back to the Problem
Tracker and build a new, alternative RFC draft with the same Motivation section.&lt;/p&gt;

&lt;p&gt;Note that, in this regime, you don&amp;rsquo;t ever open an RFC PR out of hand &amp;ndash; it must
go through the earlier phases, including the pre-RFC discuss post. While this
may feel like more process, I think that globally it will make the whole thing
more efficient, by weeding out poorly motivated RFCs earlier, by focusing
attention on the problem, by producing higher quality RFC PRs, and (as we&amp;rsquo;ll
see) by decentralizing the process a bit more. In addition, it makes it easier
to cope with the problem of &amp;ldquo;Does this need an RFC?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;As part of this proposal, &lt;strong&gt;I think we should &amp;ldquo;reboot&amp;rdquo; the notion of a
&lt;em&gt;shepherd&lt;/em&gt;.&lt;/strong&gt; The idea would be to create a broader network of people around a
subteam who are empowered to help move the RFC process along in various ways,
but aren&amp;rsquo;t necessarily responsible for the final decision. So, for example, we
would have a larger set of &amp;ldquo;lang shepherds&amp;rdquo; who help lang RFCs progress. The
powers and responsibilities of shepherds would include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Calling to question&amp;rdquo; &amp;ndash; that is, proposing that the subteam move to make a
decision on problem consensus or moving to FCP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working with the community to help brainstorm, draft, and revise pre-RFCs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moving to from pre-RFC to RFC PR phase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Acting as the &amp;ldquo;scribe&amp;rdquo; for the RFC process, by keeping the Problem Tracker up
to date. In particular, the subteams currently attempt to provide &amp;ldquo;summary&amp;rdquo;
comments for contentious RFCs, to help people track the discussion. This
proposal would give those comments more formal status, as something that would
go directly on the Problem Tracker, and that any shepherd could provide at any
point.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All subteam members can act as shepherds as well.&lt;/p&gt;

&lt;p&gt;In general, I envision the Problem Tracker as the go-to place to see where
things stand for a given problem/set of proposals, including summarization of
discussion and pros/cons for the proposals. The shepherds would play a special
role in establishing that official record.&lt;/p&gt;

&lt;p&gt;I think these changes make the RFC process both more accessible and more
scalable. More accessible because it&amp;rsquo;s easier to get involved and get quick
feedback in lightweight ways (before writing up an entire design). More scalable
because of increased parallelism, and because the big decision points happen at
either an easier stage (establishing motivation) or with many fewer proposals in
flight (the RFC PR stage).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Details to be worked out&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens to current RFC PRs? Are they grandfathered in, or moved into this
new process?&lt;/li&gt;
&lt;li&gt;Where does the &amp;ldquo;problem tracker&amp;rdquo; live?&lt;/li&gt;
&lt;li&gt;What are good guidelines around an initial &amp;ldquo;motivation&amp;rdquo;?&lt;/li&gt;
&lt;li&gt;How and where can we keep an &amp;ldquo;official record&amp;rdquo; of the progression of a
problem, including links to (and summaries of) pre-RFC and RFC PR threads?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;proposal-async-decisions&quot;&gt;Proposal: Async decisions&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://internals.rust-lang.org/t/refining-rfcs-part-3-async-decisions/3658/1&quot;&gt;Discuss link&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;There is room for improvement around the way that the subteams themselves
work. Today, subteams reach decisions on RFCs and other issues in (bi)weekly
meetings. There are at least two problems with doing so. First, since the
meetings have a limited duration, &lt;strong&gt;we often run out of time without finishing
the active business, introducing delays&lt;/strong&gt;; similarly, because of the high amount
of RFC activity, &lt;strong&gt;the subteams often operate in &amp;ldquo;reactive&amp;rdquo; mode, more than
actively leading&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another issue is that meetings provide, in some sense, the &amp;ldquo;wrong defaults&amp;rdquo; for
making decisions. We have to be careful to ensure that all the rationale for a
decision is present in the online discussion thread, and that any new rationale
that came up during a meeting means that the decision is delayed, to give the
full community a chance to respond. The point is that, &lt;strong&gt;while we work hard to
provide this transparency, it requires that extra work&lt;/strong&gt;. At the same time,
there is often good discussion in meetings wherein the subteam members build up
a set of shared values &amp;ndash; thereby missing the opportunity to argue for those
values to the wider community. Finding a way to move decision-making to a more
public, asynchronous system seems ideal, though meetings &lt;em&gt;do&lt;/em&gt; have the benefit
of providing a steady cadence to ensure that business is getting done.&lt;/p&gt;

&lt;h3 id=&quot;the-proposal&quot;&gt;The proposal&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Idea&lt;/strong&gt;: move away from video meetings for decision-making, instead reaching
  decisions entirely in the associated comment threads.&lt;/p&gt;

&lt;p&gt;By moving the decision-making process fully online, we make it transparent by
default. That is not to say that subteam members &amp;ndash; or anyone else &amp;ndash; will never
have private conversation, of course. Just that this particular bit of business
is better conducted online.&lt;/p&gt;

&lt;p&gt;The key to making this work is automation. Right now, the meetings provide a
convenient &amp;ldquo;forcing function&amp;rdquo; to ensure that decisions are being reached in a
somewhat timely fashion. To ensure that we still make steady progress, we need a
&lt;em&gt;dashboard&lt;/em&gt; for every subteam member, showing them precisely what outstanding
items they need to weigh in on &amp;ndash; and that list needs to be kept manageably
short.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll need a dashboard tool that can pick up on special text from subteam
members for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calling an RFC/issue into FCP

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: fcp&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Approving/disapproving FCP

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: fcp r+&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;process: fcp r-&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Extending FCP

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: fcp extend&amp;rdquo; (for one more week by default; possibly give parameter?)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Approving stabilization/RFC merging

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: r+&amp;rdquo; (ideally followed up by some commentary)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Weakly objecting

&lt;ul&gt;
&lt;li&gt;Just leave a comment, followed by a &amp;ldquo;process: r+&amp;rdquo; once you are satisfied
that the objection is addressed or that it&amp;rsquo;s OK not to address it.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Strongly objecting (i.e. blocking acceptance)

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: r-&amp;rdquo; (followed up with objection)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Abstaining (possibly?)

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;process: ack&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard tool would track the current status of RFCs/issues facing a
decision, and would track the various timelines involved, e.g. that RFC FCP
lasts for one week.&lt;/p&gt;

&lt;p&gt;We can and should continue to hold video subteam meetings (they&amp;rsquo;re high
bandwidth!), but for more forward-looking purposes: discussing specific
early-stage RFCs, brainstorming, and prioritization. We can explore recording
these meetings, and potentially opening them up to additional stakeholders who
are not part of the subteam.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Details to be worked out&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A plausible story for automation that retains the consensus process and is
likely to keep things moving.&lt;/li&gt;
&lt;li&gt;Can the automation itself be responsible for moving to FCP/merging? Or at
least provide a pushbutton way for doing so?&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Resurrecting impl Trait</title>
   <link href="http://aturon.github.io/blog/2015/09/28/impl-trait/"/>
   <updated>2015-09-28T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2015/09/28/impl-trait</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: since before Rust 1.0, we&amp;rsquo;ve wanted to be able to return an unboxed
closure or avoid spelling out huge iterator types. This blog post revives the
old &lt;code&gt;impl Trait&lt;/code&gt; proposal, and discusses the broad tradeoffs between two
different ways of carrying it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heads up&lt;/strong&gt;: I&amp;rsquo;m going to gloss over some details in this post, in the interest
of getting across the high-level situation as I see it. Of course, any actual
proposal will need to address the questions that I skip over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I removed the &amp;ldquo;elision&amp;rdquo; terminology, which was more confusing than
helpful. I also now mention some implementation issues for the return type
inference proposal. And I&amp;rsquo;ve toned down my preference in the wrapup; I&amp;rsquo;m
becoming less certain :)&lt;/p&gt;

&lt;h2 id=&quot;the-original-proposal&quot;&gt;The original proposal&lt;/h2&gt;

&lt;p&gt;This post is about a topic near-and-dear to me &amp;ndash; my
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/105&quot;&gt;first Rust RFC&lt;/a&gt;! &amp;ndash; which is known
as the &amp;ldquo;&lt;code&gt;impl Trait&lt;/code&gt;&amp;rdquo; proposal. The RFC termed these &amp;ldquo;unboxed abstract types&amp;rdquo;,
and it&amp;rsquo;s easiest to start with the motivation given there:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In today&amp;rsquo;s Rust, you can write a function signature like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;consume_iter_static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;consume_iter_dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In both cases, the function does not depend on the exact type of the argument.
The type is held &amp;ldquo;abstract&amp;rdquo;, and is assumed only to satisfy a trait bound.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;_static&lt;/code&gt; version using generics,
each use of the function is specialized to a concrete, statically-known type,
giving static dispatch, inline layout, and other performance wins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;_dynamic&lt;/code&gt; version using trait objects, the concrete argument type is
only known at runtime using a vtable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, while you can write&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;produce_iter_dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;you &lt;em&gt;cannot&lt;/em&gt; write something like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;produce_iter_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That is, in today&amp;rsquo;s Rust, abstract return types can only be written using trait objects, which
can be a significant performance penalty. This RFC proposes &amp;ldquo;unboxed abstract
types&amp;rdquo; as a way of achieving signatures like &lt;code&gt;produce_iter_static&lt;/code&gt;. Like
generics, unboxed abstract types guarantee static dispatch and inline data
layout.&lt;/p&gt;

&lt;p&gt;Here are some problems that unboxed abstract types solve or mitigate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Returning unboxed closures&lt;/em&gt;. The ongoing work on unboxed closures expresses
closures using traits. Sugar for closures generates an anonymous type
implementing a closure trait. Without unboxed abstract types, there is no way
to use this sugar while returning the resulting closure unboxed, because there
is no way to write the name of the generated type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Leaky APIs&lt;/em&gt;. Functions can easily leak implementation details in their return
type, when the API should really only promise a trait bound. For example, a
function returning &lt;code&gt;Rev&amp;lt;Splits&amp;lt;&amp;#39;a, u8&amp;gt;&amp;gt;&lt;/code&gt; is revealing exactly how the iterator
is constructed, when the function should only promise that it returns &lt;em&gt;some&lt;/em&gt;
type implementing &lt;code&gt;Iterator&amp;lt;u8&amp;gt;&lt;/code&gt;. Using newtypes/structs with private fields
helps, but is extra work. Unboxed abstract types make it as easy to promise only
a trait bound as it is to return a concrete type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Complex types&lt;/em&gt;. Use of iterators in particular can lead to huge types:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Enumerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;MoveItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SkipWhile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slice&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even when using newtypes to hide the details, the type still has to be written
  out, which can be very painful. Unboxed abstract types only require writing the
  trait bound.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Documentation&lt;/em&gt;. In today&amp;rsquo;s Rust, reading the documentation for the &lt;code&gt;Iterator&lt;/code&gt;
trait is needlessly difficult. Many of the methods return new iterators, but
currently each one returns a different type (&lt;code&gt;Chain&lt;/code&gt;, &lt;code&gt;Zip&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Filter&lt;/code&gt;,
etc), and it requires drilling down into each of these types to determine what
kind of iterator they produce.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, unboxed abstract types make it easy for a function signature to
promise nothing more than a trait bound, and do not generally require the
function&amp;rsquo;s author to write down the concrete type implementing the bound.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, the RFC began with the framing that there was a kind of &amp;ldquo;gap&amp;rdquo; in the
expressiveness matrix: we can choose between static and dynamic dispatch for
inputs, but not for outputs.&lt;/p&gt;

&lt;p&gt;The RFC went on to propose the &lt;code&gt;impl Trait&lt;/code&gt; notation as a way of solving these
problems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The basic idea is to allow code like the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;produce_iter_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;impl Iterator&amp;lt;u8&amp;gt;&lt;/code&gt; should be understood as &amp;ldquo;some type &lt;code&gt;T&lt;/code&gt; such that &lt;code&gt;T:
Iterator&amp;lt;u8&amp;gt;&lt;/code&gt;.  Notice that the function author does not have to write down any
concrete iterator type, nor does the function&amp;rsquo;s signature reveal those details
to its clients. But the type promises that &lt;em&gt;there exists&lt;/em&gt; some concrete type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The point here is to avoid writing a return type like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Skip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Rev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Range&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and instead give only the relevant information: some trait(s) that are
implemented for the return type.&lt;/p&gt;

&lt;p&gt;For a variety of reasons the RFC was closed and the feature has not shipped.
But part of the impetus for returning to this topic now is that the illustrious
@eddyb has a working implementation of a subset of the RFC! Ideally, the Rust
community can come to a consensus around a design, and we can adapt and land
this implementation.&lt;/p&gt;

&lt;h2 id=&quot;design-questions&quot;&gt;Design questions&lt;/h2&gt;

&lt;p&gt;As it turns out, though, there are a lot of complex issues and decisions at play
here, and as usual, multiple interesting points in the design space. Some of
these were brought up in the RFC itself, others brought up on thread, and others
haven&amp;rsquo;t really been discussed. But they all have to be tackled.&lt;/p&gt;

&lt;p&gt;First I&amp;rsquo;ll go quickly through the main questions, then talk about design
priorities, and finally present two possible designs.&lt;/p&gt;

&lt;h3 id=&quot;is-impl-trait-a-type&quot;&gt;Is &lt;code&gt;impl Trait&lt;/code&gt; a type?&lt;/h3&gt;

&lt;p&gt;Can &lt;code&gt;impl Trait&lt;/code&gt; appear everywhere a type can?&lt;/p&gt;

&lt;p&gt;If not, where &lt;em&gt;can&lt;/em&gt; &lt;code&gt;impl Trait&lt;/code&gt; be used? Only return types? What about arguments, struct
definitions, type aliases, etc? In each case, what should the semantics be?&lt;/p&gt;

&lt;p&gt;The RFC gave answers to many of these questions, although I think today I would
answer some of them differently.&lt;/p&gt;

&lt;h3 id=&quot;is-impl-trait-sealed&quot;&gt;Is &lt;code&gt;impl Trait&lt;/code&gt; &amp;quot;sealed&amp;rdquo;?&lt;/h3&gt;

&lt;p&gt;As @Ericson2314 astutely remarked on thread:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This RFC is trying to serve up type inference and type abstraction as one
feature, when they are orthogonal.&lt;/p&gt;

&lt;p&gt;Inference-wise, we want to introduce meta-variables/unknowns where we are are not allowed to today.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BigLongIterator&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Abstraction-wise, we want to give ourselves more leeway to change our libraries without breaking client code.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;nsa&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Works with any T!&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Iter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SnoopWhile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;

&lt;p&gt;Here &amp;ldquo;type inference&amp;rdquo; means something akin to leaving off a type
annotation that&amp;rsquo;s required today (like the return type of a function),
without any change to semantics.  By contrast, &amp;ldquo;type abstraction&amp;rdquo;
means &lt;em&gt;hiding&lt;/em&gt; some information about a type from clients, similarly
to what we often do with
&lt;a href=&quot;http://aturon.github.io/features/types/newtype.html&quot;&gt;newtypes&lt;/a&gt;
today. The original proposal coupled these two features together.&lt;/p&gt;

&lt;p&gt;This is going to turn out to be a central question for this blog post. &lt;em&gt;Should&lt;/em&gt;
these two aspects of the feature be treated separately or coupled? Are both
needed? What are the tradeoffs?&lt;/p&gt;

&lt;h3 id=&quot;how-do-you-deal-with-clone-or-iterator-adapters&quot;&gt;How do you deal with &lt;code&gt;Clone&lt;/code&gt; or &lt;code&gt;Iterator&lt;/code&gt; adapters?&lt;/h3&gt;

&lt;p&gt;It&amp;rsquo;s pretty common that a trait is &lt;em&gt;conditionally&lt;/em&gt; implemented:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But that poses a problem for &lt;code&gt;impl Trait&lt;/code&gt;, which requires an &lt;em&gt;unconditional&lt;/em&gt;
statement about which traits are implemented. This is especially painful for
things like the iterator adapters, which are often &lt;code&gt;Clone&lt;/code&gt; if the original
iterator is, &lt;code&gt;DoubleEndedIterator&lt;/code&gt; if the original iterator is, etc.&lt;/p&gt;

&lt;h3 id=&quot;do-marker-traits-send-sync-have-to-be-mentioned&quot;&gt;Do marker traits (&lt;code&gt;Send&lt;/code&gt;, &lt;code&gt;Sync&lt;/code&gt;, &amp;hellip;) have to be mentioned?&lt;/h3&gt;

&lt;p&gt;When you use the
&lt;a href=&quot;http://aturon.github.io/features/types/newtype.html&quot;&gt;newtype pattern&lt;/a&gt; today,
you have to explicitly forward most traits, but certain traits like &lt;code&gt;Send&lt;/code&gt; and
&lt;code&gt;Sync&lt;/code&gt; will &lt;em&gt;automatically&lt;/em&gt; be implemented for the new type if they were for the
old type. Should &lt;code&gt;impl Trait&lt;/code&gt; work similarly, implicitly carrying the markers?&lt;/p&gt;

&lt;p&gt;This is not just a question of ergonomics, though the ergonomic issue here is
significant! There&amp;rsquo;s also an extensibility problem: new libraries can add new
&amp;ldquo;OIBIT&amp;rdquo;-style marker traits which are supposed to automatically apply to types,
but forcing those markers to be explicitly opted in to for &lt;code&gt;impl Trait&lt;/code&gt; means
they often won&amp;rsquo;t apply. We&amp;rsquo;ve already seen significant problems along these
lines with trait objects today.&lt;/p&gt;

&lt;h2 id=&quot;design-constraints&quot;&gt;Design constraints&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m going to be a bit opinionated here and lay out some design desires.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hard constraints&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;must be possible to return an unboxed closure and store it in a struct&lt;/li&gt;
&lt;li&gt;must be possible to return a compound iterator without giving the type explicitly&lt;/li&gt;
&lt;li&gt;must cope with &lt;em&gt;multiple&lt;/em&gt; such types appearing as &lt;em&gt;components&lt;/em&gt; of a return
type (e.g., returning a pair of different unboxed closures)&lt;/li&gt;
&lt;li&gt;must be able to assert that at least &lt;em&gt;some&lt;/em&gt; traits are satisfied&lt;/li&gt;
&lt;li&gt;must be able to deal with conditional trait implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Strong desires&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;minimal signature verbosity&lt;/li&gt;
&lt;li&gt;compatible with adding new OIBITs&lt;/li&gt;
&lt;li&gt;simple semantics/explanation of the feature, especially if it looks like a type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nice to haves&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;type abstraction (the &amp;ldquo;hiding&amp;rdquo; that @Ericson2314 was talking about)&lt;/li&gt;
&lt;li&gt;more ergonomic newtypes (where you don&amp;rsquo;t have to forward trait impls explicitly)&lt;/li&gt;
&lt;li&gt;applicable to struct definitions, not just function signatures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;option-1-return-type-inference&quot;&gt;Option 1: return type inference&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ll start with the simpler design: attack only the type inference aspect of the
original proposal, without actually hiding any details about a type from clients.&lt;/p&gt;

&lt;p&gt;The simplest way to do this would be to allow wildcards to leave off types in return
position:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;first closure&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;second closure&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea here is that the actual return type is fully concrete &amp;ndash; clients of the
API know exactly what it is, and can take advantage of public inherent methods or
arbitrary traits.&lt;/p&gt;

&lt;p&gt;But a pure wildcard proposal is a pretty drastic step away from our policy of
explicitness for signatures and type definitions. In particular, it doesn&amp;rsquo;t lead
to a very informative signature for clients of the API.&lt;/p&gt;

&lt;p&gt;A more palatable choice would be something closer to &lt;code&gt;impl Trait&lt;/code&gt;, like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;first closure&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;second closure&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is that these trait bounds don&amp;rsquo;t say &lt;em&gt;everything&lt;/em&gt; about the concrete
type, but they give some trait bounds that must hold of the concrete type. (So
&lt;code&gt;~FnOnce()&lt;/code&gt; means &amp;ldquo;an elided type with interface roughly &lt;code&gt;FnOnce()&lt;/code&gt;&amp;rdquo;.) Usually,
there is one &amp;ldquo;primary&amp;rdquo; trait for a given return type, though of course you can
list as many as you like using &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If I have my druthers, this feature would also be usable in argument position:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To be clear about the &amp;ldquo;roughly&amp;rdquo; here: in the &lt;code&gt;foo&lt;/code&gt; example, the return type also
implements &lt;code&gt;Clone&lt;/code&gt; and &lt;code&gt;ExactSizeIterator&lt;/code&gt; &amp;ndash; and client code can rely on those
facts, despite them not being written down.&lt;/p&gt;

&lt;p&gt;On the one hand, this approach is uncomfortably implicit (since bounds can be
left off), and it may leak information about the type that we do not
intend.&lt;/p&gt;

&lt;p&gt;There are also some implementation concerns &amp;ndash; the typechecker will need to
check function definitions in a particular order to discover concrete types, and
must ensure that return type inference isn&amp;rsquo;t used in a cycle between
functions. Note, however, that type inference continues to be purely local.&lt;/p&gt;

&lt;p&gt;On the other hand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It&amp;rsquo;s dead simple from the programmer&amp;rsquo;s perspective. There are no
thorny questions about type equality, scoping of type abstractions,
or what &lt;code&gt;~&lt;/code&gt; means in various contexts. It&amp;rsquo;s just an extension of
inference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It behaves exactly like associated types today.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It accounts for conditional trait implementations easily, since those will
automatically be known about the return type whenever they are applicable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It accounts for marker traits and &amp;ldquo;OIBITs&amp;rdquo; without any fuss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This kind of &amp;ldquo;leakage&amp;rdquo; is already prevalent &amp;ndash; and important! &amp;ndash; in Rust
today. For example, when you define an abstract type, you give a trait bound
which must be fulfilled. But when a client has narrowed to a particular
&lt;code&gt;impl&lt;/code&gt;, &lt;em&gt;everything&lt;/em&gt; about the associated type is revealed:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// we know that u8::Assoc == u8! We&amp;#39;re only limited to the bound when writing&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// fully generic code.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The type leakage is, in general, very unlikely to be relied upon. For example, to
observe the particulars of an iterator adapter type, you&amp;rsquo;d have to do
something like assign it to a suitably-typed mutable variable:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Chain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Enumerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;MoveItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SkipWhile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slice&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This design addresses all of the hard constraints and strong desires &amp;ndash; but none
of the nice-to-haves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key point&lt;/strong&gt;: the strong simplicity here is a major selling point, given that
the pain we&amp;rsquo;re trying to solve here is one of the places where Rust is
considered to be particularly complicated. (See
&lt;a href=&quot;https://www.reddit.com/r/rust/comments/397xn3/why_does_anything_have_higher_priority_than/&quot;&gt;this reddit post&lt;/a&gt;
for example.)&lt;/p&gt;

&lt;h2 id=&quot;option-2-type-abstraction&quot;&gt;Option 2: type abstraction&lt;/h2&gt;

&lt;p&gt;On the other end of the spectrum, we could try to address all of the use cases
outlined, including type abstraction.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to give one particular strawman proposal and syntax here, and only at
a high level &amp;ndash; it&amp;rsquo;s not a fully fleshed out spec, but should give some idea of
the possible direction.&lt;/p&gt;

&lt;p&gt;The basic idea is to introduce a &amp;ldquo;type abstraction operator&amp;rdquo; &lt;code&gt;@&lt;/code&gt; that is used to
&amp;ldquo;seal&amp;rdquo; a concrete type to a particular interface:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileDesc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Seek&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You should read this as &amp;ldquo;at&amp;rdquo;, meaning that you are viewing a type &amp;ldquo;at&amp;rdquo; some
specific bounds.&lt;/p&gt;

&lt;p&gt;This definition is roughly equivalent to:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileDesc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&amp;#39;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&amp;#39;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Seek&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&amp;#39;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&amp;#39;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However that there is a &lt;em&gt;scope&lt;/em&gt; in which the equivalence &lt;code&gt;File = FileDesc&lt;/code&gt; is
known. Within that scope (&amp;ldquo;inside the abstraction boundary&amp;rdquo;), &lt;code&gt;File&lt;/code&gt; is a simple
type alias for &lt;code&gt;FileDesc&lt;/code&gt;. Outside that scope, &lt;code&gt;File&lt;/code&gt; is an opaque type that is
only known to implement the four traits given. This is akin to what you get with
privacy, except that you don&amp;rsquo;t have to explicitly project using &lt;code&gt;.0&lt;/code&gt; or
construct using &lt;code&gt;File(SomeFileDesc)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The obvious scoping rules for the abstraction would be the current privacy rules
(i.e., literally the same as what you get with a newtype).&lt;/p&gt;

&lt;p&gt;There are some tricky questions here that need to be answered in a complete
design, which I don&amp;rsquo;t try to answer here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aside from &lt;code&gt;type&lt;/code&gt; definitions, where else can &lt;code&gt;@&lt;/code&gt; be used? We&amp;rsquo;ll explore one
other location &amp;ndash; function signatures &amp;ndash; in this post, but &lt;code&gt;struct&lt;/code&gt;/&lt;code&gt;enum&lt;/code&gt;
definitions are another interesting possibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How should these type definitions interact with coherence? Can you implement
traits for &lt;code&gt;File&lt;/code&gt;? Inherent methods? What if they conflict with traits/methods
on &lt;code&gt;FileDesc&lt;/code&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you deal with bounds where the type isn&amp;rsquo;t in &lt;code&gt;Self&lt;/code&gt; position? For
example, there is also an impl of &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt; for &lt;code&gt;&amp;amp;File&lt;/code&gt; that should
be exported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are the rules for equality around these types?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, I want to focus on the original motivation: avoiding having to fully
name a type, while providing an interface to it.&lt;/p&gt;

&lt;h3 id=&quot;integrating-return-type-inference&quot;&gt;Integrating return type inference&lt;/h3&gt;

&lt;p&gt;The other part of the &lt;code&gt;@&lt;/code&gt; proposal is that, when used in function signatures,
you can leave off the type before the &lt;code&gt;@&lt;/code&gt; (i.e., the concrete type being
abstracted):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unlike the &lt;code&gt;~&lt;/code&gt; proposal above, &lt;em&gt;this hides everything about the return type
except for the stated trait bound&lt;/em&gt;. So clients here don&amp;rsquo;t know that the iterator
is also &lt;code&gt;Clone&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;scaling-up-marker-and-conditional-traits&quot;&gt;Scaling up: marker and conditional traits&lt;/h3&gt;

&lt;p&gt;To make this kind of &amp;ldquo;sealing&amp;rdquo; work, we&amp;rsquo;d have to deal with two additional
thorny problems: marker traits and conditional traits.&lt;/p&gt;

&lt;p&gt;Marker traits like &lt;code&gt;Send&lt;/code&gt; and &lt;code&gt;Sync&lt;/code&gt; are often &amp;ldquo;defaulted&amp;rdquo; (via &lt;code&gt;..&lt;/code&gt; impls, AKA
OIBITs). When you follow the newtype pattern, these &amp;ldquo;defaulted&amp;rdquo; traits come
along for the ride, whether you ask for them or not &amp;ndash; they leak through. They
are also often conditional (e.g., one type is &lt;code&gt;Send&lt;/code&gt; if some other types are
&lt;code&gt;Send&lt;/code&gt;). It&amp;rsquo;s probably simplest to say that &lt;code&gt;@&lt;/code&gt; has newtype-like semantics and
marker traits leak through. (Leaking is also important because OIBIT-style
traits can be defined in downstream crates about which you have no knowledge.)&lt;/p&gt;

&lt;p&gt;Leaking, of course, makes &lt;code&gt;@Trait&lt;/code&gt; and &lt;code&gt;Box&amp;lt;Trait&amp;gt;&lt;/code&gt; different forms of type
abstraction, but OIBITs are a huge pain point for trait objects today, so that&amp;rsquo;s
likely a worthwhile difference.&lt;/p&gt;

&lt;p&gt;A more difficult issue is truly conditional traits, like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To deal with this situation, we&amp;rsquo;d need conditional bounds like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;rsquo;s, obviously, pretty verbose. Fortunately, in many cases there are groups
of conditional bounds that tend to go together (see the iterator adapters, for
example). You could imagine capturing these groups into aliases, so that you
could say something like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IterAdapter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IterAdapter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These aliases still have documentation advantages over the current adapter API,
since you&amp;rsquo;d reuse the same alias over and over. By contrast, today each adapter
introduces a separate newtype which must be examined separately to find its API.&lt;/p&gt;

&lt;h3 id=&quot;benefits-drawbacks&quot;&gt;Benefits/drawbacks&lt;/h3&gt;

&lt;p&gt;So in all, it seems feasible to introduce a type abstraction feature, &lt;code&gt;@&lt;/code&gt;, along
with an elided form for function signatures, and have reasonably concise
signatures.&lt;/p&gt;

&lt;p&gt;Some benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The design feels a bit more &amp;ldquo;principled&amp;rdquo; than the pure type inference design:
except for OIBIT traits, the entire interface to a type must be written
explicitly, so there&amp;rsquo;s no accidental leakage and everything is fully
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The use in &lt;code&gt;type&lt;/code&gt; gives a lighter weight form of newtypes that doesn&amp;rsquo;t require
manually forwarding trait impls (akin to &amp;ldquo;generalized newtype deriving&amp;rdquo; from
the Haskell world). However, these types would likely not function as complete
newtypes from the perspective of impl coherence &amp;ndash; it probably doesn&amp;rsquo;t make
sense to impl new traits for them, for example. So they don&amp;rsquo;t solve the whole
problem.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Complexity. This variant is &lt;em&gt;way&lt;/em&gt; more complicated than pure type
inference. And it&amp;rsquo;s not clear that type abstraction is a feature that Rust
really needs, given that we already have privacy and the newtype pattern. We
could provide &amp;ldquo;newtype deriving&amp;rdquo; in a much simpler way to address the pain
points there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verbosity. Even with aliases, the signatures involve here tend to be much more
complicated. Of course, that&amp;rsquo;s part of the point: this proposal is trying to
be explicit about signatures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A somewhat deeper change. This proposal means, for example, that &lt;code&gt;type&lt;/code&gt; can no
longer be understood as a straight-up alias, since repeated uses of &lt;code&gt;@&lt;/code&gt; create
&lt;em&gt;distinct&lt;/em&gt; abstract types.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wrapup&quot;&gt;Wrapup&lt;/h2&gt;

&lt;p&gt;We absolutely need to expand Rust in this area; I stand by the design
constraints listed here. But we managed to ship a relatively slim Rust 1.0, and
I&amp;rsquo;d like to fight to keep the language as small and concise as we can manage.&lt;/p&gt;

&lt;p&gt;In that light, I&amp;rsquo;m leaning somewhat toward return type inference here, despite
its break from full signature explicitness. But I remain concerned about the
fact that the bound is not actually all that meaningful.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Specialize to reuse</title>
   <link href="http://aturon.github.io/blog/2015/09/18/reuse/"/>
   <updated>2015-09-18T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2015/09/18/reuse</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;specialization&lt;/a&gt; supports clean, inheritance-like patterns
out of the box. This post explains how, and discusses the interaction with the
&amp;ldquo;virtual structs&amp;rdquo; saga.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#specialization-as-proposed&quot;&gt;Specialization as proposed&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#a-small-addendum&quot;&gt;A small addendum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ending-1:-the-trait-based-approach&quot;&gt;Ending 1: the trait-based approach&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#thin-pointers&quot;&gt;Thin pointers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#incorporating-fields&quot;&gt;Incorporating fields&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#struct-composition&quot;&gt;Struct composition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#struct-inheritance&quot;&gt;Struct inheritance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#trait-fields&quot;&gt;Trait fields&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ending-2:-the-enum-based-approach&quot;&gt;Ending 2: the enum-based approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#getting-opinionated&quot;&gt;Getting opinionated&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve been working for a while with Niko Matsakis and Nick Cameron on another
round of design for handling type hierarchies like those found in the DOM, in
GUI frameworks, and even the compiler&amp;rsquo;s AST. The Rust community has gone through
&lt;a href=&quot;https://github.com/rust-lang/rfcs/issues/349&quot;&gt;many iterations&lt;/a&gt; of design in
this space, having identified the following goals for a type hierarchy design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cheap field access from internal methods;&lt;/li&gt;
&lt;li&gt;cheap dynamic dispatch of methods;&lt;/li&gt;
&lt;li&gt;cheap downcasting;&lt;/li&gt;
&lt;li&gt;thin pointers;&lt;/li&gt;
&lt;li&gt;sharing of fields and methods between definitions;&lt;/li&gt;
&lt;li&gt;safe, i.e., doesn&amp;rsquo;t require a bunch of transmutes or other unsafe code to be usable;&lt;/li&gt;
&lt;li&gt;syntactically lightweight or implicit upcasting;&lt;/li&gt;
&lt;li&gt;calling functions through smart pointers, e.g. &lt;code&gt;fn foo(JSRef&amp;lt;T&amp;gt;, ...)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;static dispatch of methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two important constraints are missing from this prior list, one technical and
one philosophical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reusable constructor code at every level of the hierarchy;&lt;/li&gt;
&lt;li&gt;fits well into the language, either by smoothly extending existing features,
or by adding orthogonal concepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the design I&amp;rsquo;ve been pursuing, &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;&lt;code&gt;impl&lt;/code&gt; specialization&lt;/a&gt; plays a key
role. That&amp;rsquo;s appealing because specialization is something we&amp;rsquo;ve long wanted for
other reasons, and is a natural deepening of our trait system. But it&amp;rsquo;s not
quite enough, by itself, to meet all of the constraints above.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to start by recapping the specialization design. Then I&amp;rsquo;ll explore two
competing avenues for building on specialization to meet the design constraints,
choose-your-own-adventure style. At the end, I&amp;rsquo;ll give my current opinions on
where we ought to go.&lt;/p&gt;

&lt;h2 id=&quot;specialization-as-proposed&quot;&gt;Specialization as proposed&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;Specialization&lt;/a&gt; allows overlapping trait (and inherent) impls, so long
as there is always a &amp;ldquo;most specific&amp;rdquo; impl that applies to a given concrete type.
The more general impl uses &lt;code&gt;default&lt;/code&gt; to signal which items can be specialized &amp;ndash;
sort of the opposite of &lt;code&gt;final&lt;/code&gt; in Java, or a bit like &lt;code&gt;virtual&lt;/code&gt; in C++.&lt;/p&gt;

&lt;p&gt;One of the major intended uses is to support true zero-cost abstraction, by
allowing you to customize the impl for specific cases to match performance of
non-abstract impls, while maintaining the abstraction for clients. To quote from
the RFC:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Traits today can provide static dispatch in Rust, but they can
still impose an abstraction tax. For example, consider the &lt;code&gt;Extend&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;IntoIterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Collections that implement the trait are able to insert data from arbitrary
iterators. Today, that means that the implementation can assume nothing about
the argument &lt;code&gt;iterable&lt;/code&gt; that it&amp;rsquo;s given except that it can be transformed into
an iterator. That means the code must work by repeatedly calling &lt;code&gt;next&lt;/code&gt; and
inserting elements one at a time.&lt;/p&gt;

&lt;p&gt;But in specific cases, like extending a vector with a slice, a much more
efficient implementation is possible &amp;ndash; and the optimizer isn&amp;rsquo;t always capable
of producing it automatically. In such cases, specialization can be used to get
the best of both worlds: retaining the abstraction of &lt;code&gt;extend&lt;/code&gt; while providing
custom code for specific cases.&lt;/p&gt;

&lt;p&gt;The design in this RFC relies on multiple, overlapping trait impls, so to take
advantage for &lt;code&gt;Extend&lt;/code&gt; we need to refactor a bit:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;IntoIterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The generic implementation&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;IntoIterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// the `default` qualifier allows this method to be specialized below&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// implementation using push (like today&amp;#39;s extend)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// A specialized implementation for slices&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// implementation using ptr::write (like push_all)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;

&lt;p&gt;Because the generic impl uses &lt;code&gt;default&lt;/code&gt; for its implementation of &lt;code&gt;extend&lt;/code&gt;, it&amp;rsquo;s
permitted to give a more specialized impl block that overrides it. (The block is
more specialized because it applies to a subset of the types the generic one
applies to.)&lt;/p&gt;

&lt;p&gt;A specialized impl doesn&amp;rsquo;t have to provide all the items for a trait; whatever
it doesn&amp;rsquo;t provide is automatically inherited from the generic impl it&amp;rsquo;s
specializing. And conversely, it can &lt;em&gt;only&lt;/em&gt; override items marked &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Going a bit farther, it&amp;rsquo;s possible to specialize not just impls for a trait, but
also &lt;em&gt;defaults&lt;/em&gt; for a trait. This is done via &lt;code&gt;partial impl&lt;/code&gt; blocks, which are
impls that provide some, but not all, of the items required by a trait. Again
quoting the RFC:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, consider a design for overloading &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;+=&lt;/code&gt;, such that
they are always overloaded together:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rhs&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_assign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, there&amp;rsquo;s no natural way to provide a default implementation of
&lt;code&gt;add_assign&lt;/code&gt;, since we do not want to restrict the &lt;code&gt;Add&lt;/code&gt; trait to &lt;code&gt;Clone&lt;/code&gt; data.&lt;/p&gt;

&lt;p&gt;The specialization design in this RFC also allows for &lt;em&gt;partial&lt;/em&gt; implementations,
which can provide specialized defaults without actually providing a full trait
implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// the `default` qualifier allows further specialization&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_assign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rhs&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This partial impl does &lt;em&gt;not&lt;/em&gt; mean that &lt;code&gt;Add&lt;/code&gt; is implemented for all &lt;code&gt;Clone&lt;/code&gt;
data, but jut that when you do impl &lt;code&gt;Add&lt;/code&gt; and &lt;code&gt;Self: Clone&lt;/code&gt;, you can leave off
&lt;code&gt;add_assign&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#[derive(Copy, Clone)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rhs&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// no fn add_assign necessary&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;

&lt;h3 id=&quot;a-small-addendum&quot;&gt;A small addendum&lt;/h3&gt;

&lt;p&gt;The specialization RFC touches on, but doesn&amp;rsquo;t actually specify, a way to
&amp;ldquo;access&amp;rdquo; the implementation you&amp;rsquo;re overriding (akin to &lt;code&gt;super&lt;/code&gt; in the OO world).&lt;/p&gt;

&lt;p&gt;For the sake of this post, I&amp;rsquo;ll assume we&amp;rsquo;ve added such a mechanism by way of a
UFCS-like use of &lt;code&gt;default&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// do some complicated stuff&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;About to `foo` on {:?}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is that the &lt;code&gt;default::&lt;/code&gt; prefix accessing the generic impl that&amp;rsquo;s being
overridden, and works like UFCS (in that methods become functions taking &lt;code&gt;self&lt;/code&gt;
explicitly).&lt;/p&gt;

&lt;p&gt;The details here aren&amp;rsquo;t so important, as long as specialization supports &lt;em&gt;some&lt;/em&gt;
mechanism like this (which was always the intent).&lt;/p&gt;

&lt;h2 id=&quot;ending-1-the-trait-based-approach&quot;&gt;Ending 1: the trait-based approach&lt;/h2&gt;

&lt;p&gt;It should already be clear that specialization has a connection to inheritance,
because items left off of a specialized impl are inherited from the impl
(partial or otherwise) it is specializing. As it turns out, that&amp;rsquo;s already
enough to code up something like traditional type hierarchies in OO
languages. You can get pretty far!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This general approach is, in some ways, inspired by
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/250&quot;&gt;eddyb and Kimundi&amp;rsquo;s proposal&lt;/a&gt;
from last time around, but using specialization rather than a targeted feature
for default refinement. And of course many of the fine points of the design
here have been explored by others in the community as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here&amp;rsquo;s an example, using a lightly simplified extract from Servo&amp;rsquo;s DOM
implementation.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Node ////////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// additional virtual methods for Node&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// non-virtual methods for Node&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_parent_of&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// additional methods here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Element /////////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_activatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// additional Element methods&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// non-virtual methods for Element&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nearest_activable_element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;class&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Activatable /////////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Activatable&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// moar methods&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_activatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// HtmlAnchorElement ///////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// moar fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;rel&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// HtmlImageElement ////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HtmlImageElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// moar fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;width&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;height&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hspace&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;vspace&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This example is following a basic pattern:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;ldquo;Abstract base classes&amp;rdquo; turn into traits&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Their virtual methods become methods in the traits (e.g. &lt;code&gt;parse_plain_attribute&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They will be virtually dispatched when using trait objects, and statically
dispatched when used directly on a type implementing the trait (as usual).
In practice that means that after the first virtual call, additional calls
on &lt;code&gt;self&lt;/code&gt; are statically-dispatched.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Their non-virtual methods become inherent methods for the trait, DST style
(e.g. &lt;code&gt;is_parent_of&lt;/code&gt;). These are always statically-dispatched. (Note: it may
be preferable to write these as extension traits with blanket impls, to gain
further static dispatch through monomorphization, at a cost in code size.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default implementations of methods can be done via &amp;hellip; defaulted methods!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&amp;ldquo;Concrete classes&amp;rdquo; turn into structs.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The structs implement all of the traits for the abstract base classes above them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In this case, &amp;ldquo;overriding&amp;rdquo; generally just means supplying an impl when a
default was available.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Methods can be overridden at any point in the hierarchy.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This is done via a blanket (partial) impl, like &lt;code&gt;partial impl&amp;lt;T: Element&amp;gt; Node for T&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When one abstract base class overrides its parent, it generally uses
&lt;code&gt;partial impl&lt;/code&gt;. This is because there are usually still some &amp;ldquo;abstract&amp;rdquo; aka
&amp;ldquo;pure virtual&amp;rdquo; methods for the parent (which are just required methods on
the trait).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If further overriding should be allowed, these (partial) impls should use
&lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For example, the &lt;code&gt;as_activatable&lt;/code&gt; method is overridden for &lt;code&gt;T:
Activatable&lt;/code&gt; with a &amp;ldquo;final&amp;rdquo; version that cannot be further overridden.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that&amp;rsquo;s it. This entire vision of OO-ish programming rests on using the
existing system of dynamic dispatch through traits, and gets reuse/inheritance
via specialization.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take stock of the design constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cheap field access from internal methods;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No&lt;/strong&gt;: traits have no way to talk about fields directly, and
accessors require virtual dispatch (much more expensive than a fixed offset).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;cheap dynamic dispatch of methods;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;: covered via the trait system.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;cheap downcasting;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sort of&lt;/strong&gt;: see the &lt;code&gt;as_activatable&lt;/code&gt; pattern. But not as fast as a type tag
check. (The latter can be encoded if we have fields, however.)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;thin pointers;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No&lt;/strong&gt;: trait objects use fat pointers.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;sharing of fields and methods between definitions;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt; for methods (via specialization), &lt;strong&gt;No&lt;/strong&gt; for fields.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;safe, i.e., doesn&amp;rsquo;t require a bunch of transmutes or other unsafe code to be usable;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;syntactically lightweight or implicit upcasting;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;, once we have it for super-traits in general (an already-slated,
highly desired, simple feature).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;calling functions through smart pointers, e.g. &lt;code&gt;fn foo(JSRef&amp;lt;T&amp;gt;, ...)&lt;/code&gt;;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;, via existing coercion/Deref mechanisms.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;static dispatch of methods;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;, as discussed avove.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;reusable constructor code at every level of the hierarchy;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No&lt;/strong&gt;, because fields are not addressed.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;fits well into the language, either by smoothly extending existing features,
or by adding orthogonal concepts.

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yes&lt;/strong&gt;: we didn&amp;rsquo;t have to add anything beyond specialization (which we&amp;rsquo;re
taking for granted here).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we essentially met all but two requirements: thin pointers, and field
access/inheritance. What&amp;rsquo;s the simplest way we could accommodate those?&lt;/p&gt;

&lt;h3 id=&quot;thin-pointers&quot;&gt;Thin pointers&lt;/h3&gt;

&lt;p&gt;Recall that today, trait objects are &amp;ldquo;fat pointers&amp;rdquo;: a pointer to some data, and
a pointer to a vtable containing methods for operating on that data.&lt;/p&gt;

&lt;p&gt;This representation is not an arbitrary choice. It goes hand-in-hand with an
important aspect of traits: you can implement a new trait for an already-defined
type. This makes traits quite unlike interfaces in languages like Java, C#, or
Scala, which have to be applied when you define a type. Traits are flexible bits
of glue that can be applied after the fact. But the tradeoff is that the vtable
cannot be part of the &lt;code&gt;Self&lt;/code&gt; type, at least not if you want separate
compilation. After all, the crate defining a &lt;code&gt;struct&lt;/code&gt; simply &lt;em&gt;does not know&lt;/em&gt;
what traits might eventually be applied.&lt;/p&gt;

&lt;p&gt;On the other hand, these fat pointers have a drawback: space overhead. In
particular, if you have a dense graph of trait objects that are pointing to each
other, &lt;em&gt;each pointer&amp;rsquo;s size is doubled&lt;/em&gt;, but the information being stored is
often redundant (and the relevant traits are often implemented up front). For
serious object graphs, this is a non-starter.&lt;/p&gt;

&lt;p&gt;In Rust, when faced with representation tradeoffs, we have a simple tool: the
&lt;code&gt;repr&lt;/code&gt; attribute. So we can address the desire for thin pointers to traits by
introducing &lt;code&gt;#[repr(thin)]&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#[repr(thin)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyThinTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyThinTrait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;take_thin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MyThinTrait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Applying &lt;code&gt;#[repr(thin)]&lt;/code&gt; to a trait like &lt;code&gt;MyThinTrait&lt;/code&gt; has a few implications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The representation of types like &lt;code&gt;&amp;amp;MyThinTrait&lt;/code&gt; (used in &lt;code&gt;take_thin&lt;/code&gt;) is a
single pointer, which points to a vtable followed by the data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can only implement a thin trait for types you define in your crate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you implement multiple thin traits for a given type, they must form a
hierarchy. That ensures consistent layout of the vtable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thin traits are a useful representation for Rust to offer regardless of any
notion of &amp;ldquo;inheritance&amp;rdquo;.&lt;/p&gt;

&lt;h3 id=&quot;incorporating-fields&quot;&gt;Incorporating fields&lt;/h3&gt;

&lt;p&gt;Now all that&amp;rsquo;s left to handle is fields. To get maximal performance, we need
some way for a trait to require that &lt;code&gt;Self&lt;/code&gt; provides specific fields at
&lt;em&gt;statically-known locations&lt;/em&gt; (which is true for genuine inheritance hierarchies
as one gets in languages like C++). In particular, accessing such fields through
a trait is no more expensive than accessing them directly through a known
struct: you just load the offset. But unlike a full struct definition, this only
requires the existence of a specific field at a specific location; it doesn&amp;rsquo;t
constrain other fields that might be available.&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;Note&lt;/em&gt;: it may also be desirable to support fields in traits at dynamic
offsets, which is still faster than a full dynamic dispatch, but that&amp;rsquo;s distinct
from the requirements set out at the beginning of the post.)&lt;/p&gt;

&lt;p&gt;In addition, it would be ideal if field definitions only have to be mentioned
once, not repeated in every trait and struct definition that is talking about them.&lt;/p&gt;

&lt;p&gt;There are likely a lot of ways we could accomplish these goals, but I&amp;rsquo;ll
highlight a few promising ones, in order of increasing complexity: struct
composition, struct inheritance, and trait fields.&lt;/p&gt;

&lt;h4 id=&quot;struct-composition&quot;&gt;Struct composition&lt;/h4&gt;

&lt;p&gt;There&amp;rsquo;s a very simple way, in today&amp;rsquo;s Rust, for one struct to contain all of the
information of another struct: simply include the other struct as a field!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;EventTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Note: this refers to the Node *trait*! see below.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first_child&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_child&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_sibling&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prev_sibling&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node_fields&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, &lt;code&gt;Element&lt;/code&gt; &amp;ldquo;inherits&amp;rdquo; the fields of &lt;code&gt;Node&lt;/code&gt; simply by embedding
them. This approach also neatly solves the problem of reusing constructors
across the hierarchy: a &lt;code&gt;Node&lt;/code&gt; here is already a partly-constructed &lt;code&gt;Element&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the remaining question is how to gain access to these fields in a
trait. Here&amp;rsquo;s one possibility:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is that a trait can list any number of super-structs (including
indirectly through super-traits), so long as those structs form a &lt;em&gt;composition
hierarchy&lt;/em&gt;: they must form a chain where each struct contains a leading field
whose type is the next struct (like with &lt;code&gt;ElementFields&lt;/code&gt; and &lt;code&gt;NodeFields&lt;/code&gt;
above). The chain then ends in the &lt;code&gt;Self&lt;/code&gt; type implementing the trait.&lt;/p&gt;

&lt;p&gt;So, to complete the DOM example, we&amp;rsquo;d have:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element_fields&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// internally, contains a leading NodeFields&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// moar fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When the trait is in scope, it allows direct access to the fields as if they had
been flattened into the struct:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parent_node_via_element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(A more verbose alternative might be some UFCS-style &lt;code&gt;&amp;lt;self as
NodeFields&amp;gt;::parent_node.clone()&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Of course, this proposal assumes that structs beginning with the same leading
field always lay that field out in the same way &amp;ndash; in particular, this rules out
reordering of the field. If we don&amp;rsquo;t want to make such a guarantee, we could
limit use of struct bounds to thin traits. Since thin traits are implemented for
structs in the same crate defining those structs, they can impose additional
representation constraints.&lt;/p&gt;

&lt;h4 id=&quot;struct-inheritance&quot;&gt;Struct inheritance&lt;/h4&gt;

&lt;p&gt;The above struct composition approach is, in some ways, pretty simple. It builds
directly on current patterns for building hierarchies of structs. But it is
perhaps &lt;em&gt;too&lt;/em&gt; targeted and narrow.&lt;/p&gt;

&lt;p&gt;A more expansive alternative is explicit struct inheritance. The basic idea here
is very simple:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;EventTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// implicitly contains all of NodeFields fields&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElementFields&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The initializer sytax for child structs would then permit either providing all
field explicitly, or extending from an instance of the parent structure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Style 1: all fields&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e1&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more NodeFields fields&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more ElementFields fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Style 2: using parent struct&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more NodeFields fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e2&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more ElementFields fields&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This covers the need for constructors at each level of the hierarchy. But what
about hooking into traits?&lt;/p&gt;

&lt;p&gt;With struct inheritance, we can treat structs &lt;em&gt;in general&lt;/em&gt; as something you can write in a bound, e.g.:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;take_node_descendant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// same as writing `trait Node where Self: NodeFields`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In all cases, using a struct as a bound like &lt;code&gt;T: NodeFields&lt;/code&gt; means that &lt;code&gt;T&lt;/code&gt;
&lt;em&gt;must inherit from&lt;/em&gt; &lt;code&gt;NodeFields&lt;/code&gt;. For traits, that would immediately give you
access to the fields, and would impose the fixed static offset requirement
(giving maximal performance when accessing those fields). That is, given the
definition of &lt;code&gt;Node&lt;/code&gt; above, if we have &lt;code&gt;n: &amp;amp;Node&lt;/code&gt;, we could write
&lt;code&gt;n.parent_node&lt;/code&gt; and that would compile as if we had &lt;code&gt;n: NodeFields&lt;/code&gt; instead.
Because inheritance is explicit at the point of struct definition, we don&amp;rsquo;t have
the layout worries we had with struct composition; we can lay out child structs
so that their parents are always consistent prefixes.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s plausible that struct inheritance is generally useful outside of OO-like
hierarchies; certainly it avoids long chains like
&lt;code&gt;my_struct.parent1.parent2.actual_field&lt;/code&gt; one gets when using struct composition
at scale, although the previous proposal does that as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While it&amp;rsquo;s not necessary to address our goals here, you could also imagine
adding coercions from &lt;code&gt;&amp;amp;ElementFields&lt;/code&gt; to &lt;code&gt;&amp;amp;NodeFields&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;trait-fields&quot;&gt;Trait fields&lt;/h4&gt;

&lt;p&gt;Finally, we could imagine instead adding fields directly to traits:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This raises a few questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What do you have to say in an &lt;code&gt;impl&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Can the fields be hooked up arbitrarily to &lt;code&gt;Self&lt;/code&gt;, or must they form a prefix?&lt;/li&gt;
&lt;li&gt;Can you avoid writing out copies of the field definitions in every struct in
the hierarchy?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many ways we might answer these questions, and I won&amp;rsquo;t try to fully
explore the space here. But a simple option is to say that the fields must form
a prefix of the fields of &lt;code&gt;Self&lt;/code&gt;, and you don&amp;rsquo;t have to say anything in an
impl. Furthermore, if you write:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HtmlAnchorElement&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// moar fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;you automatically include the fields mentioned in the &lt;code&gt;Element&lt;/code&gt; trait (including
those from its super-trait &lt;code&gt;Node&lt;/code&gt;) as leading fields in the struct.&lt;/p&gt;

&lt;p&gt;If we furthermore want to provide reusable constructors at every level of the
hierarchy, we have to &lt;em&gt;also&lt;/em&gt; include some way of naming these intermediate
structs and using them in initaializers, e.g.:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;::&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;::&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_node&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more Node fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;::&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;::&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more Element fields&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;: &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// more HtmlAnchorElement fields&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The main advantage of this approach over the previous ones is that you avoid the
need to explicitly name structs corresponding to &amp;ldquo;abstract base classes&amp;rdquo; (like
&lt;code&gt;NodeFields&lt;/code&gt; and &lt;code&gt;ElementFields&lt;/code&gt;); instead, these are implicit via the
&lt;code&gt;::struct&lt;/code&gt; associated type. But there remain questions about using this syntax
more flexibly, for mapping trait fields in more arbitrary ways to struct fields,
without giving up performance in the fixed-offset case.&lt;/p&gt;

&lt;p&gt;A downside is the question of &lt;em&gt;visibility&lt;/em&gt;: currently all items in a trait are
considered public, but this is not necessarily desirable for fields, so we&amp;rsquo;d
likely need some way to express visibility choices. Fitting that into the
existing syntax is not going to be easy. Whereas with struct composition or
inheritance, it just &amp;ldquo;falls out&amp;rdquo; of the struct definitions.&lt;/p&gt;

&lt;h2 id=&quot;ending-2-the-enum-based-approach&quot;&gt;Ending 2: the enum-based approach&lt;/h2&gt;

&lt;p&gt;Whew! So all of the proposals we just saw took traits as the sole source of
dynamic dispatch and tried to close remaining gaps through slight enrichments of
traits and structs.&lt;/p&gt;

&lt;p&gt;A radically different approach takes the perspective that Rust already has &lt;em&gt;two&lt;/em&gt;
forms of dynamic dispatch today &amp;ndash; traits and &lt;em&gt;match expressions&lt;/em&gt; &amp;ndash;
corresponding to &amp;ldquo;open&amp;rdquo; (extensible) and closed sets of types respectively.&lt;/p&gt;

&lt;p&gt;Niko Matsakis outlined a substantial expansion to enums in
&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2015/08/20/virtual-structs-part-3-bringing-enums-and-structs-together/&quot;&gt;his recent post&lt;/a&gt;,
which is part of the original design he, Nick Cameron, and I had been working
on. The missing piece in that post is how to tie it together with specialization
and thereby get something more like inheritance.&lt;/p&gt;

&lt;p&gt;I won&amp;rsquo;t recap the whole proposal here (it&amp;rsquo;s worth a read in full!), but in short
it makes enums into full-blown hierarchies, defining types at every level (and
structs at the leaves):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// where this node is positioned after layout&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TextElement&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ParagraphElement&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given such a hierarchy, you can write:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;takes_any_node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That is, you can use an enum as a &lt;em&gt;bound&lt;/em&gt;, which stands for &amp;ldquo;any type under this
point in the hierarchy&amp;rdquo;, but will be statically resolved via monomorphization.&lt;/p&gt;

&lt;p&gt;This immediately opens the door to specialization for reuse:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;class&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;rel&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This pattern of specialization, trying to match the example at the beginning of
the post, &lt;em&gt;almost&lt;/em&gt; works: if you call &lt;code&gt;parse_plain_attribute&lt;/code&gt; on an
&lt;code&gt;HtmlAnchorElement&lt;/code&gt;, you&amp;rsquo;ll get the correct behavior.&lt;/p&gt;

&lt;p&gt;But if you&amp;rsquo;ve upcasted to an &lt;code&gt;Element&lt;/code&gt; or &lt;code&gt;Node&lt;/code&gt;, &lt;em&gt;the behavior will revert to
the defaults for those types&lt;/em&gt;! That&amp;rsquo;s because you&amp;rsquo;re not getting dynamic
dispatch here, which for enums we said should go through &lt;code&gt;match&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The solution is to instead write the code as follows:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;class&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;rel&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_serialized_tokenlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we&amp;rsquo;re now using specialization &lt;em&gt;without any explicit blanket
impls&lt;/em&gt;. In this proposal, when the &lt;code&gt;Self&lt;/code&gt; type is an enum, it&amp;rsquo;s &lt;em&gt;as if&lt;/em&gt; you had
written a blanket impl like the ones above, except that when the function is
invoked on the enum type, it will use a &lt;code&gt;match&lt;/code&gt; to dispatch to most specialized
implementation. That is, it&amp;rsquo;s as if we&amp;rsquo;d written the following for &lt;code&gt;Node&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Fully generic *default* impl&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specialized impl for the `Node` type itself&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// NOTE: `this` has a different type in each arm!&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_plain_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And of course:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s nicer to write the impls directly against the enum type than using an explicit blanket;&lt;/li&gt;
&lt;li&gt;This is also almost certainly the behavior you wanted anyway: you always get
the most specific impl, whether dynamically or statically dispatched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the desugaring &lt;em&gt;only&lt;/em&gt; triggers when &lt;code&gt;Self&lt;/code&gt; is a direct enum type.&lt;/p&gt;

&lt;h2 id=&quot;getting-opinionated&quot;&gt;Getting opinionated&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;ve stuck with me until this point, first of all: thanks! That was a long
haul.&lt;/p&gt;

&lt;p&gt;So, what should we do? To recap, we have two major routes, both of which start
with specialization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first takes a minimalistic approach, adding a couple of minor
(and independently motivated) features to traits and structs to get to
our goal. There are a few options for dealing with fields, in
particular.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second combines specialization with another major set of enhancements to
enums, which are also independently motivated, but are much more complex. It
then adds a bit of sugar on top to tie the two together.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trait approach allows for open-ended hierarchies (extensible by downstream
crates), while the enum approach is closed. On the flip side, that means that
downcasting can be somewhat more awkward (and is a code smell) for the trait
approach, while it&amp;rsquo;s completely natural (just a &lt;code&gt;match&lt;/code&gt;) for the enum approach.&lt;/p&gt;

&lt;p&gt;Initially, I was very excited about the latter, enum-centric approach, because
the work on enum hierarchies seems like such a natural extension to Rust. But I
am worried about a few things. First of all, getting the proposal that Niko laid
out to work will require substantially reworking our type inference to account
for subtyping. Making this happen &lt;em&gt;backwards-compatibly&lt;/em&gt; with our existing enums
is not going to be easy, and may not even be possible. It also makes subtyping
much more important in Rust, which is likely to be a &lt;em&gt;complexity multiplier&lt;/em&gt; as
it interacts with every other aspect of the type system.  There are also various
dark syntactic corners that come out of the partial unification of enums and
structs (e.g., how do you specify visibility of shared fields in an in-line
enum?)  Finally, the key bit of sugar at the apex that ties enum hierarchies and
specialization together is a bit subtle, and only covers the most obvious cases
of &lt;code&gt;Self&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In short, I see a lot of known risks, and worry about unknown risks, with the
enum hierarchy route.&lt;/p&gt;

&lt;p&gt;In contrast, the struct/trait-centric proposals feel much less risky; they don&amp;rsquo;t
introduce fundamental new complexity that interacts with the rest of the type
system, and they have a smaller overall footprint. I also like the way that
specialization is used very explicitly to get inheritance, rather than through
a layer of sugar on top.&lt;/p&gt;

&lt;p&gt;And of the struct proposals, I think that struct inheritance strikes the best
balance between minimalism, flexibility, and &amp;ldquo;fit&amp;rdquo; with the existing language.&lt;/p&gt;

&lt;p&gt;The main downside of my preferred struct/trait approach is that there&amp;rsquo;s some
amount of boilerplate: &amp;ldquo;abstract base classes&amp;rdquo; like &lt;code&gt;Node&lt;/code&gt; turn into a &lt;code&gt;Node&lt;/code&gt;
trait and a &lt;code&gt;NodeFields&lt;/code&gt; struct. That detail could easily be hidden behind a
macro, but it might also argue in favor of the more complex traits-with-fields
variant.&lt;/p&gt;

&lt;p&gt;(I should mention: it&amp;rsquo;s possible that in the long run, we&amp;rsquo;ll want subtyping and
not just coercions with any approach we take. But still, enum hierarchies want
this to happen for our existing enums in a way that may require breakage.)&lt;/p&gt;

&lt;p&gt;If we &lt;em&gt;do&lt;/em&gt; go with a struct/trait approach, I think we should carefully check
that the design is compatible with a future expansion of enums along the lines
Niko laid out in his post, since we may still want enum hierarchies in the long
run. I&amp;rsquo;ve given this a fair amount of thought, and likewise think that struct
inheritance is the best fit. In particular, it could replace the somewhat
magical proposal for &amp;ldquo;common fields&amp;rdquo; (which included an associated
&lt;code&gt;MyEnum::struct&lt;/code&gt; type).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lock-freedom without garbage collection</title>
   <link href="http://aturon.github.io/blog/2015/08/27/epoch/"/>
   <updated>2015-08-27T00:00:00-07:00</updated>
   <id>http://aturon.github.io/2015/08/27/epoch</id>
   <content type="html">&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s widespread folklore that one advantage of garbage collection is the ease of
building high-performance lock-free data structures. Manual memory management
for these data structures is not easy, and a GC makes it trivial.&lt;/p&gt;

&lt;p&gt;This post shows that, using Rust, it&amp;rsquo;s possible to build a memory management API
for concurrent data structures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes it as easy to implement lock-free data structures as a GC does;&lt;/li&gt;
&lt;li&gt;Statically safeguards against misuse of the memory management scheme;&lt;/li&gt;
&lt;li&gt;Has overhead competitive with (and more predictable than) GC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the benchmarks I show below, Rust is able to easily beat a Java
lock-free queue implementation, with an implementation that&amp;rsquo;s as easy
to write.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve implemented &amp;ldquo;epoch-based memory reclamation&amp;rdquo; in a new library called
&lt;a href=&quot;https://github.com/aturon/crossbeam&quot;&gt;Crossbeam&lt;/a&gt;, which is ready to use in for
your own data structures today. This post covers some background on lock-free
data structures, the epoch algorithm, and the entire Rust API.&lt;/p&gt;

&lt;h3 id=&quot;contents&quot;&gt;Contents&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#benchmarks&quot;&gt;Benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lock-free-data-structures&quot;&gt;Lock-free data structures&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#treiber&amp;#x27;s-stack&quot;&gt;Treiber&amp;rsquo;s stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#the-problem&quot;&gt;The problem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#epoch-based-reclamation&quot;&gt;Epoch-based reclamation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#the-rust-api&quot;&gt;The Rust API&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#guard&quot;&gt;&lt;code&gt;Guard&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#owned-and-shared-pointers&quot;&gt;&lt;code&gt;Owned&lt;/code&gt; and &lt;code&gt;Shared&lt;/code&gt; pointers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#atomic&quot;&gt;&lt;code&gt;Atomic&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#freeing-memory&quot;&gt;Freeing memory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#treiber&amp;#x27;s-stack-on-epochs&quot;&gt;Treiber&amp;rsquo;s stack on epochs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#managing-garbage&quot;&gt;Managing garbage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#the-road-ahead&quot;&gt;The road ahead&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;

&lt;p&gt;Before looking in depth at the API design and usage for epoch reclamation, let&amp;rsquo;s
cut right to the chase: performance.&lt;/p&gt;

&lt;p&gt;To test the overhead my Crossbeam implementation relative to a full
GC, I implemented a basic lock-free queue (a vanilla
&lt;a href=&quot;http://www.research.ibm.com/people/m/michael/podc-1996.pdf&quot;&gt;Michael-Scott queue&lt;/a&gt;)
on top of it, and built the same queue in Scala. In general, JVM-based
languages are a good test case for the &amp;ldquo;good GC&amp;rdquo; path toward lock-free
data structures.&lt;/p&gt;

&lt;p&gt;In addition to these implementations, I compared against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A more efficient &amp;ldquo;segmented&amp;rdquo; queue that allocates nodes with multiple slots. I
wrote this queue in Rust, on top of Crossbeam.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Rust single-threaded queue protected by a mutex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The java.util.concurrent queue implementation (ConcurrentLinkedQueue), which
is a tuned variant of the Michael-Scott queue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tested these queues in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A multi-producer, single-consumer (MPSC) scenario in which two threads
repeatedly send messages and one thread receives them, both in a tight loop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A multi-producer, multi-consumer (MPMC) scenario in which two threads send and
two thread receive in a tight loop.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmarks like these are fairly typical for measuring the scalability of a
lock-free data structure under &amp;ldquo;contention&amp;rdquo; &amp;ndash; multiple threads competing to
make concurrent updates simultaenously. &lt;strong&gt;There are many variations that should be
benchmarked when building a production queue implementation; the goal here is
just to gauge the ballpark overhead of the memory management scheme&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the MPSC test, I also compared against the algorithm used in Rust&amp;rsquo;s built-in
channels, which is optimized for this scenario (and hence doesn&amp;rsquo;t support MPMC).&lt;/p&gt;

&lt;p&gt;The machine is a 4 core 2.6Ghz Intel Core i7 with 16GB RAM.&lt;/p&gt;

&lt;p&gt;Here are the results, given in nanosecond per message (lower is better):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/public/bench-mpsc.png&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/public/bench-mpmc.png&quot;&gt;&lt;/p&gt;

&lt;h3 id=&quot;analysis&quot;&gt;Analysis&lt;/h3&gt;

&lt;p&gt;The main takeaway is that the Crossbeam implementation &amp;ndash; which has not been
tuned &amp;ndash; is competitive in all cases. It&amp;rsquo;s possible to do better on both the
Rust and JVM sides by using more clever or specialized queues, but these results
show at least that the overhead of epochs is reasonable.&lt;/p&gt;

&lt;p&gt;Notice that the Java/Scala versions fare much better in the MPMC test than they do in
MPSC test. Why is that?&lt;/p&gt;

&lt;p&gt;The answer is simple: garbage collection. In the MPSC test, the producers tend
to overrun the consumer over time, meaning that the amount of data in the queue
slowly grows. That in turn increases the cost of each garbage collection, which
involves walking over the live data set.&lt;/p&gt;

&lt;p&gt;In the epoch scheme, by contrast, the cost of managing garbage is relatively
fixed: it&amp;rsquo;s proportional to the number of threads, not the amount of live
data. This turns out to yield both better and more consistent/predictable
performance.&lt;/p&gt;

&lt;p&gt;Finally, one comparison I did not include on the chart (because it would dwarf
the others) was using a &lt;code&gt;Mutex&lt;/code&gt; around a deque in Rust. For the MPMC test,
performance was around 3040ns/operation, over 20x slower than the Crossbeam
implementation. This is a vivid demonstration of why lock-free data structure
are important &amp;ndash; so let&amp;rsquo;s start by diving into what those are.&lt;/p&gt;

&lt;h2 id=&quot;lock-free-data-structures&quot;&gt;Lock-free data structures&lt;/h2&gt;

&lt;p&gt;When you want to use (and mutate) a data structure from many concurrent threads,
you need synchronization. The simplest solution is a global lock &amp;ndash; in Rust,
wrapping the entire data structure in
a &lt;a href=&quot;http://static.rust-lang.org/doc/master/std/sync/struct.Mutex.html&quot;&gt;&lt;code&gt;Mutex&lt;/code&gt;&lt;/a&gt; and
calling it a day.&lt;/p&gt;

&lt;p&gt;Problem is, that kind of &amp;ldquo;coarse-grained&amp;rdquo; synchronization means that multiple
threads always need to coordinate when accessing a data structure, even if they
were accessing disjoint pieces of it. It also means that even when a thread is
only trying to read, it must &lt;em&gt;write&lt;/em&gt;, by updating the lock state &amp;ndash; and since
the lock is a global point of communication, these writes lead to a large amount
of cache invalidation traffic. Even if you use a lot of locks at a finer grain,
there are other
&lt;a href=&quot;https://en.wikipedia.org/wiki/Lock_%28computer_science%29#Disadvantages&quot;&gt;hazards&lt;/a&gt;
like &lt;a href=&quot;https://en.wikipedia.org/wiki/Deadlock&quot;&gt;deadlock&lt;/a&gt; and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Priority_inversion&quot;&gt;priority inversion&lt;/a&gt;, and you
often still leave performance on the table.&lt;/p&gt;

&lt;p&gt;A more radical alternative is &lt;em&gt;lock-free data structures&lt;/em&gt;, which use atomic
operations to make direct changes to the data structure without further
synchronization. They are often faster, more scalable, and more robust than
lock-based designs.&lt;/p&gt;

&lt;p&gt;I won&amp;rsquo;t try to give a full tutorial to lock-free programming in this post, but a
key point is that, if you don&amp;rsquo;t have global synchronization, it&amp;rsquo;s very difficult
to tell when you can free memory. Many published algorithms basically assume a
garbage collector or some other means of reclaiming memory. So before lock-free
concurrency can really take off in Rust, we need a story for memory reclamation
&amp;ndash; and that&amp;rsquo;s what this blog post is all about.&lt;/p&gt;

&lt;h3 id=&quot;treibers-stack&quot;&gt;Treiber&amp;rsquo;s stack&lt;/h3&gt;

&lt;p&gt;To make things more concrete, let&amp;rsquo;s look at the &amp;ldquo;Hello world&amp;rdquo; of lock-free data
structures: Treiber&amp;rsquo;s stack. The stack is represented as a singly-linked list,
with all modifications happening on the &lt;code&gt;head&lt;/code&gt; pointer:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#![feature(box_raw)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;sync&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;atomic&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;AtomicPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;sync&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;atomic&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Ordering&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;AtomicPtr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;AtomicPtr&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s easiest to start with popping. To pop, you just loop, taking a snapshot of
the &lt;code&gt;head&lt;/code&gt; and doing a compare-and-swap replacing the snapshot with its next
pointer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that &lt;code&gt;compare_and_swap&lt;/code&gt; atomically changes the value of an &lt;code&gt;AtomicPtr&lt;/code&gt;
from an old value to a new value, if the old value matched. Also, for this post
you can safely ignore the &lt;code&gt;Acquire&lt;/code&gt;, &lt;code&gt;Release&lt;/code&gt; and &lt;code&gt;Relaxed&lt;/code&gt; labels if you&amp;rsquo;re
not familiar with them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// take a snapshot&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// we observed the stack empty&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// if snapshot is still good, update from `head` to `next`&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare_and_swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// **NOTE**: leaks the node!&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;ptr::read&lt;/code&gt; function is Rust&amp;rsquo;s way of extracting ownership of data without
static or dynamic tracking. Here we are using the atomicity of
&lt;code&gt;compare_and_swap&lt;/code&gt; to guarantee that only one thread will call &lt;code&gt;ptr::read&lt;/code&gt; &amp;ndash;
and as we&amp;rsquo;ll see, this implementation never frees &lt;code&gt;Node&lt;/code&gt;s, so the destructor on
&lt;code&gt;data&lt;/code&gt; is never invoked. Those two facts together make our use of &lt;code&gt;ptr::read&lt;/code&gt;
safe.&lt;/p&gt;

&lt;p&gt;Pushing is similar:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// allocate the node, and immediately turn it into a *mut pointer&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;into_raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// snapshot current head&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// update `next` pointer with snapshot&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// if snapshot is still good, link in new node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare_and_swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;If we had coded the above in a language with a GC, we&amp;rsquo;d be done. But as written
in Rust, it leaks memory. In particular, the &lt;code&gt;pop&lt;/code&gt; implementation doesn&amp;rsquo;t
attempt to free the node pointer after it has removed it from the stack.&lt;/p&gt;

&lt;p&gt;What would go wrong if we did just that?&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// free the node&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;from_raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is that other threads could also be running &lt;code&gt;pop&lt;/code&gt; at the same
time. Those threads could have a snapshot of the current head; nothing would
prevent them from reading &lt;code&gt;(*head).next&lt;/code&gt; on that snapshot just after we
deallocate the node they&amp;rsquo;re pointing to &amp;ndash; a use-after-free bug in the making!&lt;/p&gt;

&lt;p&gt;So that&amp;rsquo;s the crux. We want to use lock-free algorithms, but many follow a
similar pattern to the stack above, leaving us with no clear point where it&amp;rsquo;s
safe to deallocate a node. What now?&lt;/p&gt;

&lt;h2 id=&quot;epoch-based-reclamation&quot;&gt;Epoch-based reclamation&lt;/h2&gt;

&lt;p&gt;There are a few non-GC-based ways of managing memory for lock-free code, but
they all come down to the same core observations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;There are two sources of reachability at play &amp;ndash; the data structure, and the
snapshots in threads accessing it. Before we delete a node, we need to know that
it cannot be reached in either of these ways.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once a node has been unlinked from the data structure, no &lt;em&gt;new&lt;/em&gt; snapshots
reaching it will be created.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most elegant and promising reclamation schemes is
&lt;a href=&quot;https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf&quot;&gt;Keir Fraser&amp;rsquo;s &lt;em&gt;epoch-based reclamation&lt;/em&gt;&lt;/a&gt;,
which was described in very loose terms in his PhD thesis.&lt;/p&gt;

&lt;p&gt;The basic idea is to stash away nodes that have been unlinked from the data
structure (the first source of reachability) until they can be safely deleted.
Before we can delete a stashed node, we need to know that all threads that were
accessing the data structure at the time have finished the operation they were
performing. By observation 2 above, that will imply that there are no longer any
snapshots left (since no new ones could have been created in the meantime).  The
hard part is doing all of this without much synchronization.  Otherwise, we lose
the benefit that lock-freedom was supposed to bring in the first place!&lt;/p&gt;

&lt;p&gt;The epoch scheme works by having:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A global epoch counter (taking on values 0, 1, and 2);&lt;/li&gt;
&lt;li&gt;A global list of garbage for each epoch;&lt;/li&gt;
&lt;li&gt;An &amp;ldquo;active&amp;rdquo; flag for each thread;&lt;/li&gt;
&lt;li&gt;An epoch counter for each thread.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The epochs are used to discover when garbage can safely be freed, because no
thread can reach it. &lt;strong&gt;Unlike traditional GC, this does not require walking
through live data&lt;/strong&gt;; it&amp;rsquo;s purely a matter of checking epoch counts.&lt;/p&gt;

&lt;p&gt;When a thread wants to perform an operation on the data structure, it first sets
its &amp;ldquo;active&amp;rdquo; flag, and then updates its local epoch to match the global one. If
the thread removes a node from the data structure, it adds that node to the
garbage list for the current global epoch. (Note: it&amp;rsquo;s very important that the
garbage go into the &lt;em&gt;current&lt;/em&gt; global epoch, not the previous local snapshot.)
When it completes its operation, it clears the &amp;ldquo;active&amp;rdquo; flag.&lt;/p&gt;

&lt;p&gt;To try to collect the garbage (which can be done at any point), a thread walks
over the flags for all participating threads, and checks whether all active
threads are in the current epoch. If so, it can attempt to increment the global
epoch (modulo 3). If the increment succeeds, the garbage from &lt;em&gt;two&lt;/em&gt; epochs ago
can be freed.&lt;/p&gt;

&lt;p&gt;Why do we need three epochs? Because &amp;ldquo;garbage collection&amp;rdquo; is done concurrently,
it&amp;rsquo;s possible for threads to be in one of two epochs at any time (the &amp;ldquo;old&amp;rdquo; one,
and the &amp;ldquo;new&amp;rdquo; one). But because we check that all active threads are in the old
epoch before incrementing it, we are guaranteed that no active threads are in
the third epoch.&lt;/p&gt;

&lt;p&gt;This scheme is carefully designed so that most of the time, threads touch data
that is already in cache or is (usually) thread-local. Only doing &amp;ldquo;GC&amp;rdquo; involves
changing the global epoch or reading the epochs of other threads. The epoch
approach is also algorithm-agnostic, easy to use, and its performance is
&lt;a href=&quot;http://csng.cs.toronto.edu/publication_files/0000/0159/jpdc07.pdf&quot;&gt;competitive with other approaches&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It also turns out to be a great match for Rust&amp;rsquo;s ownership system.&lt;/p&gt;

&lt;h2 id=&quot;the-rust-api&quot;&gt;The Rust API&lt;/h2&gt;

&lt;p&gt;We want the Rust API to reflect the basic principles of epoch-based reclamation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When operating on a shared data structure, a thread must always be in its
&amp;ldquo;active&amp;rdquo; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a thread is active, all data read out of the data structure will remain
allocated until the thread becomes inactive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll leverage Rust&amp;rsquo;s ownership system &amp;ndash; in particular, ownership-based
resource management (aka RAII) &amp;ndash; to capture these constraints directly in the
type signatures of an epoch API. This will in turn help ensure we use epoch
management correctly.&lt;/p&gt;

&lt;h3 id=&quot;guard&quot;&gt;&lt;code&gt;Guard&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;To operate on a lock-free data structure, you first acquire a &lt;em&gt;guard&lt;/em&gt;, which
is an owned value that represents your thread being active:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;pin&lt;/code&gt; function marks the thread as active, loads the global epoch, and may
try to perform GC (detailed a bit later in the post). The destructor for
&lt;code&gt;Guard&lt;/code&gt;, on the other hand, exits epoch management by marking the thread
inactive.&lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;Guard&lt;/code&gt; represents &amp;ldquo;being active&amp;rdquo;, a borrow &lt;code&gt;&amp;amp;&amp;#39;a Guard&lt;/code&gt; guarantees
that the thread is active for the entire lifetime &lt;code&gt;&amp;#39;a&lt;/code&gt; &amp;ndash; exactly what we need
to bound the lifetime of the snapshots taken in a lock-free algorithm.&lt;/p&gt;

&lt;p&gt;To put the &lt;code&gt;Guard&lt;/code&gt; to use, Crossbeam provides a set of three pointer types meant to work together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Owned&amp;lt;T&amp;gt;&lt;/code&gt;, akin to &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;, which points to uniquely-owned data that has
not yet been published in a concurrent data structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Shared&amp;lt;&amp;#39;a, T&amp;gt;&lt;/code&gt;, akin to &lt;code&gt;&amp;amp;&amp;#39;a T&lt;/code&gt;, which points to shared data that may or may
not be reachable from a data structure, but it guaranteed not to be freed
during lifetime &lt;code&gt;&amp;#39;a&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Atomic&amp;lt;T&amp;gt;&lt;/code&gt;, akin to &lt;code&gt;std::sync::atomic::AtomicPtr&lt;/code&gt;, which provides atomic
updates to a pointer using the &lt;code&gt;Owned&lt;/code&gt; and &lt;code&gt;Shared&lt;/code&gt; types, and connects them
to a &lt;code&gt;Guard&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll look at each of these in turn.&lt;/p&gt;

&lt;h3 id=&quot;owned-and-shared-pointers&quot;&gt;&lt;code&gt;Owned&lt;/code&gt; and &lt;code&gt;Shared&lt;/code&gt; pointers&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Owned&lt;/code&gt; pointer has an interface nearly identical to &lt;code&gt;Box&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Deref&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DerefMut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;Shared&amp;lt;&amp;#39;a, T&amp;gt;&lt;/code&gt; pointer is similar to &lt;code&gt;&amp;amp;&amp;#39;a T&lt;/code&gt; &amp;ndash; it is &lt;code&gt;Copy&lt;/code&gt; &amp;ndash; but it
dereferences to a &lt;code&gt;&amp;amp;&amp;#39;a T&lt;/code&gt;. This is a somewhat hacky way of conveying that the
lifetime of the pointer it provides is in fact &lt;code&gt;&amp;#39;a&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Deref&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unlike &lt;code&gt;Owned&lt;/code&gt;, there is no way to create a &lt;code&gt;Shared&lt;/code&gt; pointer directly. Instead,
&lt;code&gt;Shared&lt;/code&gt; pointers are acquired by reading from an &lt;code&gt;Atomic&lt;/code&gt;, as we&amp;rsquo;ll see
next.&lt;/p&gt;

&lt;h3 id=&quot;atomic&quot;&gt;&lt;code&gt;Atomic&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The heart of the library is &lt;code&gt;Atomic&lt;/code&gt;, which provides atomic access to a
(nullable) pointer, and connects all the other types of the library together:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;/// Create a new, null atomic pointer.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;ll look at operations one at a time, since the signatures are somewhat subtle.&lt;/p&gt;

&lt;h4 id=&quot;loading&quot;&gt;Loading&lt;/h4&gt;

&lt;p&gt;First, loading from an &lt;code&gt;Atomic&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to perform the load, we must pass in a borrow of a &lt;code&gt;Guard&lt;/code&gt;. As
explained above, this is a way of guaranteeing that the thread is active for the
entire lifetime &lt;code&gt;&amp;#39;a&lt;/code&gt;. In return, you get an optional &lt;code&gt;Shared&lt;/code&gt; pointer back
(&lt;code&gt;None&lt;/code&gt; if the &lt;code&gt;Atomic&lt;/code&gt; is currently null), with lifetime tied to the guard.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s interesting to compare this to the standard library&amp;rsquo;s &lt;code&gt;AtomicPtr&lt;/code&gt;
interface, where &lt;code&gt;load&lt;/code&gt; returns a &lt;code&gt;*mut T&lt;/code&gt;. Due to the use of epochs, we&amp;rsquo;re able
to guarantee safe dereferencing of the pointer within &lt;code&gt;&amp;#39;a&lt;/code&gt;, whereas with
&lt;code&gt;AtomicPtr&lt;/code&gt; all bets are off.&lt;/p&gt;

&lt;h4 id=&quot;storing&quot;&gt;Storing&lt;/h4&gt;

&lt;p&gt;Storing is a bit more complicated because of the multiple pointer types in play.&lt;/p&gt;

&lt;p&gt;If we simply want to write an &lt;code&gt;Owned&lt;/code&gt; pointer or a null value, we do not even
need the thread to be active. We are just transferring ownership &lt;em&gt;into&lt;/em&gt; the data
structure, and don&amp;rsquo;t need any assurance about the lifetimes of pointers:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sometimes, though, we want to transfer ownership into the data structure and
immediately acquire a shared pointer to the transferred data &amp;ndash; for example,
because we want to add additional links to the same node in the data
structure. In that case, we&amp;rsquo;ll need to tie the lifetime to a guard:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_and_ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that the runtime representation of &lt;code&gt;val&lt;/code&gt; and the return value is exactly
the same &amp;ndash; we&amp;rsquo;re passing a pointer in, and getting the same pointer out. But
the &lt;em&gt;ownership&lt;/em&gt; situation from Rust&amp;rsquo;s perspective changes radically in this step.&lt;/p&gt;

&lt;p&gt;Finally, we can store a shared pointer back into the data structure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This operation does not require a guard, because we&amp;rsquo;re not learning any new
information about the lifetime of a pointer.&lt;/p&gt;

&lt;h4 id=&quot;cas&quot;&gt;CAS&lt;/h4&gt;

&lt;p&gt;Next we have a similar family of compare-and-set operations. The simplest case
is swapping a &lt;code&gt;Shared&lt;/code&gt; pointer with a fresh &lt;code&gt;Owned&lt;/code&gt; one:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As with &lt;code&gt;store&lt;/code&gt;, this operation does not require a guard; it produces no new
lifetime information. The &lt;code&gt;Result&lt;/code&gt; indicates whether the CAS succeeded; if not,
ownership of the &lt;code&gt;new&lt;/code&gt; pointer is returned to the caller.&lt;/p&gt;

&lt;p&gt;We then have an analog to &lt;code&gt;store_and_ref&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cas_and_ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, on a successful CAS we acquire a &lt;code&gt;Shared&lt;/code&gt; pointer to the data we
inserted.&lt;/p&gt;

&lt;p&gt;Finally, we can replace one &lt;code&gt;Shared&lt;/code&gt; pointer with another:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cas_shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                             &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The boolean return value is &lt;code&gt;true&lt;/code&gt; when the CAS is successful.&lt;/p&gt;

&lt;h3 id=&quot;freeing-memory&quot;&gt;Freeing memory&lt;/h3&gt;

&lt;p&gt;Of course, all of the above machinery is in service of the ultimate goal:
actually freeing memory that is no longer reachable. When a node has been
de-linked from the data structure, the thread that delinked it can inform its
&lt;code&gt;Guard&lt;/code&gt; that the memory should be reclaimed:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Guard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unlinked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This operation adds the &lt;code&gt;Shared&lt;/code&gt; pointer to the appropriate garbage list,
allowing it to be freed two epochs later.&lt;/p&gt;

&lt;p&gt;The operation is unsafe because it is asserting that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;Shared&lt;/code&gt; pointer is not reachable from the data structure,&lt;/li&gt;
&lt;li&gt;no other thread will call &lt;code&gt;unlinked&lt;/code&gt; on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, though, other threads &lt;em&gt;may&lt;/em&gt; continue to reference this &lt;code&gt;Shared&lt;/code&gt;
pointer; the epoch system will ensure that no threads are doing so by the time
the pointer is actually freed.&lt;/p&gt;

&lt;p&gt;There is no particular connection between the lifetime of the &lt;code&gt;Shared&lt;/code&gt; pointer
here and the &lt;code&gt;Guard&lt;/code&gt;; if we have a reachable &lt;code&gt;Shared&lt;/code&gt; pointer, we know that the
guard it came from is active.&lt;/p&gt;

&lt;h3 id=&quot;treibers-stack-on-epochs&quot;&gt;Treiber&amp;rsquo;s stack on epochs&lt;/h3&gt;

&lt;p&gt;Without further ado, here is the code for Treiber&amp;rsquo;s stack using the Crossbeam
epoch API:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;sync&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;atomic&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Ordering&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crossbeam&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;::&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TreiberStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TreiberStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;TreiberStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TreiberStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// allocate the node via Owned&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Atomic&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// become active&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// snapshot current head&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// update `next` pointer with snapshot&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// if snapshot is still good, link in the new node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cas_and_ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// become active&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;epoch&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// take a snapshot&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// the stack is non-empty&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// read through the snapshot, *safely*!&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relaxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// if snapshot is still good, update from `head` to `next`&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cas_shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// mark the node as unlinked&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlinked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// we observed the stack empty&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some obserations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The basic logic of the algorithm is identical to the version that relies on a
GC, except that we explicitly flag the popped node as &amp;ldquo;unlinked&amp;rdquo;. In general,
it&amp;rsquo;s possible to take lock-free algorithms &amp;ldquo;off the shelf&amp;rdquo; (the ones on the
shelf generally assume a GC) and code them up directly against Crossbeam in
this way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After we take a snapshot, we can dereference it without using &lt;code&gt;unsafe&lt;/code&gt;,
because the &lt;code&gt;guard&lt;/code&gt; guarantees its liveness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The use of &lt;code&gt;ptr::read&lt;/code&gt; here is justified by our use of compare-and-swap to
ensure that only one thread calls it, and the fact that the epoch reclamation
scheme &lt;em&gt;does not run destructors&lt;/em&gt;, but merely deallocates memory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last point about deallocation deserves a bit more comment, so let&amp;rsquo;s wrap up
the API description by talking about garbage.&lt;/p&gt;

&lt;h3 id=&quot;managing-garbage&quot;&gt;Managing garbage&lt;/h3&gt;

&lt;p&gt;The design in Crossbeam treats epoch management as a service shared by all data
structures: there is a single static for global epoch state, and a single
thread-local for the per-thread state. This makes the epoch API very simple to
use, since there&amp;rsquo;s no per-data structure setup. It also means the (rather
trivial) space usage is tied to the number of threads using epochs, not the
number of data structures.&lt;/p&gt;

&lt;p&gt;One difference in Crossbeam&amp;rsquo;s implementation from the existing literature on
epochs is that &lt;em&gt;each thread keeps local garbage lists&lt;/em&gt;. That is, when a thread
marks a node as &amp;ldquo;unlinked&amp;rdquo; that node is added to some thread-local data, rather
than immediately to a global garbage list (which would require additional
synchronization).&lt;/p&gt;

&lt;p&gt;Each time you call &lt;code&gt;epoch::pin()&lt;/code&gt;, the current thread will check whether its
local garbage has surpassed a collection threshold, and if so, it will attempt a
collection. Likewise, whenever you call &lt;code&gt;epoch::pin()&lt;/code&gt;, if the global epoch has
advanced past the previous snapshot, the current thread can collect some of its
garbage. Besides avoiding global synchronization around the garbage lists, this
new scheme spreads out the work of actually freeing memory among all the threads
accessing a data structure.&lt;/p&gt;

&lt;p&gt;Because GC can only occur if all active threads are on the current epoch, it&amp;rsquo;s
not always possible to collect. But in practice, the garbage on a given thread
rarely exceeds the threshold.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s one catch, though: because GC can fail, if a thread is exiting, it needs
to do &lt;em&gt;something&lt;/em&gt; with its garbage. So the Crossbeam implementation &lt;em&gt;also&lt;/em&gt; has
global garbage lists, which are used as a last-ditch place to throw garbage when
a thread exits. These global garbage lists are collected by the thread that
successfully increments the global epoch.&lt;/p&gt;

&lt;p&gt;Finally, what does it mean to &amp;ldquo;collect&amp;rdquo; the garbage? As mentioned above, the
library &lt;em&gt;only&lt;/em&gt; deallocates the memory; it does not run
destructors.&lt;/p&gt;

&lt;p&gt;Conceptually, the framework splits up the destruction of an object into two
pieces: destroying/moving out interior data, and deallocating the object
containing it. The former should happen at the same time as invoking &lt;code&gt;unlinked&lt;/code&gt;
&amp;ndash; that&amp;rsquo;s the point where there is a unique thread that owns the object in every
sense except the ability to actually deallocate it. The latter happens at some
unknown later point, when the object is known to no longer be referenced. This
does impose an obligation on the user: access through a snapshot should only
read data that will be valid until deallocation. But this is basically always
the case for lock-free data structures, which tend to have a clear split between
data relevant to the container (i.e., &lt;code&gt;Atomic&lt;/code&gt; fields), and the actual data
contained (like the &lt;code&gt;data&lt;/code&gt; field in &lt;code&gt;Node&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Splitting up the tear down of an object this way means that destructors run
synchronously, at predictable times, alleviating one of the pain points of GC,
and allowing the framework to be used with non-&lt;code&gt;&amp;#39;static&lt;/code&gt; (and non-&lt;code&gt;Send&lt;/code&gt;) data.&lt;/p&gt;

&lt;h2 id=&quot;the-road-ahead&quot;&gt;The road ahead&lt;/h2&gt;

&lt;p&gt;Crossbeam is still in its infancy. The work here is laying the foundation for
exploring a wide range of lock-free data structures in Rust, and I hope for
Crossbeam to eventually play a role similar to java.util.concurrent for Rust &amp;ndash;
including a lock-free hashmap, work-stealing deques, and lightweight task
engine. If you&amp;rsquo;re interested in this work, I&amp;rsquo;d love to have help!&lt;/p&gt;
</content>
 </entry>
 

</feed>
