<?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/atom.xml" rel="self"/>
 <link href="http://aturon.github.io/"/>
 <updated>2024-11-21T22:58:44+00:00</updated>
 <id>http://aturon.github.io</id>
 <author>
   <name>Aaron Turon</name>
   <email>aturon@mozilla.com</email>
 </author>

 
 <entry>
   <title>To heal, first feel your wounds</title>
   <link href="http://aturon.github.io/personal/2020/09/13/grief-trauma-healing/"/>
   <updated>2020-09-13T00:00:00+00:00</updated>
   <id>http://aturon.github.io/personal/2020/09/13/grief-trauma-healing</id>
   <content type="html">&lt;p&gt;Grief has been in my life for two years. It took me by surprise, and it changed everything.&lt;/p&gt;

&lt;p&gt;There are some Big Words that we reserve for Big Circumstances. “Grief”, we see as a sacred process surrounding a Big Loss. “Trauma”, we see as a wound from a Big Event, like a war or imminent physical threat. In therapy, I’m learning about the urge to draw lines, making binaries saying “that’s grief, that’s trauma, that’s not”. I’m learning that while there is a place for binaries, they often lead us astray, keeping us pinned to an unhelpful story, or preventing us from accepting a helpful one.&lt;/p&gt;

&lt;p&gt;It was easier for me to admit to grief than to trauma, because the evidence was unmistakeable, even if the causes were less familiar.&lt;/p&gt;

&lt;p&gt;My first bout of grief, like most that followed, came on the heels of an intensely positive moment. I felt safe, loved, held. I was a little high. And suddenly, without warning, a shocking sentence formed on my lips, a total non-sequitur: “there’s a hole where my dad should be”. What followed was one of the most animalistic moments I have ever experienced. I sobbed, screamed, moved around on all fours, and felt as if I were vomiting. It was completely instinctual. Throughout, a parade of memories marched in my mind, memories of childhood and beyond, supplemented by new feelings and new understanding.&lt;/p&gt;

&lt;p&gt;For the first time, I let myself see and feel my experience of emotional neglect. I saw my years of longing, my failed attempts at connection. I felt what I had unconsciously held at bay throughout my life: the pain of not being understood, loved, and attended to in the ways I needed at the time. After three decades, I let go of the story of my father’s perfection, the impossibility of him hurting me. I let myself see and feel my wounds, and I grieved.&lt;/p&gt;

&lt;p&gt;I think we fear grief because it seems immensely painful. But these days I welcome grief, because it is me admitting to the pain that is already there, and allowing that pain to move through me and be released. It is a letting go of resistance to reality, feeling the feelings that are appropriate to a new admission. Grief is reconciliation to a world that differs from the story we have clung to. The bigger the story, the bigger the grief.&lt;/p&gt;

&lt;p&gt;When someone important to us dies, we grieve the story we’ve clung to that tells us they will always be in our life, the story of our plans and hopes and dreams with them. We’ve organized ourselves around that story, made it load bearing in the meaning of our life. That is as it should be. And in proportion, when we grieve we adjust our assumptions, and feel the pain of doing so.&lt;/p&gt;

&lt;p&gt;If grief is relinquishing load-bearing assumptions, trauma is experiencing something beyond our ability to cope – an overwhelming experience that cannot be metabolized head-on. We have to shut it down somehow, which often means telling ourselves a story that denies part of what happened, because the associated feelings are just too much.&lt;/p&gt;

&lt;p&gt;As a child, abuse and neglect are overwhelming, especially at the hands of the adults we’re programmed to see as our perfect caretakers. We invent a story that maintains their perfection, either denying what we experienced, or finding a way to take the blame for it – anything to keep the horror of the truth at bay. But the mind is not entirely fooled, and the exiled horror and pain remain, locked away behind a story that requires increasing distortion to cling to, lest some of the pain leak out.&lt;/p&gt;

&lt;p&gt;After that first session of grief around my childhood, something even more surprising happened. I found that my typical social anxiety just… disappeared. I stopped shrinking from strangers; I didn’t feel I was an imposition. I ceased thinking that I needed to know all the rules and expectations; I was simply present, in myself, and confident that that was enough. While that magical period lasted for only a couple of weeks at first, it provided a glimpse into what healing could mean for me. It showed me that so much of what I had taken for granted about myself was, in fact, changeable. And in the two years since then, this kind of change has begun to take deeper root – always punctuated by the release of grief.&lt;/p&gt;

&lt;p&gt;I have C-PTSD. The “C” stands for “complex”, which means that the traumas I experienced were not isolated events (like witnessing horrible violence), but rather ongoing situations. The coping strategies are likewise complex. I weaved stories hewing to key binaries, like the “perfection” of my father. I began to assume there was something innately undesirable about me, that I needed to carefully attend to the expectations of everyone around me and make sure I followed their rules, lest I be seen as a burden. Social anxiety was an inevitable result – especially around strangers, where I would do the work of discovering rules and expectations in real time. There was no room for my actual self. I was too busy protecting myself from further trauma.&lt;/p&gt;

&lt;p&gt;PTSD has to do with exactly this: the felt, ongoing threat that past unprocessed trauma could resurface. With “simple” PTSD trauma recurs via explicit flashbacks, where something in the present sends you completely back to a specific event in the past. With C-PTSD, the flashbacks are more subtle; they are termed “emotional flashbacks”, meaning that you begin &lt;em&gt;feeling&lt;/em&gt; the way you did for in the past, even though you have a cognitive grasp of the present. Either way you re-expereince what you’ve work so hard to contain, which often leads to a redoubling of your coping strategies.&lt;/p&gt;

&lt;p&gt;With C-PTSD, it’s possible to live in a state of perpetual flashback, where every present experience is colored by unresolved past trauma and the ways you tried to deal with it. You can become a servant of your coping strategies. Gradually, the color and meaning and feeling of your life fade. Everything becomes a disconnected game of self-protection against the trauma you’ve never fully faced.&lt;/p&gt;

&lt;p&gt;Grief is a way through. Grieving is a process of overcoming denial and other old coping strategies, and making your way toward acceptance of what really happened. It metabolizes those experiences that were originally too overwhelming to handle. When you begin to see and feel the fuller truth of what happened, you are released from your strategies and the beliefs they encompassed. Radical change is possible. Anxiety can melt away. All because you can see the past for what it is, and the present for what it is, too.&lt;/p&gt;

&lt;p&gt;I’ve now grieved aspects of every major relationship of my life. When I slowly realize that I’ve been dwelling in flashback, I know that eventually grief will break through. Each time around the cycle, I feel freer for longer, letting go of another layer of rigid belief and behavior meant to keep the trauma away. I’ve been able to feel and process a bit more trauma, integrating it into a more whole life story. And I find myself fully in my story in the present, empowered to take it in new directions, at last.&lt;/p&gt;

&lt;p&gt;If you want to learn more about trauma, C-PTSD, and grief, I recommend Pete Walker’s “Complex PTSD: From Surviving to Thriving”, a book that helped me understand my experiences and empowered me with tools to navigate them.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Back in the saddle</title>
   <link href="http://aturon.github.io/tech/2019/06/25/back-in-the-saddle/"/>
   <updated>2019-06-25T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2019/06/25/back-in-the-saddle</id>
   <content type="html">&lt;p&gt;Hi y’all! After some time away on mental health leave (which you can read more
about &lt;a href=&quot;http://aturon.github.io/personal/2019/06/24/survivor-skills/&quot;&gt;here&lt;/a&gt; if you’re curious), I’m fully back to work at the Mozilla Rust
team. I won’t be returning to Lang Team or Async work, but will instead be
working full-time on compiler engineering. The first goal is to work with Zoxc
and others to help ship parallel rustc. After that, there’s tons to do on the
trait system. I’m very excited about focusing on some actual Rust programming.&lt;/p&gt;

&lt;p&gt;I wanted to take this opportunity to thank Mozilla, which has been very
accommodating and understanding with my need to take some time, and especially
to thank my dear friend Niko, who quietly and competently took on the workload
around this transition.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Survivor skills</title>
   <link href="http://aturon.github.io/personal/2019/06/24/survivor-skills/"/>
   <updated>2019-06-24T00:00:00+00:00</updated>
   <id>http://aturon.github.io/personal/2019/06/24/survivor-skills</id>
   <content type="html">&lt;p&gt;I usually start with some pivotal moment and work outward from there. Leaving my religion. Getting on antidepressants. Starting therapy. My partner coming out as trans. Starting therapy again. It doesn’t really matter; the story of my mental illness and the story of my life are the same story.&lt;/p&gt;

&lt;p&gt;So let’s start in Indiana, on the worst day of my life—the day before my first of a dozen interviews for faculty positions at all the top universities. I had no intention of taking an offer from Purdue; it was a practice run. So why was I so panicked that not even sleeping pills could help me rest? I was hot shit on the market that year. This was supposed to be a slam dunk, but I was imploding.&lt;/p&gt;

&lt;p&gt;My clearest memory from that day was me, standing out in the snow, waiting for my partner to pick up the phone. I vividly recalled time spent watching my infant daughter: there but not really there, work and worries forever stealing my attention. I knew what it would look like if I stayed on that path. I said the words “I don’t want this” into the phone, and cancelled the rest of my interviews.&lt;/p&gt;

&lt;p&gt;Exactly five years later, I did it again, stepping down from a leadership role, for the exact same reason. I had tried a lot of things, but something was still wrong.&lt;/p&gt;

&lt;p&gt;As a branch of medicine, psychiatry starts with symptoms, diagnostics, and disorders. I had some mix of Generalized and Social Anxiety Disorders, with occasional depressive episodes. My primary emotion was dread: a floating sense that something, somewhere, was wrong and it was all going to fall apart. The “generalized” part meant that the dread would latch on to whatever I could rationalize it with. &lt;em&gt;If I don’t make this deadline, my career will fail. Any day now they’ll see I’m a fraud and I’ll be fired.&lt;/em&gt; At some level I knew these worries were overblown, but I couldn’t seem to put them aside. No matter where I was, there was always a tension, a nagging feeling that it would be dangerous to fully relax into the moment.&lt;/p&gt;

&lt;p&gt;For those five years I tackled my disorders head-on. If something promised to reduce anxiety, I did it. Yoga; two hour walks; jogging; meditation; dropping caffeine; cutting out sugar; probiotics; sleep tests; a slew of acronyms like SSRIs, CBT, THC, CBD, and more. All of these helped, for a while—and sometimes they helped a lot. I remember Christmas a couple of years ago, when my antidepressant kicked in, and I felt that tension truly lift, for the first time in many years. But somehow it always snuck back in.&lt;/p&gt;

&lt;p&gt;I was searching for that one weird trick that would suddenly cure me. But healing is messy and non-linear, and it doesn’t happen overnight.&lt;/p&gt;

&lt;p&gt;In the months following my second implosion, I came to think about mental health differently. Rather than focusing on symptoms, I focused on areas of rigidity. What are the things I won’t let myself see or think or feel? What kinds of compulsive behaviors does that lead to? What assumptions do I habitually make, and how do they affect my life? My therapist encouraged me to see psychological flexibility as a measure of mental health.&lt;/p&gt;

&lt;p&gt;Here’s the rub: these areas of rigidity are pesky fuckers, invisible at first, so reinforced into habit that you’re barely aware of them.&lt;/p&gt;

&lt;p&gt;When I go into someplace like a coffee shop, I often feel like I’m imposing on everyone there. I am hyper-aware of the people around me. &lt;em&gt;Where does the line end? Am I going to the right place? Is someone going to get frustrated that I didn’t move at the right time? Oh shit, the person in front of me didn’t see that it’s their turn, should I do something? OK, it’s my turn, I need to appear friendly but make clear that I want the minimum amount of interaction. Where am I supposed to wait?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These thoughts, feelings, and behaviors are so automatic that I barely register them. But I am nevertheless ruled by them. They steal my attention and energy. They inject anxiety. And they push me toward avoidance and denial, to the point that I could find myself preferring an uncomfortable bladder (“I don’t have to pee that bad”) to the discomfort of asking someone where the bathroom is, without even realizing it. And the list of my rigid habits is long and growing, as I build the skills to discover them. I started to wake up only when I realized that I saw my life as one big to-do list, an unending gauntlet of obligations in which I had less and less agency over time. I was very ill.&lt;/p&gt;

&lt;p&gt;My deepest area of rigidity, the habit that most shaped my life? Success. In particular: achieving whatever the authority figures around me seemed to want, even if they didn’t articulate it themselves.&lt;/p&gt;

&lt;p&gt;Rigidity is often born from survival. Maybe you survived an environment where your needs weren’t being met; you found your way to the best substitutes you could. Maybe you survived an acute trauma, like a threat to your physical being. Maybe the trauma was repeated, like being hit or yelled at as a child. Whatever the origin, your mind and your body worked overtime to protect you, pushing you into patterns, aversions, and strong feelings that guided your behavior toward survival. That survival often meant avoiding the full feeling of what you were surviving.&lt;/p&gt;

&lt;p&gt;In other words, the habits are hard to see, but their origin is even harder: it’s the very thing that your mind is trying to protect you from experiencing.&lt;/p&gt;

&lt;p&gt;A book that’s been very important for me, The Drama of the Gifted Child, portrays a common story, one that I share, and how it shows up in therapy:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In the very first interview they will let the listener know that they have had understanding parents, or at least one such, and if they ever lacked understanding, they felt that the fault lay with them and with their inability to express themselves appropriately. They recount their earliest memories without any sympathy for the child they once were, and this is the more striking since these patients not only have a pronounced introspective ability, but are also able to empathize well with other people. . . In general, there is a complete absence of real emotional understanding or serious appreciation of their own childhood vicissitudes, and no conception of their true needs—beyond the need for achievement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The portrait ends with a haunting line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The internalization of the original drama has been so complete that the illusion of a good
childhood can be maintained.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It took me thirty-three years and a lot of self-compassion and curiosity to uncover the truth of my own childhood, which I always saw as safe, comfortable, supported, and loving. Even now, as I write these words, I feel the pull to make excuses, to second-guess myself, to say “it wasn’t so bad”. &lt;em&gt;The adults in my life were doing the best they could, and I didn’t know how to tell them what I needed. They only hit me when I was little, and it was just spanking, not beating.&lt;/em&gt; It never occurred to me that the reason the violence stopped was that I had figured out what I needed to do to survive, that I had learned how to please my parents, to hide the parts of myself that would get me in trouble.&lt;/p&gt;

&lt;p&gt;I learned an even deeper lesson. Love for myself as I was—all of my humanity, all of my inner experience—was not available to me. But there was a substitute: attention and praise for what I could achieve, which started very young. I was given an IQ test in first grade, and enrolled in a gifted program that bused kids from all over the county into a special classroom once a week. I was told I was different, that I had special worth that separated me from my peers, because certain intellectual activities came easily to me. This message was repeated over and over throughout my life, all the way to the brink of becoming a professor. And because I was singled out, pulled away from my childhood into more “worthwhile” activities, I missed out on a lot of basic skills that didn’t come so easily to me.&lt;/p&gt;

&lt;p&gt;The story almost tells itself from here. Humans have a need to be seen and loved as they are. I was lost in a wilderness that couldn’t meet those needs, not in a healthy way. I sampled the nuts and berries I could find, and some made me sick (getting yelled at or spanked). Through trial and error, I discovered what would keep me alive, even if ultimately malnourished. By the time I left the wilderness of my childhood, I was so habituated to the survival skills that I developed that I didn’t realize it was possible to live any other way.&lt;/p&gt;

&lt;p&gt;For me, success was never a matter of ambition; it was a means of survival. It was the only way I knew how to be in the world, and I got really fucking good at it. But achievement is not a well-balanced diet. Like junk food, it just leaves you wanting more. And let me tell you, society is more than happy to present an unending ladder of success.&lt;/p&gt;

&lt;p&gt;I’ve been explicitly working on my mental health for more than five years, but I feel like it’s only in these last months that I’ve really started to heal. That healing has come from going beyond mindful awareness of my thoughts and habits to uncovering and making sense of their origins. Of course I’m an anxious wreck! I’ve been throwing all of my energy into what I learned, very young, was the “best” way to meet my needs—into things that could never fully meet my needs. By surveying my life—by facing my childhood for what it was, by mourning for the lost years, by letting myself feel the terrible isolation and abandonment and longing for love I experienced in my childhood, by raging at my parents and their inability to meet or even comprehend my basic need to be seen and loved regardless of what I did—I have begun to loosen the rigidity, to let go of the need for success, to open myself to new experiences, to fail, to discover my self, and to be seen and loved for it.&lt;/p&gt;

&lt;p&gt;I started down this road with four words: “I don’t want this”. But I’m finding my way with another four:&lt;/p&gt;

&lt;p&gt;I am a survivor.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Version selection in Cargo</title>
   <link href="http://aturon.github.io/tech/2018/07/25/cargo-version-selection/"/>
   <updated>2018-07-25T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/07/25/cargo-version-selection</id>
   <content type="html">&lt;p&gt;When there are multiple ways to resolve dependencies, Cargo generally chooses
the &lt;em&gt;newest&lt;/em&gt; possible version. The goal of this post is to explain why Cargo
works this way, and how that rationale relates to several recent discussions,
including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/5657&quot;&gt;Whether we should support a “minimal version selection” option&lt;/a&gt;,
and if so how it should relate to CI and the existing ecosystem.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2495&quot;&gt;Whether we should state a minimal Rust version in Cargo.toml&lt;/a&gt; in
a way that affects dependency resolution.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://research.swtch.com/vgo&quot;&gt;The work on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgo&lt;/code&gt;&lt;/a&gt;, a new package management
tool for Go that explicitly opts for selecting the &lt;em&gt;oldest&lt;/em&gt; possible version.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;version-selection-goals&quot;&gt;Version selection goals&lt;/h1&gt;

&lt;p&gt;No one likes spending time futzing with their dependencies instead of writing
code on top of them. For Cargo (and, I think, most package managers) that
translates to the following design goals:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;. After building, it should be easy to perform an identical
build again, even on a different machine, so that debugging can proceed from a
firm foundation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Control&lt;/strong&gt;. Users should have control over when and how dependencies are
upgraded, so that surgical fixes can be applied.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;. It should be easy to find versions of direct dependencies
that work together.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;. The support burden should be minimized and evenly
distributed, rather than falling entirely on the upstream or downstream sides.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The “dependency hell” experience comes down to one or more of these goals being
unfulfilled. But some of the goals are directly at odds! For example, if we want
to give clients fine-grained control over version selection &lt;em&gt;and&lt;/em&gt; make it easy
to find compatible sets of versions of libraries, we’ll be asking for a higher
maintenance burden across the ecosystem. That’s because ensuring compatibility
generally requires testing and bug-fixing, and the more combinations of versions
that arise, the more testing and fixing that’s needed.&lt;/p&gt;

&lt;p&gt;The role of the package manager is thus to provide mechanisms, defaults, and
best practices that push the ecosystem toward a good balance across these
goals. It’s an imperfect science, involving some social engineering and
guesswork; there’s not a clear best way to go about it.&lt;/p&gt;

&lt;h1 id=&quot;rationale-for-maximal-version-resolution&quot;&gt;Rationale for maximal version resolution&lt;/h1&gt;

&lt;p&gt;Most of the time, there are many, many valid ways to resolve a dependency graph.
Even in the simplest case of having a single dependency, if you use the typical
version constraints multiple matches will be possible:&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;py&quot;&gt;winapi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.3.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This version constraint asks for any version &lt;em&gt;compatible with&lt;/em&gt; 0.3.0, which for
Cargo means any 0.3.X version (currently, the latest is 0.3.5). How do we decide
&lt;em&gt;which&lt;/em&gt; of the compatible versions to go with? Most package managers, including
Cargo, take the maximum (newest) version possible. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgo&lt;/code&gt; package manager
from Go is a notable exception in taking the &lt;em&gt;minimum&lt;/em&gt; version.&lt;/p&gt;

&lt;p&gt;Let’s examine this question in light of the design goals:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;If we select the &lt;em&gt;maximum&lt;/em&gt; version, dependency resolution will produce
different results as new versions of crates are published. Thus, to achieve
reproducible builds, a separate mechanism is needed to record the
state of the world at the time of the build: the lockfile.&lt;/li&gt;
      &lt;li&gt;If we select the &lt;em&gt;minimum&lt;/em&gt; possible version, dependency resolution will give
the same result even if new versions are published, so no lockfile is needed
to achieve reproducibility.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Control&lt;/strong&gt;: the version selection strategy doesn’t have direct bearing on the
question of control, because users are always free to use more restrictive
constraints, like “=0.3.1”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;: since we’re talking about different &lt;em&gt;valid&lt;/em&gt; resolutions of
dependencies, we’re already in a situation where the dependency graph can be
resolved. But whether the resulting code actually compiles and works together
is another question! All else being equal, what will make compatibility most
likely is if the specific combination of versions has been actively tested and
debugged.
    &lt;ul&gt;
      &lt;li&gt;If we select the &lt;em&gt;maximum&lt;/em&gt; version, then at any given point in time, the
current maximum versions of crates will be actively tested against each
other (due to CI), and hence likely to work. Put differently, there’s an
ecosystem-wide agreement on which versions to test compatibility with each
other: the latest versions.&lt;/li&gt;
      &lt;li&gt;If we select the &lt;em&gt;minimum&lt;/em&gt; version, the version we &lt;em&gt;actually&lt;/em&gt; get will
depend on what minimum versions happen to appear in any transitive
dependencies. In other words, &lt;em&gt;it’s the minimum version that can satisfy our
particular dependency graph&lt;/em&gt;. Thus, unlike the situation with maximum
version selection, there is not ecosystem-wide agreement on which versions
will be used together in CI and elsewhere; the versions chosen will vary
across projects.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;If we select the &lt;em&gt;maximum&lt;/em&gt; version, downstream users are likelier to get the
latest bugfixes; for apps, lockfiles help protect against the opposite
problem of trading known bugs for unknown ones. Furthermore, as mentioned
above, the ecosystem-wide agreement on the “frontier” of versions to test
with each other means that bug reports against old versions (and
expectations of backports) are less likely. Active maintenance is focused on
the latest releases across the board.&lt;/li&gt;
      &lt;li&gt;If we select the &lt;em&gt;minimum&lt;/em&gt; version, there is greater chance of already-fixed
bugs biting users. Furthermore, as mentioned above, the version combination
a project ends up with is more likely to be unique to that project, and
hence seen less testing over all. Active maintenance is spread across a
larger range of versions.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Cargo team believes that, on balance, maximum version selection provides a
better experience across the ecosystem, with the primary cost being one of
conceptual and implementation complexity: the lockfile.&lt;/p&gt;

&lt;p&gt;It’s important to note, though, that while the maximum version approach tends to
focus the ecosystem on the latest versions of crates, there are still plenty of
circumstances where other version combinations arise:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;For an app with an existing lockfile, the versions will be held steady
regardless of new publications. However, &lt;em&gt;at the time the lockfile was
produced&lt;/em&gt;, the versions selected were the latest ones available, and hence
were receiving active testing and maintenance at the time. Similarly, when
dependencies are subsequently adjusted, Cargo will “unlock” the affected
dependencies and again choose the maximum version.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bounded constraints like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;=&lt;/code&gt; prevent Cargo from choosing the newest
version. These constraints are rare, especially for libraries, but they relate
to toolchain version requirements, as we’ll see next.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;toolchain-requirements&quot;&gt;Toolchain requirements&lt;/h1&gt;

&lt;p&gt;The Rust community has had recurring discussions about what kinds of constraints
libraries should impose on the compiler toolchain they use, and how those
constraints should be expressed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On the one hand, library authors would like to use the newest Rust features.&lt;/li&gt;
  &lt;li&gt;On the other hand, doing so means their clients must be using an up-to-date
toolchain. This can be a hardship in situations where it’s hard to change the
toolchain, due to deep integrations or other constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today, the most widely-used crates in the Rust ecosystem have adopted an
extremely conservative stance, effectively retaining compatibility with the
oldest version of Rust possible, in some cases with a three-year-old
toolchain. For a language as young as Rust, that’s pretty painful.&lt;/p&gt;

&lt;p&gt;Proposals for addressing this problem fall into basically two camps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Shared policy&lt;/strong&gt;: rather than have core libraries each be “as compatible as
possible”, instead set a clear, ecosystem-wide policy on what level of
compatibility is expected. This was first proposed
in &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1619&quot;&gt;2016&lt;/a&gt;, and has been revived
as part of the current &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2483&quot;&gt;long-term support (LTS) proposal&lt;/a&gt;. The key idea
is that &lt;em&gt;it is not considered a breaking change to update the compiler version
required&lt;/em&gt;, as long as the new requirement is within the compatibility
policy. For LTS-level compatibility, that means that the crate is always free
to depend on the latest LTS toolchain.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Stated toolchain&lt;/strong&gt;. There have been several RFCs proposing to
specify toolchain requirements as part of Cargo.toml, &lt;em&gt;and have those
requirements affect dependency resolution&lt;/em&gt;;
the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2495&quot;&gt;latest such RFC&lt;/a&gt; is
currently open. In this model, crates could freely bump the minimum compiler
version needed, and Cargo would only resolve to a version of the crate that
supports the compiler toolchain being used.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s again analyze this situation in light of the design goals we started with
(except for reproducibility, which isn’t relevant here):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Control&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;In the &lt;em&gt;shared policy&lt;/em&gt; approach, control is very limited. Library authors
don’t choose arbitrary toolchain versions, but instead commit to
compatibility with a &lt;em&gt;release channel&lt;/em&gt; (LTS, stable, nightly).&lt;/li&gt;
      &lt;li&gt;In the &lt;em&gt;stated toolchain&lt;/em&gt; approach, &lt;em&gt;everyone&lt;/em&gt; has a lot of control. Library
authors can set their toolchain requirements in any way they like, for any
library release they like. Consumers can likewise choose any toolchain to
work with, and Cargo will look for a compatible dependency resolution.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;: Note first that Rust toolchains are regularly tested
against the entire crates.io ecosystem, so unlike with version selection
above, there’s less concern here of finding a combination that “resolves but
fails to compile/work”. The concern is more about finding a resolution at all.
    &lt;ul&gt;
      &lt;li&gt;In the &lt;em&gt;shared policy&lt;/em&gt; approach, similar to the “maximum version selection”
we saw before, there’s an ecosystem-wide agreement about what versions to test
on and be compatible with: the latest LTS toolchain. If we assume that the
majority of users are able to stay at least on or above the most recent LTS,
then toolchain compatibility is a non-issue, at least for core crates.&lt;/li&gt;
      &lt;li&gt;In the &lt;em&gt;stated toolchain&lt;/em&gt; approach, the toolchain being used to compile
&lt;em&gt;effectively imposes an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;-style version constraint&lt;/em&gt;. That means that we
are somewhat less likely to get the &lt;em&gt;latest&lt;/em&gt; versions of all our
(transitive) dependencies, since some of them may require newer toolchain
versions; we will of course get the latest compatible versions. It’s hard to
say for certain, but this seems likely to create a larger set of crate
version combinations than we see today, and thereby diffuse the testing for
compatibility.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: Here the maintenance burden is largely on library authors.
    &lt;ul&gt;
      &lt;li&gt;In the &lt;em&gt;shared policy&lt;/em&gt; approach, library authors are often “stuck” on an old
(LTS) version of the toolchain, though not as outdated as with many crates
today; that imposes a maintenance cost. On the other hand, there’s a much
greater chance that their clients are using the latest version of &lt;em&gt;the
library&lt;/em&gt; due to this generous toolchain compatibility, which helps with
maintenance (since bug reports tend to be targeted toward the current
release).&lt;/li&gt;
      &lt;li&gt;In the &lt;em&gt;stated toolchain&lt;/em&gt; approach, the tradeoffs are exactly the reverse:
it’s easy to upgrade the toolchain requirement at will, but the cost is that
doing so &lt;em&gt;effectively creates an LTS version of the library&lt;/em&gt;, because users
stuck on old toolchains will also be stuck on old library versions, and
hence file bug reports (and request backports) for them.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s not a clear winner here! And there are a lot of other, emergent factors
to consider as well:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Rust’s rapid release process is based on the idea that most developers will
keep their toolchain up to date, since each incremental update is small (as
opposed to “big bang” updates on a much slower cadence). There is some risk
that the &lt;em&gt;stated toolchain&lt;/em&gt; approach will reduce incentives toward upgrading.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Even if crates can state toolchain requirements, there’s still the question,
for core crates, of what requirements are appropriate. Bumping the requirement
won’t break clients right away, but it will cause problems if those clients
want to update to gain new library features (but stay with the old
toolchain). In other words, it seems possible that the benefits of the &lt;em&gt;stated
toolchain&lt;/em&gt; approach are illusory, and that in practice critical crates will
stick with very conservative toolchain requirements.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, that last point is a clincher: I think that forming a good &lt;em&gt;shared
policy&lt;/em&gt; is going to be needed regardless, and that doing so will address most of
the toolchain requirement issues we have today. I similarly think that it’s
quite valuable to retain the true maximum version selection that we have today,
rather than constrain it by a toolchain filter.&lt;/p&gt;

&lt;p&gt;In the long run, it could even make sense to combine the two approaches,
allowing crates to state their toolchain requirements (and have that influence
resolution), but encourage core crates to state “LTS” as their requirement.&lt;/p&gt;

&lt;h1 id=&quot;checking-the-minimal-resolution&quot;&gt;Checking the minimal resolution&lt;/h1&gt;

&lt;p&gt;Finally, I wanted to address an interesting aspect of the current approach to
version resolution: most &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; files do not give an accurate lower bound
on their dependencies! Going back to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winapi&lt;/code&gt; example, if the stated
dependency is “0.3.0”, because we will resolve to the maximum version, we can
freely rely on a feature that only appeared in 0.3.2.&lt;/p&gt;

&lt;p&gt;Simple minimal version selection wouldn’t immediately address the issue, because
one of our &lt;em&gt;other&lt;/em&gt; dependencies could itself have a dependency like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winapi =
&quot;0.3.2&quot;&lt;/code&gt;, which would mean we’d compile against a newer version than what we
stated. To get a truly precise lower-bound, we have to (1) resolve to minimal
versions and (2) check those versions against all the ones stated in the root
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;. There’s
been &lt;a href=&quot;https://github.com/rust-lang/cargo/issues/5657&quot;&gt;some work&lt;/a&gt; to add such
capabilities to Cargo, but there’s an open question: do we care?&lt;/p&gt;

&lt;p&gt;The lack of lower-bound precision hasn’t been a problem for Cargo so far
because, in general, we eagerly resolve to the &lt;em&gt;maximum&lt;/em&gt; version; any
requirement on newer library features will thus be automatically fulfilled.&lt;/p&gt;

&lt;p&gt;However, there are at least two ways this could become more of a problem in the future:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;If we adopt the &lt;em&gt;stated toolchain&lt;/em&gt; approach above, we end up imposing more
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;-style constraints, which in turn can prevent us from choosing the
globally-maximum version of crates. The effect could be that everything passes
CI just fine, but a user with an older toolchain gets a crate resolution that
fails to compile (rather than a resolution saying “you need a newer
toolchain”). Notably, the lower-bound precision issue &lt;em&gt;also&lt;/em&gt; applies to the
stated toolchain, as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It’s possible that we will eventually have workflows that depend on the
accuracy of lower bounds in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;. At the moment, however, this is
purely speculative; the Cargo team does not have any ready examples.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we do decide to care, an approach to improve accuracy is to document, as part
of CI best-practices, that a build with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--minimal-versions&lt;/code&gt; should be performed
in CI in additional to the normal build. We could likewise build that test into
crate publication.&lt;/p&gt;

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

&lt;p&gt;While we didn’t reach crystal-clear conclusions on the current open questions,
the main goal here was to lay out more explicitly a way of thinking about the
design space. As with
the
&lt;a href=&quot;https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html&quot;&gt;Ergonomics Initiative&lt;/a&gt; post
from last year, I’m hopeful that this framing can help give us some shared
vocabulary for grappling with the current and future design question in
Cargo.&lt;/p&gt;

&lt;p&gt;For the particular questions examined here, I’d very much appreciate comments on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2495&quot;&gt;minimum version RFC&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2483&quot;&gt;LTS RFC&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/rust-lang/cargo/issues/5656&quot;&gt;CI best practices&lt;/a&gt; issue for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--minimal-versions&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>aturon.log: listening and trust, part 3</title>
   <link href="http://aturon.github.io/tech/2018/06/18/listening-part-3/"/>
   <updated>2018-06-18T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/06/18/listening-part-3</id>
   <content type="html">
&lt;p&gt;In this third post in the &lt;a href=&quot;http://aturon.github.io/tech/2018/05/25/listening-part-1/&quot;&gt;listening and trust series&lt;/a&gt;,
I’m going to talk through one of the most intense discussions the Rust community has had:
the module system changes that were part of last year’s &lt;a href=&quot;https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html&quot;&gt;ergonomics initiative&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-saga-summarized&quot;&gt;The saga, summarized&lt;/h2&gt;

&lt;p&gt;The modules saga demonstrates both payoffs and pathologies of the RFC process,
playing out over a dozen different threads reaching 1,400+ comments in total.&lt;/p&gt;

&lt;p&gt;It was, in the end, a success – at least as gauged by the collective enthusiasm
for the final result, compared to the starting point. Yet it left wounds that
have not entirely healed, which is part of why I want to talk about it here.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1774&quot;&gt;2017 roadmap&lt;/a&gt; focused on productivity and learnability, and the Lang Team
took a look across the language for areas of improvement. Modules were a
well-known stumbling block for many users, though many others (including most of
the Lang Team) found it simple and easy to grasp. So the first order of business
was working to understand what people found confusing or difficult about modules,
which led to a couple of initial threads:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;@withoutboats’s post, &lt;a href=&quot;https://withoutboats.github.io/blog/rust/2017/01/04/the-rust-module-system-is-too-confusing.html&quot;&gt;The Rust module system is too confusing&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;An &lt;a href=&quot;https://internals.rust-lang.org/t/lang-team-minutes-the-module-system-and-inverting-the-meaning-of-public/4804/&quot;&gt;internals writeup&lt;/a&gt; of a Lang Team discussion about the privacy
aspects of the module system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These early threads produced some important insights into how different people
experienced the module system. They also highlighted the level of controversy to
expect around any discussion involving such a fundamental change, even one that
was far from a complete proposal.&lt;/p&gt;

&lt;p&gt;A few months later, a subset of the Lang Team and some others spent a few
hundred person-hours delving into both the problem and solution space. We worked
through about a dozen different designs before finally reaching a mix of ideas
that seemed plausible enough to present to the community. I did so in an
&lt;a href=&quot;https://internals.rust-lang.org/t/revisiting-rusts-modules/5628&quot;&gt;initial blog post&lt;/a&gt;, which also took a stab at a “comprehensive” analysis of the
problems. The post generated an enormous amount of discussion, and a week later
I closed its thread in favor of a new one with a &lt;a href=&quot;https://internals.rust-lang.org/t/revisiting-rust-s-modules-part-2/5700&quot;&gt;revised proposal&lt;/a&gt;, which
@withoutboats &lt;a href=&quot;https://internals.rust-lang.org/t/revisiting-modules-take-3/5715&quot;&gt;revised further&lt;/a&gt;. There were also a handful of other threads with
additional proposals, or that drilled into specific aspects in greater detail.&lt;/p&gt;

&lt;p&gt;One of the problems the original proposal called out was “path confusion”. The
&lt;a href=&quot;https://internals.rust-lang.org/t/revisiting-rust-s-modules-part-2/5700&quot;&gt;revised proposal&lt;/a&gt; summarized some of the feedback as saying:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Many on the thread cited this as the core problematic issue with the module
system; I’ve collected some data about confusion around Rust modules which
also supports that to a degree.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and suggested an approach that gave more weight to solving those problems.&lt;/p&gt;

&lt;p&gt;After reaching what seemed to be a rough consensus on the internals thread
around the third design, @withoutboats wrote up a complete proposal as an
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2108&quot;&gt;initial RFC&lt;/a&gt;. A similar story played out, with that initial RFC garnering quite
a bit of feedback in multiple directions, and ultimately being closed in favor a
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2121&quot;&gt;second&lt;/a&gt;, and then a &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2126&quot;&gt;third&lt;/a&gt; (and final) RFC.&lt;/p&gt;

&lt;p&gt;The RFC that was ultimately accepted bears almost no resemblance to any of the
initial design sketches. It ultimately took the “path confusion” issue as &lt;em&gt;the&lt;/em&gt;
problem to address, and oriented the design more completely around that issue
than any of the earlier proposals did. (Discussion of some aspects of the design
&lt;a href=&quot;https://internals.rust-lang.org/t/the-great-module-adventure-continues/6678&quot;&gt;is ongoing&lt;/a&gt;; there will soon be a 2018 Edition Preview where we’ll be looking
for further feedback.)&lt;/p&gt;

&lt;p&gt;With that basic background in place, I want to examine some of the social
dynamics that played out along the way, from the context of listening and trust.&lt;/p&gt;

&lt;h2 id=&quot;momentum-urgency-and-fatigue&quot;&gt;Momentum, urgency, and fatigue&lt;/h2&gt;

&lt;p&gt;I think that, collectively, we all remember the modules discussion as
&lt;em&gt;intense&lt;/em&gt;. But it’s interesting to dig into the &lt;em&gt;ways&lt;/em&gt; it was intense.&lt;/p&gt;

&lt;p&gt;In my memory, the discussion was heated. But it turns out that memory was
faulty: when I went back and re-read all of these threads, I was shocked by the
relative lack of heat! Granted, there were a few outlier comments, but I came away
convinced that the sense of intensity was not primarily about the
discussion being charged.&lt;/p&gt;

&lt;p&gt;What I noticed, instead, is a recurring mention of the length and &lt;em&gt;velocity&lt;/em&gt;
of the comment threads involved. Threads were accruing hundreds of comments per
week, and there was a sense of high stakes (the Lang Team is considering
changing the module system!), so many people felt compelled to get involved, at
least at the beginning. And the only way to do so was to participate in those
threads, thus compounding the effect.&lt;/p&gt;

&lt;p&gt;While the modules discussion was an extreme case, the issue of comment thread
velocity is a familiar one in Rust. &lt;strong&gt;A high velocity thread often &lt;em&gt;seems&lt;/em&gt;
heated and “controversial”, even if the discussion is respectful and chock full
of insights&lt;/strong&gt;. I think this is part of why feelings about the modules discussion
are so complex, and why it seems an exemplar of both the best and the worst of
the RFC process.&lt;/p&gt;

&lt;p&gt;I personally don’t see high comment velocity as a &lt;em&gt;root&lt;/em&gt; problem, but an issue
that relates to deeper dynamics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Momentum&lt;/strong&gt;. A comment thread has a kind of “momentum” of sentiment that can
be hard to shift, and also hard to gauge as the thread gets long. If an RFC
has an initial batch of negative (or positive) comments, it can be difficult
to recover, in part because these are the first sentiments everyone sees.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Urgency&lt;/strong&gt;. Because comment threads are a major input into the
decision-making process, there’s a sense of urgency to participate and keep
the discussion “on course” from your personal perspective. This urgency is
compounded when a thread is fast-moving or lengthy, or when a proposal
originates from a team member (and thus is reasonably seen as having a
higher chance of landing).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fatigue&lt;/strong&gt;. Many people participate early on in an RFC thread, only to
ultimately step away because the thread has too much traffic to keep up with
or influence. There’s also sometimes a feeling of a topic getting discussed
“to death”; many felt that way toward the end of the modules saga.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these social dynamics are inevitable with a project as large and open as
Rust. But the net effect is a bit like the one I talked about in
the &lt;a href=&quot;http://aturon.github.io/tech/2018/05/25/listening-part-1/&quot;&gt;first post&lt;/a&gt; in the series: the sense that you need to be “in the
room when it happens”, and that it takes a lot of time and stamina to do so. In
this case it’s not about the moment of decision per se, but rather the struggle
to set the direction of the comment thread. &lt;strong&gt;I often hear from people who are
intimidated by the RFC process precisely because of the huge comment
threads&lt;/strong&gt;. Not to mention, of course, the enormous amount of work needed to
fully participate in those threads.&lt;/p&gt;

&lt;p&gt;These issues are particularly pronounced for early-stage
discussions. “Brainstorming” can get overwhelmed either by a deluge of ideas, or
(much worse) strong attempts to kill an idea before it has any chance to take
root.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But I don’t think comments themselves are the problem&lt;/strong&gt;; the whole process is,
after all, a request for comments! I think the problematic dynamics stem instead
from two core process problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A lack of clarity about the “stage” of any given discussion&lt;/strong&gt;. A thread
brainstorming on a new way to approach &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt;-wrapping should not need to
recapitulate fundamental disagreements on whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt;-wrapping is desirable.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Too much emphasis on “the thread”, rather than on standalone artifacts&lt;/strong&gt;. We
don’t have a good process or culture around reflecting the discussion into the
RFC itself, and while we do sometimes make “summary comments” to help manage
discussion, they tend to get lost in the noise. The RFC thread takes on a
primary, high stakes role instead.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe that if we adjust our process to address these two issues head-on, it
will go far in further eliminating the requirement to be “in the room” at the
right time, and the negative effects that come with it.&lt;/p&gt;

&lt;h2 id=&quot;wielding-power-changing-minds&quot;&gt;Wielding power; changing minds&lt;/h2&gt;

&lt;p&gt;In my last post, I mentioned a sentiment I’ve often seen, one sometimes made in
reference to the modules discussion:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Luckily enough of us yelled to stop the terrifying original proposal from
happening; the moment we stop speaking up, Those People will start pushing in
that direction again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I understand where this sentiment comes from; the RFC that landed indeed bore
little resemblance to the starting point, due in part to pushback. But there are
two distinct ways to understand why RFCs change, and what it means:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Wielding power&lt;/strong&gt;. There were some particular aspects of the early modules
proposals, like removing the need for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt; statements, that garnered a strong
negative reaction from a number of people. It took a lot of iterations, but
ultimately that part of the proposal was dropped. It would be reasonable to
see this as part of the community &lt;em&gt;asserting itself&lt;/em&gt;, being loud enough about
strong preferences to make it clear that certain changes would be intolerable.
The result could be a capitulation, or compromise, in which the original proposers
relent and “take what they can get”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changing minds&lt;/strong&gt;. On the other hand, a number of folks who were positive
about the original proposal were &lt;em&gt;even more positive&lt;/em&gt; about the final one. For
them, the final proposal wasn’t a compromise at all, but rather the &lt;em&gt;best&lt;/em&gt;
option.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m personally in the latter camp: I’m much happier with the RFC that landed
than with the original proposal, and I wrote both of them! &lt;strong&gt;But I think both of
the above elements were at play&lt;/strong&gt;. Let me explain.&lt;/p&gt;

&lt;p&gt;It was not until very late in the process that we stopped proposing to drop
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt; statements, and there’s no question that, had it not been for the
persistence of a few people, it wouldn’t’ve happened. Power was, indeed,
wielded. But the reason for changing the proposal wasn’t simply “well, we can’t get
this through, so let’s scale back”. Rather, those lengthy comment threads and
disagreements forced us all to dig deeper into the problem space. And we
eventually learned that our original analysis of the core problem was just
&lt;em&gt;wrong&lt;/em&gt;, that the “path confusion” issue that I initially treated as secondary
was actually &lt;em&gt;the&lt;/em&gt; problem.&lt;/p&gt;

&lt;p&gt;This is part of why I don’t want to put blame on comments themselves. Our
willingness to dig deep and long to find new insights and more nuanced designs
is a big part of what’s made Rust the language it is, and why &lt;a href=&quot;https://twitter.com/aaron_turon/status/1008153135515222017&quot;&gt;I love&lt;/a&gt;
working on it so much. Sometimes talking something “to death” is exactly what’s
needed to uncover the right set of ideas.&lt;/p&gt;

&lt;p&gt;I don’t think it’s the job of the Rust Teams to seek a &lt;em&gt;compromise solution&lt;/em&gt;,
which is a recipe for design by committee; we need a strong, coherent final
design. I think we should be &lt;em&gt;convinced&lt;/em&gt; that the solution is within striking
distance of the best for our &lt;a href=&quot;http://aturon.github.io/tech/2018/06/02/listening-part-2/&quot;&gt;plural community&lt;/a&gt;. And thus the role of
the RFC process is precisely to facilitate deep digging, to explore ideas,
tradeoffs and constraints and look for the option that genuinely seems best.&lt;/p&gt;

&lt;h2 id=&quot;lived-experience-active-listening&quot;&gt;Lived experience; active listening&lt;/h2&gt;

&lt;p&gt;A final dynamic that showed up throughout the modules discussion: reports of
“lived experience”.&lt;/p&gt;

&lt;p&gt;Going back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt; statements, several people talked about the role they play
in their personal workflow, whether due to their IDE, their lack of IDE, their
habits with respect to temporary files, or even the latency of their file
system.&lt;/p&gt;

&lt;p&gt;No one can be wrong about their own lived experience. And lived experience can
bring issues to life in a way that pure empathy and speculation can’t. Thus, a
big benefit of the RFC process is the crowdsourcing of lived experiences that it
provides.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, one’s &lt;em&gt;own&lt;/em&gt; lived experience always looms large. But our job in
building a language is to account for the experience it provides for a large and
diverse set of current &lt;em&gt;and future&lt;/em&gt; users, many of whom are not well-represented
on RFC threads. Thus accounts of lived experiences are data points, at best
proxies for the experiences of similar users, but ultimately information that
needs to be weighed in a global design space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The work of an RFC thread is in part to employ &lt;em&gt;active listening&lt;/em&gt; to turn
lived experience into design constraints&lt;/strong&gt;. In cartoon form this might look as
follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A: “I am against this RFC.”&lt;/li&gt;
  &lt;li&gt;B: &lt;em&gt;Why?&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;A: “I don’t want to get rid of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt; statements, I think they’re very important.”&lt;/li&gt;
  &lt;li&gt;B: &lt;em&gt;Can you say more about what role they play for you?&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;A: “They make it easy to temporarily remove modules while refactoring.”&lt;/li&gt;
  &lt;li&gt;B: &lt;em&gt;OK, so you have as a design constraint that workflows for refactoring should remain ergonomic?&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;A: “Yes.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href=&quot;http://aturon.github.io/tech/2018/06/02/listening-part-2/&quot;&gt;last post&lt;/a&gt; talked about the feelings that inevitably come into play in any
discussion you care about. They’re strongest when they touch on lived
experience. They should not be &lt;em&gt;hidden away&lt;/em&gt;, but part of the emotional labor of
the RFC process is to recognizing such feelings as emerging from our &lt;em&gt;personal&lt;/em&gt;
experience, and working introspectively to dig out the actual constraints that
represents – and then to weigh those against the constraints of other present
and future Rust users. We can help each other to do so, as in the cartoonish
dialogue above. But even better if we can each do some of that work privately
&lt;em&gt;first&lt;/em&gt;, and come to the thread not with a flat “I am against this RFC” but
rather “I’m concerned about refactoring workflows; here’s what my personal one
looks like…”&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Last week a few folks from the Rust Core Team got to spend a few hours talking
about the RFC process in person – something we’ve done many times before, but
that led in a more conclusive direction this time around. Niko is writing up
some of the ideas, which are partly aimed at the problems raised in this post.&lt;/p&gt;

&lt;p&gt;Ultimately, though, we can’t solely rely on process improvements; we need to do
the work of reflecting on, writing down, and improving our design culture as
well. I plan at least one more post in the Listening and Trust series, and then
on to other, broader topics.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>aturon.log: listening and trust, part 2</title>
   <link href="http://aturon.github.io/tech/2018/06/02/listening-part-2/"/>
   <updated>2018-06-02T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/06/02/listening-part-2</id>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;http://aturon.github.io/tech/2018/05/25/listening-part-1/&quot;&gt;the previous post&lt;/a&gt; in
this series, I recounted an early lesson for the Rust Core Team about working in
the open. In this post, I want to talk about the delicate interplay between
listening and trust when doing design in the open.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;I honestly despise being subtle or “nice”. The fact is, people need to know
what my position on things are. And I can’t just say “please don’t do that”,
because people won’t listen. I say “On the internet, nobody can hear you being
subtle”, and I mean it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s Linus
Torvalds
&lt;a href=&quot;https://marc.info/?l=linux-kernel&amp;amp;m=137391223711946&amp;amp;w=2&quot;&gt;on talking and listening in OSS&lt;/a&gt;.
There is, of course, a long and continuing battle in the OSS world around codes
of conduct, and Linus is often cited in these debates (by both sides). Given
that the Rust community is firmly in the pro-CoC camp, it’s tempting to think
that what Linus is describing here is simply not relevant in the Rust world.&lt;/p&gt;

&lt;p&gt;But notice that Linus talks about two things here: being subtle, and being
nice. The “being nice” part is indeed covered by codes of conduct, and is by and
large not an issue for the Rust community. But the “being subtle” part is, well,
more subtle.&lt;/p&gt;

&lt;p&gt;To be concrete, saying “This idea is insane” or “An idiotic unreadable mess” is
obviously not being nice, and the CoC draws a clear line here. But what about “I
&lt;strong&gt;very strongly&lt;/strong&gt; object” or “Doing this would ruin what I love most about
Rust”? These aren’t personal attacks, and they’re often given along with
detailed technical critiques. Moreover, they accurately describe the feelings
being experienced by the author! Yet, I think such un-nuanced statements are
often counterproductive to the design approach at the heart of Rust.&lt;/p&gt;

&lt;p&gt;I’m going to spend the rest of this post unpacking that sentiment.&lt;/p&gt;

&lt;h2 id=&quot;pluralism-and-positive-sums&quot;&gt;Pluralism and positive sums&lt;/h2&gt;

&lt;p&gt;In the run-up to 1.0, the Rust community went through a process of articulating
the value propositions of the language, and — relatedly! — the design values for
the project. We developed a pattern of slogans that summarized our understanding
at that point:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Memory safety without garbage collection&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2015/05/11/traits.html&quot;&gt;Abstraction without overhead&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html&quot;&gt;Concurrency without data races&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2014/10/30/Stability.html&quot;&gt;Stability without stagnation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and ultimately: &lt;em&gt;Hack without fear&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The common thread here is reconciling oppositions. Not just finding a balance in
a tradeoff, but finding ways to reduce or eliminate the tradeoff itself. In
our &lt;a href=&quot;https://www.youtube.com/watch?v=pTQxHIzGqFI&quot;&gt;2016 RustConf keynote&lt;/a&gt;, Niko
and I talked about this as the Rust community “knowing how to have our cake and
eat it too”, as part of our challenge to the community to take another such
step:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In short, &lt;strong&gt;productivity should be a core value of Rust&lt;/strong&gt;, and we should work
creatively to improve it while retaining Rust’s other core values. By the end
of 2017, we want to have earned the slogan: Rust: fast, reliable,
productive—pick three.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, such reconciliations are not always possible, and certainly aren’t
easy. It’s an aspiration, not an edict. &lt;strong&gt;But Rust’s culture and design process
is engineered to produce such outcomes&lt;/strong&gt;, by embracing pluralism and
positive-sum thinking:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Pluralism&lt;/strong&gt; is about who we target: Rust seeks to simultaneously appeal to
die-hard C++ programmers and to empower dyed-in-the-wool JS devs, and to reach
several other varied audiences. That’s uncomfortable! These audiences are very
different, they have divergent needs and priorities, and the usual adage
applies: if you try to please everyone, you won’t please anyone. But…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Positive-sum thinking&lt;/strong&gt; is how we embrace pluralism while retaining a
coherent vision and set of values for the language. A zero-sum view would
assume that apparent oppositions are fundamental, e.g., that appealing to the
JS crowd inherently hurts the C++ one. A positive-sum view starts by seeing
different perspectives and priorities as &lt;em&gt;legitimate&lt;/em&gt; and &lt;em&gt;worthwhile&lt;/em&gt;, with a
faith that &lt;strong&gt;by respecting each other in this way, we can find strictly better
solutions than had we optimized solely for one perspective.&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can’t tell you the number of times I’ve experienced positive-sum outcomes when
working with the Rust community. Times when I’ve ended up with a design much
better than the one I started with, and got there because I thought it was
important to listen to people with different priorities.&lt;/p&gt;

&lt;p&gt;But there’s a lot of nuance here. Rust does not seek to be a language for
&lt;em&gt;everyone&lt;/em&gt;, but the audiences and use cases it does target are nevertheless
diverse. And pluralism happens at the level of community and goals, &lt;em&gt;not&lt;/em&gt; at the
level of the actual design. We don’t embrace “there’s more than one way to do
it” as a goal for our designs, nor do we “take the average” between opposed
priorities (and please no one). Ultimately, we have to make hard decisions.&lt;/p&gt;

&lt;p&gt;It’s the formal Rust teams, the people who make the final decisions, who are
tasked to take in and care about a plurality of &lt;em&gt;perspectives&lt;/em&gt;, but ultimately put
forth a singular, coherent &lt;em&gt;vision&lt;/em&gt;. They are the keepers of the vision, the
counterbalance to the process of exploration and give-and-take.&lt;/p&gt;

&lt;h2 id=&quot;fear-and-power&quot;&gt;Fear and power&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Second, [we must] “defend” the language many times, but failing once has
dire consequences. No matter how good the defenders are, they are going to let
something slip from time to time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(from &lt;a href=&quot;https://internals.rust-lang.org/t/fortifying-the-process-against-feature-bloat/7608&quot;&gt;Fortifying the process against feature bloat&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Many times, the language team hasn’t had a chance to even read the thread
before it spirals out of control like this one, because every little bit of
discussion makes you feel like you’re losing the fight.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;a href=&quot;https://internals.rust-lang.org/t/pre-rfc-flexible-try-fn/7564/112&quot;&gt;comment from @rpjohnst&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The idea that discussions can be “purely technical”, i.e. devoid of emotional
content, is bogus. If we care at any level about what we’re discussing, then our
emotions are going to play a role, and more likely than not, they will spill
over onto the thread.&lt;/p&gt;

&lt;p&gt;People care about Rust. It resonates with their values and experiences, in
specific and highly personal ways. Because of that context, seeing a proposal
that appears at odds with those values and experiences can be distressing. And
that feeling is only heightened when you also feel you have limited power.
Someone else is making the decision, there seems to be growing momentum around
it, and so you reach for the only tool you have: raising your voice as loud as
you can.&lt;/p&gt;

&lt;p&gt;And so we come back to Linus’s issue of “subtle” communication. His
recommendation is to amplify these feelings, to yell loud to make sure you’re
heard. “I’m against every idea in this proposal”. “This feature will ruin
Rust”. “Rust is heading in the wrong direction”.&lt;/p&gt;

&lt;p&gt;These feelings are real and legitimate. But embracing and amplifying them works
directly against the principles of plurality and positive-sum
thinking. &lt;strong&gt;Escalation encourages a zero-sum environment, an us-versus-them
battle, completely at odds with the positive-sum thinking that has led to Rust’s
best innovations&lt;/strong&gt;. And it’s a vicious cycle: if everyone is yelling, &lt;em&gt;truly&lt;/em&gt;
listening becomes very painful, and you “grow a thicker skin” in part by
learning to not take other people’s feelings so seriously… which means they
need to yell louder…&lt;/p&gt;

&lt;h2 id=&quot;humility-and-trust&quot;&gt;Humility and trust&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Those that do argue for the proposal you hate often don’t have a strong
opinion one way or the other yet—they may bring up counterpoints just to have
them on the table, or to explore the design space. And, you should note, they
often do wind up agreeing with you!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;a href=&quot;https://internals.rust-lang.org/t/pre-rfc-flexible-try-fn/7564/112&quot;&gt;comment from @rpjohnst&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Fear and creativity don’t mix. Working in a positive-sum, pluralistic way
requires significant vulnerability and emotional labor:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Humility, in order to genuinely question the instinct that your values, ideas
and opinions are the Right Ones.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Empathy, in order to genuinely “put on” someone else’s perspective, needs and
values as if they were your own.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Introspection, in order to reach a deeper understanding of your own impulses and values.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We look for these skills when selecting people to join the Rust teams, and we
expect them to do this kind of work when exploring a design space. But this is
delicate work, and we do it best when the work is shared by the &lt;em&gt;whole&lt;/em&gt;
community, not just team members. And, in particular, “unsubtle” shouting driven
by fear makes this work so, so much harder.&lt;/p&gt;

&lt;p&gt;This is why I feel distraught when I see accusations of bad faith, of people
having an “agenda” and the “listening” done in the RFC process being a charade
to avoid revolt. Or the sense of “luckily enough of us yelled to stop the
terrifying original proposal from happening; the moment we stop speaking up,
Those People will start pushing in that direction again”. All of these
sentiments indicate a rising distrust, a zero-sum power-focused framing, with
a dose of tribalism to boot.&lt;/p&gt;

&lt;p&gt;What we need is to work against the vicious circle of escalation by creating a
virtuous circle instead, based on humility and trust. &lt;strong&gt;If we can trust each
other to listen and take concerns seriously, we free ourselves to be uncertain
about those concerns, and open to possibilities that superficially work against
them&lt;/strong&gt;. In other words, we free ourselves to communicate and explore with
subtlety and nuance. Trust and humility go hand-in-hand. And they are the key to
finding positive-sum outcomes.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;A code of conduct is not enough. Being “nice” is not enough. We need to take a
leap of faith and embrace humility and trust in our discussions. &lt;strong&gt;It is my
strong belief that doing so will lead to strictly better ideas and decisions&lt;/strong&gt;,
enabling us to find positive-sum outcomes. But I also think it’s vital for
keeping our plural community whole and inclusive.&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;http://aturon.github.io/tech/2018/06/18/listening-part-3/&quot;&gt;next post&lt;/a&gt; in
this series, I’ll present some concrete case studies from Rust’s past and present,
examining how the discussions functioned and what we might learn from them.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>aturon.log: listening and trust, part 1</title>
   <link href="http://aturon.github.io/tech/2018/05/25/listening-part-1/"/>
   <updated>2018-05-25T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/05/25/listening-part-1</id>
   <content type="html">&lt;p&gt;For me, most weeks working on Rust are fun — &lt;a href=&quot;http://aturon.github.io/tech/2018/02/09/amazing-week/&quot;&gt;exhilarating, even&lt;/a&gt;. But, just like with anything else, some weeks are hard.&lt;/p&gt;

&lt;p&gt;As this week draws to a close, I feel troubled. On the one hand, things are looking strong for the 2018 Edition (which I want to write more about soon). But on the other hand, this week I locked two RFC threads, flagged a bunch of comments for moderation, and generally absorbed a lot of emotion from a lot of different quarters of the community. There’s a sense of simmering distrust.&lt;/p&gt;

&lt;p&gt;I worry sometimes about becoming a victim of our own success: if our community grows more quickly than we can establish shared values/norms/culture, we could so easily descend into acrimony and tribalism. I’ve seen other language communities go through very painful periods, and I’m eager to try to steer Rust’s community around them if we can.&lt;/p&gt;

&lt;p&gt;I’m a strong believer in the fundamental importance of listening for building trust. But I’ve realized that &lt;em&gt;talking&lt;/em&gt; is also important, and that Rust’s leadership needs to do &lt;a href=&quot;https://internals.rust-lang.org/t/fortifying-the-process-against-feature-bloat/7608/29?u=aturon&quot;&gt;a better job&lt;/a&gt; broadcasting about the people and process side of the project. This post is the beginning of an ongoing series; posts like this will form a “leadership diary”, focusing on my &lt;em&gt;highly personal&lt;/em&gt; perspective as a leader — not on technical issues but rather on how the project runs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This week saw several controversies:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2444&quot;&gt;An RFC&lt;/a&gt; to “undo” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt; in argument position, a feature that &lt;a href=&quot;https://blog.rust-lang.org/2018/05/10/Rust-1.26.html&quot;&gt;recently shipped&lt;/a&gt; in stable Rust.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2441#issuecomment-390406492&quot;&gt;Outcry&lt;/a&gt; about keyword reservations for the 2018 Edition.&lt;/li&gt;
  &lt;li&gt;Heated discussion on numerous threads about the role and importance of emoji reactions in GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These may seem unrelated, but I think they all boil down to the same core issue: listening and trust.&lt;/p&gt;

&lt;p&gt;When I first started working on Rust in mid-2014, the RFC process had &lt;em&gt;just&lt;/em&gt; been put into place, and we were collectively grappling with how to make it work. At that time, there was a weekly video meeting, comprised mostly of Mozilla staff, in which RFC decisions were made (amongst other things). You can see the history of this meeting &lt;a href=&quot;https://github.com/rust-lang/meeting-minutes/tree/master/weekly-meetings&quot;&gt;here&lt;/a&gt;, all the way up to the point &lt;a href=&quot;https://github.com/rust-lang/meeting-minutes/blob/master/weekly-meetings/2015-05-26.md#future-of-weekly-meeting&quot;&gt;it was shut down&lt;/a&gt;, just after Rust 1.0.&lt;/p&gt;

&lt;p&gt;Looking back, it’s hard for me to believe that things used to operate this way. And although the process is &lt;em&gt;very&lt;/em&gt; different now, I sometimes think those early, closed-door, Mozilla-centric meetings were a kind of “original sin” that laid seeds of distrust that we’re still working through today.&lt;/p&gt;

&lt;h2 id=&quot;the-great-int-debate-and-the-no-new-rationale-rule&quot;&gt;The Great &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; Debate, and the No New Rationale rule&lt;/h2&gt;

&lt;p&gt;A critical turning point came at the end of 2014, stemming from a rather innocuous-seeming issue: what to call the types that eventually became &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isize&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the time, the types were called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint&lt;/code&gt;, but these names had been &lt;a href=&quot;https://github.com/rust-lang/rust/issues/9940&quot;&gt;debated on the issue tracker&lt;/a&gt; for over a year. As the time for Rust 1.0 drew near, finalizing these names was one of the countless “small issues” that needed to be settled for good. Seeing this as a relatively minor issue, project leaders read the comment history, discussed the matter in — you guessed it! — a closed-door meeting, and then posted an &lt;a href=&quot;https://internals.rust-lang.org/t/a-tale-of-twos-complement/1062&quot;&gt;extensive writeup&lt;/a&gt;, which included a very important sentence:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We (the core team) have been reading these threads and have also done a lot of internal experimentation, and we believe we’ve come to a final decision on the fate of integers in Rust.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The result was… explosive. And rightfully so! I am forever indebted to glaebhoerl, who &lt;a href=&quot;https://www.reddit.com/r/rust/comments/2qmeeq/rfc_rename_intuint_to_intxuintx/cn8ugag/&quot;&gt;articulated the problem&lt;/a&gt; with painful clarity:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Importantly though: There was almost zero participation from members of the core team in &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/464&quot;&gt;the public discussion thread&lt;/a&gt;. That’s what I most think is not right. When anyone else has an opinion on an RFC that they want to express, whether in support or opposition, what they have to do is to lay out their reasoning as a comment in the discussion thread. Then other people can read, be swayed by it, or not, respond to it, and a productive discussion may ensue. Why is it a good idea for members of the core team to be entitled to skip this, to keep their reasoning and discussions to themselves, and only reveal it together with their final decision?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This moment crystallized the dysfunction in the early days of RFCs. I’m proud to say that the core team ultimately responded by going back to square one and &lt;a href=&quot;https://internals.rust-lang.org/t/restarting-the-int-uint-discussion/1131&quot;&gt;fully engaging&lt;/a&gt;, and in the end, the decision was reversed.&lt;/p&gt;

&lt;p&gt;But more important than that: the experience led to numerous shifts in the process. The most direct was codifying what I call the “No New Rationale” rule:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No New Rationale&lt;/strong&gt;: decisions must be made only on the basis of rationale already debated in public (to a steady state)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what we say about this in the &lt;a href=&quot;https://github.com/rust-lang/rfcs&quot;&gt;RFC process README&lt;/a&gt; (emphasis mine):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At some point, a member of the subteam will propose a “motion for final comment period” (FCP), along with a &lt;em&gt;disposition&lt;/em&gt; for the RFC (merge, close, or postpone).
    &lt;ul&gt;
      &lt;li&gt;This step is taken when enough of the tradeoffs have been discussed that the subteam is in a position to make a decision. That does not require consensus amongst all participants in the RFC thread (which is usually impossible). &lt;strong&gt;However, the argument supporting the disposition on the RFC needs to have already been clearly articulated, and there should not be a strong consensus&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;against&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;that position outside of the subteam&lt;/strong&gt;. Subteam members use their best judgment in taking this step, and the FCP itself ensures there is ample time and notification for stakeholders to push back if it is made prematurely.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The “FCP” process, which involves consent of all subteam members, plays out entirely on the RFC thread, and is mediated by our beloved @rfcbot. And it’s specifically designed to signal that the team believes the discussion has reached a steady state, and give participants ample time to object if they disagree (or believe that some commentary hasn’t been sufficiently addressed).&lt;/p&gt;

&lt;p&gt;In addition, &lt;em&gt;all&lt;/em&gt; major project decisions &lt;a href=&quot;https://github.com/rust-lang/rfcs#when-you-need-to-follow-this-process&quot;&gt;must go through the RFC process.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The unifying theme here is a steady move away from “being in the room when it happens” to a fully inclusive process, and it’s something we’re always working to improve.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So with all of that, why am I troubled? Because I’m seeing increasing signs of distrust, “us vs them” thinking, and people feeling like they have to yell in order to be listened to. And I’m also seeing a lot of divergent understanding of how the RFC/decision-making process is &lt;em&gt;supposed&lt;/em&gt; to work.&lt;/p&gt;

&lt;p&gt;The Rust community prides itself on being a friendly and welcoming place, but it’s going to take constant, explicit work to keep it that way — and part of that work is being forthright about the cases where things have gotten less than friendly, pausing and working together to figure out why.&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;http://aturon.github.io/tech/2018/06/02/listening-part-2/&quot;&gt;next post&lt;/a&gt; on this topic, I plan to focus on the kinds of breakdown I’ve been seeing, and some of my hypotheses about the underlying causes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Borrowing in async code</title>
   <link href="http://aturon.github.io/tech/2018/04/24/async-borrowing/"/>
   <updated>2018-04-24T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/04/24/async-borrowing</id>
   <content type="html">&lt;p&gt;The
&lt;a href=&quot;https://internals.rust-lang.org/t/announcing-the-network-services-working-group-wg-net/7354&quot;&gt;networking working group&lt;/a&gt; is
pushing hard on async/await notation for Rust, and @withoutboats in particular
wrote a fantastic blog series working through the design space (final
post &lt;a href=&quot;https://boats.gitlab.io/blog/post/2018-04-06-async-await-final/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I wanted to talk a little bit about some of the &lt;em&gt;implications&lt;/em&gt; of async/await,
which may not have been entirely clear. In particular, &lt;strong&gt;async/await is not just
about avoiding combinators; it completely changes the game for borrowing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The core issue is that, while the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt; trait does not itself impose a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; bound, in practice futures have to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; because they are
tossed onto executors like thread pools and hence not tied to any particular
stack frame. Today, what that means is that futures-based APIs have to be
careful not to hold on to borrows, and instead take ownership of whatever they
need. That in turn leads to all kinds of unidiomatic patterns, including
threading through ownership and widespread use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RefCell&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;idioms-in-the-standard-library&quot;&gt;Idioms in the standard library&lt;/h2&gt;

&lt;p&gt;To see what I mean, it’s helpful to work through an example. Let’s take the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; method from the standard library:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&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;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&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;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This method takes a mutable reference to both an I/O object and a buffer to read
into, then does the read synchronously. That lets you write idiomatic code like
the following:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&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;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;nf&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;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cursor&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;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is perfectly ordinary code, in which we repeatedly take mutable borrows
within a loop.&lt;/p&gt;

&lt;h2 id=&quot;idioms-in-futures-today&quot;&gt;Idioms in futures today&lt;/h2&gt;

&lt;p&gt;If we wanted to translate the above to an asynchronous setting using futures,
we’d need to use a futures-based analog to the read method. That exists today
with roughly the following signature:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&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;nb&quot;&gt;AsMut&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;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;k&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;impl&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&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;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&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;k&quot;&gt;Self&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;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That signature looks rather different! The reason is that we want the returned
future to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt;, so we have to pass in (and return) ownership of both the
I/O object and the buffer.&lt;/p&gt;

&lt;p&gt;Not only is the signature more complicated: it’s also unwieldy to use, even if
we employ async/await notation:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// box this up so we&apos;re not moving it around&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;nb&quot;&gt;Box&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;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&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;n&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;AsMut&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;nb&quot;&gt;u8&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_mut&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.cursor&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Buf&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;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cursor&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;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&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;socket&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_buf&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;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.cursor&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;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_buf&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;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;Err&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;p&quot;&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While we could take steps to make this particular example easier, the fact is
that requiring you to always move values in and out of async code prevents you
from following the usual Rust idioms for borrowing.&lt;/p&gt;

&lt;h2 id=&quot;borrowing-in-async-code&quot;&gt;Borrowing in async code&lt;/h2&gt;

&lt;p&gt;You might wonder: why can’t we just use the following signature instead?&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And indeed, you &lt;em&gt;can&lt;/em&gt; write and implement such a function; you just can’t
effectively use it. The problem is that the future you get back contains
borrowed values, which today will prevent it from being used in most
futures-based code, due to there being a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; requirement to ultimately
execute futures.&lt;/p&gt;

&lt;p&gt;This is where the async/await plan comes in: &lt;strong&gt;you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; a future with
borrowed data, while still being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; overall!&lt;/strong&gt;. This is what it means to
support “borrowing across yield points”, as explained in
@withoutboats’s
&lt;a href=&quot;https://boats.gitlab.io/blog/post/2018-01-25-async-i-self-referential-structs/&quot;&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In particular, using this borrowing version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt;, we can write:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;socket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&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;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&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;socket&lt;/span&gt;&lt;span class=&quot;nf&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;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cursor&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;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and the type of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; block will be:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&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;o&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;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Despite the fact that we borrow &lt;em&gt;internally&lt;/em&gt; within the async block, the block
as a whole produces a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; future which we can spawn onto a thread pool or
other executor.&lt;/p&gt;

&lt;p&gt;In other words, &lt;strong&gt;the async/await proposal allows you to write fully idiomatic
Rust code that runs asynchronously&lt;/strong&gt;. That applies even to signatures; the
borrowing version of async &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; will ultimately look as follows:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&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;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&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;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This signature is &lt;em&gt;exactly&lt;/em&gt; the same as for the synchronous version, just with
an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; on the front.&lt;/p&gt;

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

&lt;p&gt;The bottom line is that async/await isn’t just about not having to use
combinators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and_then&lt;/code&gt;. It also fundamentally changes API design in the
async world, allowing us to use borrowing in the idiomatic style. Those who have
written much futures-based code in Rust will be able to tell you just how big a
deal this is.&lt;/p&gt;

&lt;p&gt;Right now the networking WG is focused on landing async/await itself
(which
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2394#issuecomment-383773009&quot;&gt;will probably happen soon&lt;/a&gt;),
and providing a migration path for the futures crate. Once those basics are in
place, though, we’ll be able to revisit APIs throughout the async stack and make
them more idiomatic. With luck, we’ll have a very strong story in place for Rust 2018.&lt;/p&gt;

&lt;p&gt;If you’re interested in getting involved in this effort, please check out the &lt;a href=&quot;https://gitter.im/rust-lang/WG-net&quot;&gt;Net WG gitter&lt;/a&gt;
and &lt;a href=&quot;https://github.com/rust-lang-nursery/net-wg/&quot;&gt;repo&lt;/a&gt;!&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Cargo, Xargo, and Rustup</title>
   <link href="http://aturon.github.io/tech/2018/04/06/rustup-xargo/"/>
   <updated>2018-04-06T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/04/06/rustup-xargo</id>
   <content type="html">&lt;p&gt;Another topic of discussion at the &lt;a href=&quot;https://blog.rust-lang.org/2018/04/06/all-hands.html&quot;&gt;Berlin Rust All Hands&lt;/a&gt; was the long-term
story around Cargo, Xargo, and Rustup. The latter two tools are both involved in
managing your Rust toolchain, with Xargo allowing you to build custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;s and
Rustup managing pre-built artifacts for mainstream targets. Xargo is most
commonly used for cross-compiling to less common platforms, but can also be used
to customize the standard library on mainstream platforms.&lt;/p&gt;

&lt;p&gt;The tools today are a bit of a muddle: Xargo acts as a CLI wrapper around Cargo,
while Rustup is a completely separate tool, despite the fact that they handle
some similar responsibilities. Moreover, Rustup cannot manage targets set up by
Xargo. And there’s long been a desire for toolchain requirements to be expressed
directly within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;, so that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo build&lt;/code&gt; is all that is ever required
to build a Rust package.&lt;/p&gt;

&lt;p&gt;Given all that context, we’ve talked at various junctures about simply
integrating &lt;em&gt;all&lt;/em&gt; of the above functionality into Cargo. We had another such
discussion at the All Hands, which I’ll summarize below. &lt;strong&gt;Note&lt;/strong&gt;: as always,
this summary covers &lt;em&gt;preliminary&lt;/em&gt; thoughts; all changes will go through the
usual RFC process.&lt;/p&gt;

&lt;h2 id=&quot;xargo-integration&quot;&gt;Xargo integration&lt;/h2&gt;

&lt;p&gt;There is widespread agreement that Xargo’s functionality should instead be
expressed directly within Cargo, along the rough lines of the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1133&quot;&gt;std-aware Cargo
RFC&lt;/a&gt;. In particular, we strongly want the ability to enrich &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; with feature
flags and enable crates to customize those flags.&lt;/p&gt;

&lt;p&gt;There are a lot of open design questions here; in particular, there is &lt;em&gt;not&lt;/em&gt;
consensus on the details in the std-aware RFC. There are a lot of moving parts,
since the ability to specify details for the standard library is closely related
to specifying details about the compiler version and release channel as well.&lt;/p&gt;

&lt;p&gt;The upshot, though, is that once we have this integration the concept of
“target” within &lt;em&gt;Rustup&lt;/em&gt; can disappear entirely (though, of course, the target
must be specified at some point in the build process). Rather than manually
installing a list of targets per toolchain, Cargo will automatically set up
targets as needed, either building them or downloading cached binaries when
available.&lt;/p&gt;

&lt;h2 id=&quot;rustup-integration&quot;&gt;Rustup integration&lt;/h2&gt;

&lt;p&gt;In general, folks didn’t see a lot of value in having toolchain management
handled by a separate command from Cargo, especially given the desire for crates
to specify toolchain dependency information. Hence, while there will probably
always be a need to have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustup&lt;/code&gt; &lt;em&gt;binary&lt;/em&gt;, we want to explore exposing its
functionality through Cargo instead.&lt;/p&gt;

&lt;p&gt;Here, again, the hard work is in the details. We probably want some combination of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Toolchain declarations within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;, as with the Xargo integration.&lt;/li&gt;
  &lt;li&gt;Automatic toolchain component installation.&lt;/li&gt;
  &lt;li&gt;New Cargo subcommands for manual toolchain adjustments.&lt;/li&gt;
  &lt;li&gt;Additional settings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cargo/config&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All told, the hope is that we can replace some of Rustup’s unique aspects (like
its override system) with uses of standard Cargo concepts (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cargo/config&lt;/code&gt;), and generally speaking to make toolchain management
“disappear”, instead driving it on demand as part of the normal project
workflows.&lt;/p&gt;

&lt;p&gt;One other insight: since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustup&lt;/code&gt; the tool will likely stay around in some form,
we can retain its CLI for niche cases, meaning that the Cargo integration only
needs cover the common case, and can thus likely make some simplifications.&lt;/p&gt;

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

&lt;p&gt;The most pressing issue to address for the Rust 2018 release is the needs of the
Embedded WG, where Xargo is currently commonly used to set up embedded targets.
It turns out, though, that by raising a handful of those targets to Tier 1
status (which has other benefits besides), the large majority of these cases will
be covered just by using Rustup.&lt;/p&gt;

&lt;p&gt;On the whole, the Rust community is entering another “impl period” like state:
for the next several months, the focus will be on executing all of the plans
already laid for Rust 2018, rather than on brand new design. So the relevant
teams plan to pick back up these integration questions in the last quarter of
the year, after the 2018 edition has shipped.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Futures 0.2 is here!</title>
   <link href="http://aturon.github.io/tech/2018/04/06/futures2/"/>
   <updated>2018-04-06T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/04/06/futures2</id>
   <content type="html">&lt;p&gt;As of this morning, the futures crate version 0.2.0 is now available on
crates.io! You can get the full low-down on the changes
from &lt;a href=&quot;http://aturon.github.io/tech/2018/02/27/futures-0-2-RC/&quot;&gt;my earlier post&lt;/a&gt;; here
I’ll review the overall roadmap and what this release means.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our goal is to ship async/await in Rust 2018 (roughly by mid-September), and
to ship futures 1.0 this year.&lt;/strong&gt; All told, this work will provide a stable and
ergonomic foundation for async programming in Rust. But it will take a few steps
to get there!&lt;/p&gt;

&lt;h2 id=&quot;todays-release&quot;&gt;Today’s release&lt;/h2&gt;

&lt;p&gt;The 0.2.0 release today marks an important &lt;strong&gt;snapshot&lt;/strong&gt; of our progress so far:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It completely revamps the task/executor system — the most hairy and confusing part of futures 0.1.&lt;/li&gt;
  &lt;li&gt;It sets up the crate to more easily allow for iteration.&lt;/li&gt;
  &lt;li&gt;It makes a large number of long-standing API tweaks that required breakage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It has also been fully integrated into both Tokio and Hyper under experimental feature flags.&lt;/p&gt;

&lt;h2 id=&quot;whats-ahead&quot;&gt;What’s ahead&lt;/h2&gt;

&lt;p&gt;Concurrent with the 0.2.0 release, we’ve posted two RFCs to rust-lang covering,
respectively, the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2394&quot;&gt;language&lt;/a&gt; and &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2395&quot;&gt;library&lt;/a&gt; additions needed to support
async/await notation.&lt;/p&gt;

&lt;p&gt;On the library side, the RFC proposes two significant changes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt;
compared to the freshly-minted 0.2 release:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The use of &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2349&quot;&gt;pinned types&lt;/a&gt; to enable borrowing within futures.&lt;/li&gt;
  &lt;li&gt;Removing the associated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; types (and adjusting combinators accordingly).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not currently possible to make these changes, because of rustc limitations,
but these are expected to be addressed quite soon.&lt;/p&gt;

&lt;p&gt;The overall plan is to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Immediately begin work a 0.3 branch that fully matches the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2395&quot;&gt;library&lt;/a&gt; RFC.&lt;/li&gt;
  &lt;li&gt;Publish the 0.3 version, &lt;em&gt;initially as nightly-only&lt;/em&gt;, as soon as the rustc limitations around pinning are lifted.&lt;/li&gt;
  &lt;li&gt;Publish a 0.3.x version that works on the stable channel, as soon as pinning is stable.&lt;/li&gt;
  &lt;li&gt;Publish a 0.3.x version that simply re-exports the core APIs from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;, once they are available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, the 0.3 release will be forward-compatible with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; version of futures-core APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR: experimentation and feedback on this 0.2 snapshot is very welcome,
but we anticipate a 0.3 release relatively soon&lt;/strong&gt;. That release will set a
stable foundation for futures-core, after which we can focus on iterating the
rest of the stack to take full advantage of async/await!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Custom tasks in Cargo</title>
   <link href="http://aturon.github.io/tech/2018/04/05/workflows/"/>
   <updated>2018-04-05T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/04/05/workflows</id>
   <content type="html">&lt;p&gt;One of the big requests from the &lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/2314-roadmap-2018.md#domains&quot;&gt;Domain Working Groups&lt;/a&gt; for Rust 2018 is a
richer feature set for framework- or domain-specific workflows in Cargo. At the
simplest level, that might look like &lt;em&gt;project templates&lt;/em&gt; – the ability to
direct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo new&lt;/code&gt; to start with a custom template defined in crates.io. That’s
already enough to get you cooking with frameworks like &lt;a href=&quot;https://github.com/killercup/quicli&quot;&gt;QuiCLI&lt;/a&gt;, which today
involve a fixed set of initial scaffolding that you can fill in.&lt;/p&gt;

&lt;p&gt;More ambitiously, though, working within a particular framework or domain may
require special workflows &lt;em&gt;after&lt;/em&gt; initial project creation. For example, a web
framework might want to provide workflows for making database changes or adding
new resources.&lt;/p&gt;

&lt;p&gt;At the Rust All Hands in Berlin last week, the Cargo team and other stakeholders
talked about these desires and cooked up a simple but compelling plan to address
them.&lt;/p&gt;

&lt;h2 id=&quot;cargo-tasks&quot;&gt;Cargo tasks&lt;/h2&gt;

&lt;p&gt;The core idea is extremely simple. We add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[tasks]&lt;/code&gt; section to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;,
with entries resembling normal dependencies. However, the &lt;em&gt;binaries&lt;/em&gt; provided by
those packages are automatically available from the Cargo CLI via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;task&lt;/code&gt;
subcommand.&lt;/p&gt;

&lt;p&gt;Suppose for example that we have the following in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[tasks]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;rust-on-rails&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rust-on-rails&lt;/code&gt; crate provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt; bins, then you’d be
able to type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; cargo task server
&amp;gt; cargo task console
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;at the CLI to invoke those binaries.&lt;/p&gt;

&lt;p&gt;Ultimately, we may want to avoid the need for writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;task&lt;/code&gt;, but this raises
questions about conflicts with built-in and installed custom commands that we
didn’t want to get into.&lt;/p&gt;

&lt;p&gt;Anyway… that’s it! A very simple but powerful idea.&lt;/p&gt;

&lt;h2 id=&quot;metapackages&quot;&gt;Metapackages&lt;/h2&gt;

&lt;p&gt;In subsequently discussing these ideas with @wycats, he (as always) raised a
very astute point: in some package managers, the existence of project templates
has made it easy to set up leaky abstractions. For example, if we do have a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rust-on-rails&lt;/code&gt; crate, it would probably provide a Cargo template that would
include &lt;em&gt;several&lt;/em&gt; sections of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; – at the very least, both
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[dependencies]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[tasks]&lt;/code&gt;. But that’s not really what we want;
conceptually, these are all part of the same framework, and should be versioned
together, requiring only a single entry to bring into your project.&lt;/p&gt;

&lt;p&gt;Incidentally, the same is already true of things like custom derives and build
scripts, where to use what is conceptually a single package requires multiple
bits of setup.&lt;/p&gt;

&lt;p&gt;A while back I proposed &lt;a href=&quot;http://aturon.github.io/tech/2016/07/27/rust-platform/&quot;&gt;metapackages&lt;/a&gt; as a way of grouping and versioning a
&lt;em&gt;set&lt;/em&gt; of dependencies. But in my chat with @wycats, we had the insight that
metapackages could more generally be a way of &lt;em&gt;abstracting a chunk of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;&lt;/em&gt;, including not just normal dependencies, but also tasks, build
scripts, and more.&lt;/p&gt;

&lt;p&gt;In this brave new world, a single dependency entry in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; is generally
all that is ever needed to bring in a conceptual package.&lt;/p&gt;

&lt;p&gt;Open question: what might this mean for things like &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2196/&quot;&gt;metabuild&lt;/a&gt;?&lt;/p&gt;

&lt;h2 id=&quot;todays-custom-subcommands&quot;&gt;Today’s custom subcommands?&lt;/h2&gt;

&lt;p&gt;One open question: if we provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[tasks]&lt;/code&gt;, how should we think about today’s
custom subcommands (generally set up via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo install&lt;/code&gt;)?&lt;/p&gt;

&lt;p&gt;One possibility would be to allow for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[tasks]&lt;/code&gt; section in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cargo/config&lt;/code&gt;,
basically using the same mechanism for &lt;em&gt;all&lt;/em&gt; workflow customization. But this
raises questions about conflicting names, global lockfiles, and more. More
thought and design is needed.&lt;/p&gt;

&lt;h2 id=&quot;prior-art&quot;&gt;Prior art?&lt;/h2&gt;

&lt;p&gt;Before finalizing any design here, we should do a survey of existing package
managers, many of which offer similar functionality and have learned painful
lessons.&lt;/p&gt;

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

&lt;p&gt;The most immediate step along these lines is to write and implement an RFC for
Cargo templates, which @withoutboats plans to do.&lt;/p&gt;

&lt;p&gt;After that, I’m hoping to pair up with @ag_dubs to dig into the ideas in this
post and put together an RFC. In the meantime, though, please let me know if you
have thoughts or pointers to prior art!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sound and ergonomic specialization for Rust</title>
   <link href="http://aturon.github.io/tech/2018/04/05/sound-specialization/"/>
   <updated>2018-04-05T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/04/05/sound-specialization</id>
   <content type="html">&lt;p&gt;Specialization holds the dubious honor of being among the oldest post-1.0
features remaining in unstable limbo. That’s for good reason, though: until
recently, we did not know how to make it sound.&lt;/p&gt;

&lt;p&gt;There’s a long history here, but I’ll pick up from the immediately previous
episode: Niko’s &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2018/02/09/maximally-minimal-specialization-always-applicable-impls/&quot;&gt;blog post on “max-min” specialization&lt;/a&gt;. While that post
showed, for the first time, an “obviously sound” approach to specialization, it
came at a severe ergonomic cost for the ecosystem. This post proposes a twist on
Niko’s idea that avoids its downsides.&lt;/p&gt;

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

&lt;p&gt;First, let’s reintroduce our nemesis: lifetime dispatch. I
wrote &lt;a href=&quot;https://aturon.github.io/blog/2017/07/08/lifetime-dispatch/&quot;&gt;at length&lt;/a&gt; about this problem before, but the core issue is
that for specialization to be sound, we need type checking and code generation (“trans”)
to agree on what it does. But there are two big things that happen between those
compiler phases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Monomorphization&lt;/strong&gt;, which instantiates all generics with actual types.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Lifetime erasure&lt;/strong&gt;, which destroys all lifetime information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lifetime erasure means that we must prevent lifetime-dependent specializations
like the following:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bad&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad&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;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Bad&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad&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;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&apos;t know if T: &apos;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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bad&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bad&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;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.bad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// what do we see?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In a case like this, the type checker has &lt;em&gt;more&lt;/em&gt; information than trans does,
and hence will use the more specialized impl. Trans, by contrast, has lost the
information that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;test&quot;&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt;, and hence cannot use the specialized
impl. This kind of disagreement can easily cause soundness problems.&lt;/p&gt;

&lt;p&gt;Unfortunately, it’s not so easy to fix, partly because “lifetime dependence” can
happen in very subtle, indirect ways, and partly because &lt;em&gt;monomorphization&lt;/em&gt;
causes information mismatches in the opposite direction, where trans knows more
than the type checker.&lt;/p&gt;

&lt;p&gt;Bottom line, we’ve searched long and hard in this space and come up short –
until fairly recently.&lt;/p&gt;

&lt;h2 id=&quot;nikos-max-min-proposal&quot;&gt;Niko’s max-min proposal&lt;/h2&gt;

&lt;p&gt;In Niko’s &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2018/02/09/maximally-minimal-specialization-always-applicable-impls/&quot;&gt;latest blog post&lt;/a&gt;, he proposes an ingenious strategy for
ensuring soundness: we simply bake in the needed requirements for any traits we
wish to specialize on.&lt;/p&gt;

&lt;p&gt;In particular, we want a specialization to occur only when the relevant impl is
“always applicable” (i.e. regardless of how type and lifetime parameters are
instantiated). This always-applicable test, in particular, ensures that the
difference in knowledge produced by monomorphization and lifetime erasure cannot
matter.&lt;/p&gt;

&lt;p&gt;The blog post is fairly long and contains several extensions, but basically
boils down to the following: an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; is &lt;strong&gt;always applicable&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it is fully generic with respect to lifetimes (no repetitions, use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt;, or constraints),&lt;/li&gt;
  &lt;li&gt;it doesn’t repeat any generic type parameters, and&lt;/li&gt;
  &lt;li&gt;the only trait bounds that appear are for “always applicable traits”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specialization is only allowed when the more specialized impl is always applicable.&lt;/p&gt;

&lt;p&gt;An “always applicable trait” is one that is marked with a special attribute,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[specialization_predicate]&lt;/code&gt;, which means that all impls of the trait &lt;em&gt;must&lt;/em&gt; be
always applicable. In other words, it forces the “always applicable” property to
apply recursively to all the traits involved in an impl.&lt;/p&gt;

&lt;p&gt;Now, this works quite well when specializing a blanket impl with an impl for a concrete type:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;cm&quot;&gt;/* default fns */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* specialized fns */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s because in this case, we aren’t adding any extra trait bounds nor type parameters.&lt;/p&gt;

&lt;p&gt;However, the proposal has a major downside, and one that it seems was not well
understood by the broader community: &lt;strong&gt;specialization based on traits like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TrustedLen&lt;/code&gt; requires those traits to be specially-marked, and doing so is a
breaking change!&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In particular, suppose we want to do the following:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;nb&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;..&lt;/span&gt; &lt;span class=&quot;p&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;nb&quot;&gt;Iterator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TrustedLen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;According to the definition above, this is only allowed if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TrustedLen&lt;/code&gt; is marked
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[specialization_predicate]&lt;/code&gt;. But nothing prevents there from being impls
like the following today:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TrustedLen&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&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;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[specialization_predicate]&lt;/code&gt; would make such impls illegal, breaking
downstream code. And more generally, both adding &lt;em&gt;or&lt;/em&gt; removing the attribute is
a breaking change, forcing all trait authors to make a difficult up-front
decision, and meaning that &lt;em&gt;none&lt;/em&gt; of the existing traits in the standard library
could be used as a bound in a specializing impl.&lt;/p&gt;

&lt;h2 id=&quot;a-new-idea&quot;&gt;A new idea&lt;/h2&gt;

&lt;p&gt;Last week at the Rust All Hands in Berlin, I talked to some members of the Libs
Team about the max-min proposal and it became clear that they’d missed the above
implications – and they were left quite dejected. “So does specialization solve
&lt;em&gt;any&lt;/em&gt; of the original use cases?”&lt;/p&gt;

&lt;p&gt;Naturally, that got me thinking whether we could do better, and I think we can
– basically by slightly repackaging Niko’s insight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key idea&lt;/strong&gt;: Rather than a per-trait attribute, we provide an explicit
&lt;em&gt;specialization modality&lt;/em&gt; for trait bounds. That is, you write something like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialize(T: TrustedLen)&lt;/code&gt; in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;where&lt;/code&gt; clause. This specialization mode is more
selective about which impls it considers: it effectively drops any impls that
constrain lifetimes or repeat generic parameters. Trait bounds, however, are
fine; they are just interpreted within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialize&lt;/code&gt; mode as well,
recursively. Thus, an impl is “always applicable” if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it is fully generic with respect to lifetimes (no repetitions, use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt;, or constraints),&lt;/li&gt;
  &lt;li&gt;it doesn’t repeat any generic type parameters, and&lt;/li&gt;
  &lt;li&gt;the only trait bounds that appear are (recursively) within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialize&lt;/code&gt; mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is easiest to see by example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The compiler refuses this specialization: it is not always applicable&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;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SomeTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The compiler refuses this specialization: it is not always applicable&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;n&quot;&gt;SomeTrait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The compiler **accepts** this specialization, because `specialize(T: SomeTrait)`&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// filters the applicable impls to only the &quot;always applicable&quot; ones.&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;specialize&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;SomeTrait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;true&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;c1&quot;&gt;// prints &quot;generic&quot;&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;0i32&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;c1&quot;&gt;// prints &quot;specialized:&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&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;c1&quot;&gt;// prints &quot;generic&quot;, because the `&amp;amp;&apos;static str` impl for `SomeTrait` is ignored&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, this design is &lt;em&gt;almost&lt;/em&gt; latent in the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;original RFC&lt;/a&gt;! The new
mechanism here, though, is an &lt;strong&gt;explicit filtering of impls&lt;/strong&gt; via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialize&lt;/code&gt;. This explicit filtering is helpful not just for soundness, but to
remind the programmer that specialization is &lt;em&gt;not&lt;/em&gt; considering &lt;em&gt;all&lt;/em&gt; impls, but
rather a filtered set.&lt;/p&gt;

&lt;p&gt;Moreover, it should be possible both within the type checker and in trans to
detect cases where the “naive” (unfiltered) specialization algorithm would have
produced a different result, and produce a warning in such cases.&lt;/p&gt;

&lt;p&gt;I believe that this approach is as “obviously” sound as Niko’s proposal; it
could even be understood as a kind of sugar over his proposal. And given our
experiences in this area, I’ve long since believed that the only acceptable
solution would have to be “obviously” sound – no clever tricks. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialize&lt;/code&gt; modality has a very natural interpretation in Chalk, where we are
already juggling &lt;a href=&quot;https://aturon.github.io/tech/2017/04/24/negative-chalk/&quot;&gt;other modalities related to crate-local reasoning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, it’s worth saying that the particular mechanism here is orthogonal to
the many other design questions around specialization, including things like
“intersection impls”, as well as the other extensions mentioned in Niko’s
previous post.&lt;/p&gt;

&lt;p&gt;While I’m doubtful that specialization will make it for the Rust 2018 release, I
think that with luck it could stabilize this year.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Putting bors on a PIP</title>
   <link href="http://aturon.github.io/tech/2018/03/19/bors/"/>
   <updated>2018-03-19T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/03/19/bors</id>
   <content type="html">&lt;p&gt;We have a problem: the average queue of ready-to-test PRs to the main Rust repo
has been steadily growing for a year. And at the same time, the likelihood of
merge conflicts is also growing, as we include more submodules and Cargo
dependencies that require updates to Cargo.lock.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This problem could threaten our ability to produce Rust 2018 on time&lt;/strong&gt;,
because as the year progresses, there will be an increasing amount of contention
for the PR queue. My goal in this post is to avoid this outcome, &lt;em&gt;without&lt;/em&gt;
reliving the Rust 1.0-era experience of Alex working full time to land massive
rollups.&lt;/p&gt;

&lt;p&gt;In particular, the Rust All Hands is coming up next week, and I think it’s a
great opportunity to dive into these issues, so after chatting for a while with
Alex I wanted to set out some ideas.&lt;/p&gt;

&lt;h1 id=&quot;goals-and-problems&quot;&gt;Goals and problems&lt;/h1&gt;

&lt;p&gt;There are two major bors experiences we care about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Small PRs from early contributors. We want these to land very quickly to
provide a good contribution experience.&lt;/li&gt;
  &lt;li&gt;Major PRs. We want to avoid requiring lots of rebasing, or having &lt;em&gt;too&lt;/em&gt; long a
delay before landing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s say “bors time” is the amount of time a PR is in mergable and r+’ed state
but not yet landed. Quantitatively, the above goals probably map to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Low &lt;em&gt;average&lt;/em&gt; bors time&lt;/li&gt;
  &lt;li&gt;Low &lt;em&gt;maximum&lt;/em&gt; bors time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rollups-today&quot;&gt;Rollups today&lt;/h2&gt;

&lt;p&gt;Today, rollups generally group together a large number of small PRs; we then
attempt to land those rollups aggressively. &lt;strong&gt;The result is improved average
bors time, but often at the cost of worsening &lt;em&gt;maximum&lt;/em&gt; bors time.&lt;/strong&gt;
That’s because of a few factors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Rollups generally prioritize &lt;em&gt;small&lt;/em&gt; PRs over &lt;em&gt;old&lt;/em&gt; PRs. That is, the “normal”
order for bors is to attempt the oldest ready-to-test PR. But when doing a
rollup, we cherry pick throughout the queue, and then give maximum priority to
the rollup.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Rollups generally bounce on the first couple of attempts, which is “wasted”
time during which an older PR might have been able to merge.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, rollups tend to cause a need for rebasing, which for major PRs
introduces significant extra latency: the author has to get around to doing a
rebase, then get back in the queue, with a non-trivial chance of being
pre-empted by &lt;em&gt;another&lt;/em&gt; rollup that requires further rebasing.&lt;/p&gt;

&lt;h2 id=&quot;overall-queue-length&quot;&gt;Overall queue length&lt;/h2&gt;

&lt;p&gt;The steady state of the queue has been worsening over time. The average queue
length has roughly quadrupled over the last year, from 5 ready PRs to 20.&lt;/p&gt;

&lt;p&gt;The longer the queue, the worse the situation is for major PRs, because the
effects of rollups and rebase requirements is multiplied by the standing queue
length.&lt;/p&gt;

&lt;h1 id=&quot;some-ideas&quot;&gt;Some ideas&lt;/h1&gt;

&lt;p&gt;I believe that, because of rollups, our current &lt;em&gt;average&lt;/em&gt; bors time remains
tolerable. But our &lt;em&gt;maximum&lt;/em&gt; bors time has gotten quite bad as the steady-state
queue size has continued to grow. We need to rebalance.&lt;/p&gt;

&lt;h2 id=&quot;reduce-absolute-cycle-time&quot;&gt;Reduce absolute cycle time&lt;/h2&gt;

&lt;p&gt;The most direct action is to reduce absolute cycle time by improving the build
system. That will help across the board, and there is usually low-hanging fruit
to be had on whatever our current-slowest build scenarios are.&lt;/p&gt;

&lt;p&gt;I’m not qualified to say much more here, but I’m hopeful that, during the All
Hands, the Infra Team can work together to come up with plans or guidance on
this front.&lt;/p&gt;

&lt;h2 id=&quot;reduce-failures&quot;&gt;Reduce failures&lt;/h2&gt;

&lt;p&gt;Failed builds are often very expensive, since failures often occur late in the
build cycle, meaning that we lose ~2.5 hours of serialized work.&lt;/p&gt;

&lt;h3 id=&quot;spurious-failures&quot;&gt;Spurious failures&lt;/h3&gt;

&lt;p&gt;Currently, spurious failures &lt;em&gt;largely&lt;/em&gt; come down to timeouts; reducing absolute
cycle time will help.&lt;/p&gt;

&lt;p&gt;More radically, we could consider storing artifacts at each build stage,
allowing us to retry a build without going through the cycle scratch. But that
would amount to a complete reworking of the build system, and probably isn’t
plausible for the Rust 2018 timeline.&lt;/p&gt;

&lt;h3 id=&quot;legit-failures&quot;&gt;Legit failures&lt;/h3&gt;

&lt;p&gt;But there are also “legit” failures — and there’s potentially a lot we could do
to help there. We effectively have a two-stage CI system today:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Stage 1&lt;/strong&gt;: automatic PR testing. Today this is a single Travis build, hence
a small slice of our overall test suite. &lt;strong&gt;Stage 1 testing is almost always
complete by the time a reviewer looks at a PR.&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Stage 2&lt;/strong&gt;: serialized, full PR testing via bors.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stage 1 testing is parallelizable and &lt;em&gt;masks queue length&lt;/em&gt; because it’s
generally dominated by the time it takes to get a review. &lt;strong&gt;We can decrease the
likelihood of legit failures by testing more build scenarios in stage 1.&lt;/strong&gt; For
example, we could gate stage 1 on Windows as well as Linux. And we could include
more of the test suite in stage 1. Generally, we have some amount of free
capacity to work with here, and we can always through in additional builders to
get more.&lt;/p&gt;

&lt;p&gt;We should also consider strongly gating on stage 1 passing before ever
attempting stage 2 testing on a PR.&lt;/p&gt;

&lt;p&gt;More generally, are there ways we can better take advantage of the two-stage
system we have today, and the way in which stage 1 is “masked” by review
latency?&lt;/p&gt;

&lt;h2 id=&quot;being-more-strategic-with-rollups&quot;&gt;Being more strategic with rollups&lt;/h2&gt;

&lt;p&gt;Right now rollups generally gather together a number of “easy” PRs. However,
this comes at the cost of “hard” PRs, because rollups skip them in the queue,
thus forcing a rebase. And rollups themselves tend to bounce on the first few
tries, essentially blocking the build queue for some period.&lt;/p&gt;

&lt;p&gt;Here are some ways we could be smarter about rollups:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Prioritize a rollup PR as if it is as old as the oldest PR is contains.&lt;/strong&gt;
That is, in bors’s normal queue ordering, a rollup would not make it possible
to “jump the queue”. Rather, it would be running at the same time as its first
PR normally would, but we’d be trying to “get more” out of the run.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make it possible to pre-test rollup PRs with a greater number of build
scenarios, without blocking the queue.&lt;/strong&gt; We could do this by expanding the set
of stage 1 tests (mentioned above) in general, or by having a separate
“try”-style build command for rollups that tests a larger subset, but still
much smaller than the full build (i.e. “Stage 1.5”). &lt;strong&gt;We should make it
possible to aggressively run this larger suite of tests on a rollup build,
&lt;em&gt;before&lt;/em&gt; going to the full test suite.&lt;/strong&gt; The core idea is that a rollup should
~never bounce.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fix test failures within a rollup, rather than removing PRs from the
rollup&lt;/strong&gt;. This can be done by pushing changes back to the original PR
branches. Basically, once we’ve invested in including a PR in a rollup, we
should “see it through”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Consider including “bigger” PRs in a rollup&lt;/strong&gt;, and seeing them through as
above.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;data-to-gather&quot;&gt;Data to gather&lt;/h1&gt;

&lt;p&gt;There’s a bunch of data that would be great to have before the All Hands to help
guide discussion:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How often are we making rollups?&lt;/li&gt;
  &lt;li&gt;How many PRs are included in the average rollup?&lt;/li&gt;
  &lt;li&gt;How often do rollups bounce?
    &lt;ul&gt;
      &lt;li&gt;What % spurious?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;How often do non-rollups bounce?
    &lt;ul&gt;
      &lt;li&gt;What % spurious?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;For non-spurious failures, what are the major cases we’re missing in stage 1
that we catch in stage 2? E.g., Windows? A particular part of the test suite?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;what-else&quot;&gt;What else?&lt;/h1&gt;

&lt;p&gt;Are there other &lt;em&gt;near term&lt;/em&gt; steps we could take to head off problems with the
queue length? (While long-term improvements are important too, the immediate
risk is that we will struggle to produce Rust 2018 over the next few months).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Futures 0.2 is nearing release</title>
   <link href="http://aturon.github.io/tech/2018/02/27/futures-0-2-RC/"/>
   <updated>2018-02-27T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/02/27/futures-0-2-RC</id>
   <content type="html">&lt;p&gt;On behalf of the futures-rs team, I’m very happy to announce that the master
branch is now at 0.2: we have a release candidate! Barring any surprises, we
expect to publish to crates.io in the next week or two.&lt;/p&gt;

&lt;p&gt;You can peruse the 0.2 API via the &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/index.html&quot;&gt;hosted crate docs&lt;/a&gt;, or dive right in to the
master branch. Note that Tokio is not currently compatible with Futures 0.2; see
below for more detail.&lt;/p&gt;

&lt;h2 id=&quot;whats-futures-02-about&quot;&gt;What’s Futures 0.2 about?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Futures 0.2 release is all about putting us on a road toward 1.0 this
year&lt;/strong&gt;. To that end, it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Makes numerous long-desired API improvements, many of which are breaking
changes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Positions the crate for significant iteration this year by (temporarily!)
breaking it into a number of independently-versioned subcrates.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full details are in the &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/pulls?q=is%3Apr+label%3A0.2&quot;&gt;three RFCs&lt;/a&gt;, but we’ll review the high level
changes here.&lt;/p&gt;

&lt;h3 id=&quot;api-improvement-explicit-task-contexts&quot;&gt;API improvement: explicit task contexts&lt;/h3&gt;

&lt;p&gt;The heart of the futures library is its task system. But historically, that task
system was almost invisible: information about the current task in 0.1 was provided
via implicit context (a thread-local variable):&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// The 0.1 API for task contexts:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While this implicit context had some ergonomic benefits, it was also a major
stumbling block for learning futures, and meant that you needed to carefully
read documentation to know whether a given function could only be used “in a
task context”.&lt;/p&gt;

&lt;p&gt;In Futures 0.2, we instead deal with task contexts &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/prelude/trait.Future.html&quot;&gt;via an explicit argument&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Futures in 0.2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&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;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While we believe the ergonomic hit here is minor, we were also encouraged by
an &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/pull/2#issuecomment-363923477&quot;&gt;ingenious construction from @seanmonstar&lt;/a&gt; showing how to
recover the ergonomics of the 0.1 API.&lt;/p&gt;

&lt;p&gt;As a happy by-product, the &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/task/struct.LocalKey.html&quot;&gt;APIs for working with &lt;em&gt;task&lt;/em&gt;-local data&lt;/a&gt; are now
substantially more pleasant, giving direct mutable access to the stored data:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// The 0.2 API for working with task-local data&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;n&quot;&gt;LocalKey&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;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_mut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cx&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;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;api-improvement-overhauled-executors&quot;&gt;API improvement: overhauled executors&lt;/h3&gt;

&lt;p&gt;Executors in 0.2 are &lt;em&gt;vastly&lt;/em&gt; simplified compared to 0.1, while supporting a
wider range of functionality.&lt;/p&gt;

&lt;p&gt;First, we codify that futures are &lt;em&gt;always&lt;/em&gt; run in the context of an executor on
which &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/task/struct.Context.html#method.spawn&quot;&gt;they can spawn additional tasks&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// An API on `task::Context`:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&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;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&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;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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Baking in an executor as part of all task contexts makes it much easier to
coordinate execution choices.&lt;/p&gt;

&lt;p&gt;The “out of the box” ways of executing futures change as well:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/executor/struct.ThreadPool.html&quot;&gt;The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThreadPool&lt;/code&gt;&lt;/a&gt; executor replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CpuPool&lt;/code&gt; as a general purpose
task executor, and provides a streamlined set of APIs for getting things
running. It provides “M:N” task scheduling.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/executor/struct.LocalPool.html&quot;&gt;The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalPool&lt;/code&gt;&lt;/a&gt; executor provides single-threaded (“M:1”)
task scheduling, which is appropriate for mostly I/O-bound tasks. Since it is
single threaded, &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/executor/struct.LocalExecutor.html#method.spawn_local&quot;&gt;it supports non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt; tasks&lt;/a&gt;. This executor is
ultimately intended to replace the old built-in executor in Tokio.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wait&lt;/code&gt; methods, which block on futures (and friends), have been replaced
with &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/executor/fn.block_on.html&quot;&gt;a new top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block_on&lt;/code&gt;&lt;/a&gt; function designed to be harder to
misuse.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common theme with the built-in executors is removing footguns from the
previous design, either by detecting problematic situations and panicking, or by
structuring APIs in a more natural and intuitive way.&lt;/p&gt;

&lt;p&gt;Finally, there are a host of simplifications to the way you implement executors.
The numerous traits and types of 0.1 now boil down to just two key
constructs: &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/task/trait.Wake.html&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wake&lt;/code&gt; trait&lt;/a&gt;, which itself has been simplified,
and &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/task/struct.Context.html&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; type&lt;/a&gt;, which is very simple to construct, and is all
you need to execute a task.&lt;/p&gt;

&lt;h3 id=&quot;api-improvement-core-io-interfaces&quot;&gt;API improvement: core I/O interfaces&lt;/h3&gt;

&lt;p&gt;The Futures crate will now ship with an async equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::io&lt;/code&gt;,
namely &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/io/trait.AsyncRead.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncRead&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/io/trait.AsyncWrite.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncWrite&lt;/code&gt;&lt;/a&gt; traits and
numerous conveniences for working with them.&lt;/p&gt;

&lt;p&gt;These traits previously lived in the &lt;a href=&quot;https://docs.rs/tokio-io/0.1.5/tokio_io/&quot;&gt;tokio-io crate&lt;/a&gt;, but they are in
no way specific to Tokio as a backing source of I/O. This new setup provides all
the core I/O interfaces at the futures level, with the intent that libraries can
use them to be event loop agnostic. (Note, however, that codec support will
remain in Tokio).&lt;/p&gt;

&lt;p&gt;The traits are also updated in several ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;They no longer inherit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Read&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write&lt;/code&gt;, eliminating a major source of
confusion; instead, there are specific adapters that allow you to pass async
I/O objects into sync APIs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The vectored I/O operations are now based on the more foundational iovec
library, which allows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncRead&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncWrite&lt;/code&gt; to be object safe, and to
decouple from more opinionated buffering stories. Use of e.g. the bytes crate
can be layered on top.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;api-improvements-top-to-bottom-cleanup&quot;&gt;API improvements: top-to-bottom cleanup&lt;/h3&gt;

&lt;p&gt;In addition to the highlights above, a whole host of APIs received minor tweaks,
including renamings, generalizations, adjustments for consistency, and so
on. With the 0.2 release, we’re clearing out a long backlog of such requests.&lt;/p&gt;

&lt;p&gt;The API documentation has also been completely reworked.&lt;/p&gt;

&lt;h3 id=&quot;supporting-further-design-iteration&quot;&gt;Supporting further design iteration&lt;/h3&gt;

&lt;p&gt;While we’re making a bunch of improvements in this release, there are still some
known issues and places where changes are expected (see below for some more
detail). Our goal this year is to iterate the crate to a 1.0 state, but we
want to minimize ecosystem pain while doing so.&lt;/p&gt;

&lt;p&gt;Starting with 0.2, the main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures&lt;/code&gt; crate is now a &lt;em&gt;facade&lt;/em&gt; that simply
re-exports from a number of separate crates. This allows us to decouple the key
public APIs–&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;, and the task system–from the myriad other APIs
that work with them, versioning them independently. These core APIs are provided
by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt; crate.&lt;/p&gt;

&lt;p&gt;The upshot is that most of the async ecosystem can happily interoperate as long
as they agree on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt; version; the rest of the futures APIs can
usually be used with independent versions without harm. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt;
also contains the most stable of the futures APIs, we expect this to cut down on
ecosystem coordination pain as we continue to iterate on the peripheral APIs.&lt;/p&gt;

&lt;p&gt;To take advantage of this split, &lt;em&gt;libraries&lt;/em&gt; are encouraged to use the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-*&lt;/code&gt; crates directly, rather than the facade.&lt;/p&gt;

&lt;p&gt;Ultimately, when we reach 1.0, the expectation is that &lt;em&gt;all&lt;/em&gt; of these APIs will
be re-incorporated into a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures&lt;/code&gt; crate, and the facade will be no
more.&lt;/p&gt;

&lt;p&gt;More detail about this split is available
in &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/pull/1&quot;&gt;the RFC&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;when-will-it-be-published&quot;&gt;When will it be published?&lt;/h2&gt;

&lt;p&gt;TL;DR: most likely within a couple of weeks.&lt;/p&gt;

&lt;p&gt;While we’ve been discussing and vetting the 0.2 changes publicly for some time,
it’s important to get some real usage prior to publication. We’ve made
substantial progress porting parts of Fuchsia to the new release, and expect to
have a complete port soon. We will also be coordinating with the Tokio team,
which intends to release a 0.2 to integrate with Futures 0.2.&lt;/p&gt;

&lt;p&gt;If you are a Futures user, you are &lt;em&gt;strongly&lt;/em&gt; encouraged the look
at &lt;a href=&quot;http://rust-lang-nursery.github.io/futures-rs/futures/index.html&quot;&gt;the docs&lt;/a&gt; and, if possible, try porting some code. Please open issues
or reach out on #futures if you run into problems!&lt;/p&gt;

&lt;h2 id=&quot;whats-the-road-to-10&quot;&gt;What’s the road to 1.0?&lt;/h2&gt;

&lt;p&gt;Concurrent with the release of Futures 0.2, we plan to release an updated
version of &lt;a href=&quot;https://github.com/alexcrichton/futures-await&quot;&gt;futures-await&lt;/a&gt; that provides async/await notation &lt;em&gt;with full
borrowing support&lt;/em&gt;, due to @withoutboats’s great work in that area.&lt;/p&gt;

&lt;p&gt;Beyond 0.2, there are several areas where further iteration is needed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The initial support for borrowing with async/await will depend on unstable
features, and thus will be provided by an external “shim” so that the core
futures crate can continue to work on stable Rust. Once the ingredients are
stabilized, we will need to update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt; to remove the shim.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Borrowing support will also entail changes to combinators and possibly core
traits (particularly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sink&lt;/code&gt;); we will need to work through the full set of
ramifications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We plan to investigate removing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt; and friends, which could
clear up some longstanding issues with the combinators.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We plan to hone our backpressure story with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sink&lt;/code&gt; and bounded channels.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Changes in these areas will go through the &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/&quot;&gt;RFC process&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that some of these changes affect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures-core&lt;/code&gt;, meaning that there’s
likely to be at least one more disruptive bump before we hit 1.0.&lt;/p&gt;

&lt;p&gt;We are also working on a book, &lt;em&gt;Asynchronous Programming in Rust&lt;/em&gt;, that will
provide comprehensive explanations of the library and how to use it, including
exercises and case studies.&lt;/p&gt;

&lt;h2 id=&quot;how-to-get-involved&quot;&gt;How to get involved&lt;/h2&gt;

&lt;p&gt;The Futures team wants to grow, and as part of 0.2 we’ve been pushing toward
Rust-style governance to make it easier to get involved.&lt;/p&gt;

&lt;p&gt;At the moment, the most valuable help is review of the 0.2 release
candidate. You can report feedback via issues or the #futures IRC channel.&lt;/p&gt;

&lt;p&gt;If you’re interested in any of the topics listed above for post-0.2 iteration, or
otherwise see areas to improve, please reach out on the tracker or channel, or
consider writing an RFC!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Closing out an incredible week in Rust</title>
   <link href="http://aturon.github.io/tech/2018/02/09/amazing-week/"/>
   <updated>2018-02-09T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/02/09/amazing-week</id>
   <content type="html">&lt;p&gt;This week has been so amazing that I just &lt;em&gt;had&lt;/em&gt; to write about it. Here’s a
quick list of &lt;em&gt;some&lt;/em&gt; of what went down in &lt;em&gt;one week&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Breakthrough #1&lt;/strong&gt;: @withoutboats and @eddyb tag-teamed to develop a &lt;em&gt;safe&lt;/em&gt;,
&lt;em&gt;library&lt;/em&gt;-based &lt;a href=&quot;https://boats.gitlab.io/blog/post/2018-02-07-async-iv-an-even-better-proposal/&quot;&gt;foundation for borrowing in async blocks&lt;/a&gt;. It’s suddenly
seeming plausible to ship async/await notation &lt;em&gt;with borrowing&lt;/em&gt; as part of
Rust Epoch 2018.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Breakthrough #2&lt;/strong&gt;: @nikomatsakis had a eureka moment and figured out a path
to make specialization sound, while still supporting its most important use
cases (blog post forthcoming!). Again, this suddenly puts specialization on
the map for Rust Epoch 2018. &lt;strong&gt;Update&lt;/strong&gt;: the post is &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2018/02/09/maximally-minimal-specialization-always-applicable-impls/&quot;&gt;here&lt;/a&gt;!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Breakthrough #3&lt;/strong&gt;: @seanmonstar came up with &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/pull/2#issuecomment-363923477&quot;&gt;a brilliant way to make
“context arguments” more ergonomic&lt;/a&gt;, which lets us make a long-desired
change to the futures crate without regressing ergonomics.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Tokio reform&lt;/strong&gt;: @carllerche shipped the &lt;a href=&quot;https://tokio.rs/blog/2018-02-tokio-reform-shipped/&quot;&gt;newly reformed Tokio crate&lt;/a&gt;, with a
plan for intercepting ongoing work with futures and laying a more
stable foundation for async I/O in 2018.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Futures 0.2&lt;/strong&gt;: @cramertj, @alexcrichton and I have completed and merged &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rfcs/pull/1&quot;&gt;an RFC for
futures 0.2&lt;/a&gt;, and the &lt;a href=&quot;https://github.com/rust-lang-nursery/futures-rs/tree/0.2&quot;&gt;0.2 branch&lt;/a&gt; made a ton of progress.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Domain working groups&lt;/strong&gt;: we now have an all-star lineup for &lt;a href=&quot;https://internals.rust-lang.org/t/announcing-the-2018-domain-working-groups/6737&quot;&gt;leading the 2018 Domain Working Groups&lt;/a&gt;:
    &lt;ul&gt;
      &lt;li&gt;Networking services: @withoutboats and @cramertj&lt;/li&gt;
      &lt;li&gt;WebAssembly: @fitzgen&lt;/li&gt;
      &lt;li&gt;CLI apps: @killercup&lt;/li&gt;
      &lt;li&gt;Embedded: @japaric&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Libs Team restructuring&lt;/strong&gt;: we finalized a revamp of the Libs Team, which will break out:
    &lt;ul&gt;
      &lt;li&gt;a subgroup to manage &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; led by @alexcrichton,&lt;/li&gt;
      &lt;li&gt;a subgroup working on discoverability led by myself, and&lt;/li&gt;
      &lt;li&gt;a subgroup supporting ecosystem work led by @kodraus&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A vision for portability in Rust&lt;/strong&gt;: I finally wrote up &lt;a href=&quot;http://aturon.github.io/tech/2018/02/06/portability-vision/&quot;&gt;the vision we’ve been
working toward&lt;/a&gt; for a uniform way of handling portability concerns in Rust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just the items that loomed large for me personally; one of the great
things about how Rust has grown last year is that it has taken on an increasing
set of leaders and teams doing great work independently. It’s now simply
impossible to drink from the full firehose. But even a sip from the firehose,
like the list above, can blow you away.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>A vision for portability in Rust</title>
   <link href="http://aturon.github.io/tech/2018/02/06/portability-vision/"/>
   <updated>2018-02-06T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2018/02/06/portability-vision</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: This post proposes to deprecate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; facade, instead having a
unified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; that uses target- and capability-based &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt;s to control API
availability. &lt;a href=&quot;https://internals.rust-lang.org/t/a-vision-for-portability-in-rust/6719&quot;&gt;Leave comments on internals!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Portability is extremely important for Rust, in two distinct (and sometimes
competing!) ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Rust should be usable in almost any environment, and ideally much of the
ecosystem would be as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Rust should be low-friction when writing for “mainstream” platforms (32- and
64-bit machines running Windows, Linux, or macOS).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example of the tension between these two goals is handling allocation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Some targets for Rust do not support allocation natively, so Rust must at
least have a “mode” in which no allocation is assumed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For “mainstream” applications and platforms, we want to assume not only that
allocation is available, but that running out of memory is a catastrophic
failure. Those assumptions are reasonable for a huge amount of software, and
making them greatly reduces the friction to writing Rust code.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve been slowly evolving a &lt;em&gt;set&lt;/em&gt; of answers to this kind of question, and part
of the point of this blog post is to step back and try to give a unifying vision
for how to approach portability issues in Rust.&lt;/p&gt;

&lt;p&gt;But first, let’s take stock of where we are today.&lt;/p&gt;

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

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

&lt;p&gt;Rust’s standard library is actually made up of three “rings” of increasing
assumptions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt;: assume “nothing” about the target platform.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alloc&lt;/code&gt;: assume that allocation is available.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;: assume that “mainstream” OS facilities are available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In particular, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; is partly a &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/40&quot;&gt;“facade” crate&lt;/a&gt; that re-exports almost all of
the functionality from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alloc&lt;/code&gt;. This factoring allows crates that
target &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; to be seamlessly used with crates that target &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;, and led to
the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1184&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no_std&lt;/code&gt; flag&lt;/a&gt;. So far, only &lt;a href=&quot;https://github.com/rust-lang/rust/issues/27701&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt;&lt;/a&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; are stable.&lt;/p&gt;

&lt;h4 id=&quot;problems-with-the-facade&quot;&gt;Problems with the facade&lt;/h4&gt;

&lt;p&gt;While the three-layer division may &lt;em&gt;seem&lt;/em&gt; very clean, in practice things turn
out to be far more complicated:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; does not in fact assume “nothing”: some core types like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i128&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AtomicU8&lt;/code&gt; are available within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt;, but not available on all platforms
Rust targets. Thus, on some of these platforms, these definitions are simply
&lt;em&gt;missing&lt;/em&gt; (i.e. have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt; applied).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For non-mainstream OSes, often only a portion of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; functionality is
available. The remaining pieces are either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt;-ed out, return errors, or
panic if you try to use them.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Because the crates are separated, there are some trait coherence issues, which
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; uses special magic to overcome.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Libraries have to specifically opt in to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no_std&lt;/code&gt; and rewrite to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt;
rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;. While it’s relatively rare for a library to just happen to
be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no_std&lt;/code&gt; compatible, it’s still a bit of a papercut.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The root issue here is that the three-layer arrangement is based on a particular
division of environment capabilities, and that reality is not so simple.&lt;/p&gt;

&lt;h3 id=&quot;environment-specific-extensions&quot;&gt;Environment-specific extensions&lt;/h3&gt;

&lt;p&gt;Today we provide access to low-level or OS-specific services via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt;
module. APIs in this module are largely traits that extend the cross-platform
APIs, and in particular can expose their OS-level representation. The fact that
these APIs require explicitly importing from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt; provides a small “speed
bump” for venturing out of guaranteed mainstream platform portability.&lt;/p&gt;

&lt;h4 id=&quot;problems-with-environment-specific-extensions&quot;&gt;Problems with environment-specific extensions&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt; module has submodules that correspond to a hierarchy of OS
types. But it’s not at all clear how to use the module hierarchy to organize
features like &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1543&quot;&gt;fixed-size atomic types&lt;/a&gt;, where the types
available vary in a fine-grained way based on the CPU family; &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1199&quot;&gt;SIMD&lt;/a&gt; is even
worse. And even the OS story is ultimately not such a simple hierarchy.&lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The “speed bump” for using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt; is minimal and easy to miss; it’s just an
import that looks the same as any other.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Platform-specific APIs don’t live in their “natural location”. The majority of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt; works through extension traits to enhance the functionality of
standard primitives, rather than providing inherent methods directly on the
relevant types.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Rather than today’s assortment of approaches to portability, I propose the
following consolidated story:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There is just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;All APIs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; live in their “natural” location.&lt;/li&gt;
  &lt;li&gt;APIs not supported by a target are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt;-ed off for that target.&lt;/li&gt;
  &lt;li&gt;There are capability-based &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt; flags.&lt;/li&gt;
  &lt;li&gt;You can use the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1868&quot;&gt;portability lint&lt;/a&gt; to check for compatibility with arbitrary
platform assumptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, I propose that we move away from the facade, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::os&lt;/code&gt; model, and
runtime failure, and instead embrace target- and capability-based &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt;s as the
&lt;em&gt;sole&lt;/em&gt; way of expressing portability information.&lt;/p&gt;

&lt;p&gt;The portability lint makes it possible to compile and test on one target while
checking that you are not accidentally making assumptions based on that
target. For example, by default Rust code will be checked for “mainstream”
portability, so that even if you’re compiling on Windows, any use of a
Windows-specific API will be linted against. If you want to be compatible with
today’s “no_std” ecosystem, you can tune the knob to check that you are–but you
won’t have to change from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt;. The &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1868&quot;&gt;RFC&lt;/a&gt; has full
details.&lt;/p&gt;

&lt;p&gt;To make this all work, we will need to give careful design to the set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt;
flags and their interrelations.&lt;/p&gt;

&lt;p&gt;And to fully gain from abandoning the facade (i.e., to remove the special magic
used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; today), we would need to use an epoch boundary to fully remove
libcore.&lt;/p&gt;

&lt;p&gt;As part of this effort:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; itself should likely be refactored to make maintaining the external
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt; information as easy as possible, and to create a &lt;a href=&quot;https://internals.rust-lang.org/t/libsystem-or-the-great-libstd-refactor/2765/33&quot;&gt;sharper division&lt;/a&gt;
between public APIs and internal, platform-specific implementation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We would need to reconceptualize “pluggability” into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;. For example, today
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no_std&lt;/code&gt; allows you to define certain primitives, like panic handling, which
are normally defined by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;. We would need a way to instead &lt;em&gt;swap out&lt;/em&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;’s default definition. Some related issues &lt;a href=&quot;https://github.com/rust-lang-nursery/rust-wasm/issues/38&quot;&gt;have come up&lt;/a&gt; in the
wasm world, where ideally we would let you plug in your own JS imports to define
things like printing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;call-to-action&quot;&gt;Call to action&lt;/h2&gt;

&lt;p&gt;The vision above is deliberately sketchy. The fact of the matter is that the
Rust project has never had a group of people tasked with thinking about
portability and platform support from a holistic design perspective–and as we
continue to expand Rust, we really need that.&lt;/p&gt;

&lt;p&gt;In particular, we need help:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implementing the portability lint.&lt;/li&gt;
  &lt;li&gt;Fleshing out a unified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; design.&lt;/li&gt;
  &lt;li&gt;Designing a clean, coherent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg&lt;/code&gt; hierarchy.&lt;/li&gt;
  &lt;li&gt;Refactoring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; to make portability cleaner and easier.&lt;/li&gt;
  &lt;li&gt;Designing a more general “plugability” story.&lt;/li&gt;
  &lt;li&gt;Ensuring that we provide top-notch support for platform capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I propose that the Rust project spin up a dedicated Portability Working Group
devoted to this work. The group will need a strong leader who can take a
holistic, design-focused view of things. If you’re interested in leading or
participating in such a group, please leave a comment on &lt;a href=&quot;https://internals.rust-lang.org/t/a-vision-for-portability-in-rust/6719&quot;&gt;the internals thread&lt;/a&gt;!&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Retooling the Rust Libs Team team for 2018</title>
   <link href="http://aturon.github.io/tech/2018/01/16/libs-mission/"/>
   <updated>2018-01-16T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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;“as a product” means that we need to focus on the &lt;em&gt;end-to-end experience&lt;/em&gt;
people have with the ecosystem. It’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;“the crate ecosystem” means that the Libs Team needs to look far beyond &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;“improve the quality” means that we don’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’s a lofty goal! Let’s take a look at how we’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’s more we could be doing, and that a rebalancing of
priorities is in order–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’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 “monolithic” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; changes. To remove this bottleneck, we are
considering a “working group” 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’s go back to the question of “product quality” for the ecosystem. I’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’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’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–an approach that’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 “networking” 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’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 “distant” 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 “blessing” crates and tools that would then, in some sense, be
“shipped” 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’t fully
panned out.&lt;/p&gt;

&lt;p&gt;I don’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 “long form” material, e.g. by
writing detailed “design evaluation” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’m sure there are other avenues to explore, and I’d love to hear your ideas!
It’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’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’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’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/tech/2018/01/09/rust-2018/"/>
   <updated>2018-01-09T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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’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
“there’s always another train on the way”; there’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 “rally the troops”, 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’s a kind of “&lt;a href=&quot;https://en.wikipedia.org/wiki/Boiling_frog&quot;&gt;frog boil&lt;/a&gt;” 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’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 “product” releases&lt;/strong&gt;. These are sometimes called
“marketing releases”, 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’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’s the marketing aspect, which comes in several
layers. Releasing “Rust 2018” gives us a chance to say to the world that “Rust
has taken a major step since 1.0; it’s time to take another look”. That, of
course, ties directly back to the end-to-end experience; we’ll want to have a
polished web site, installation process, etc. For existing Rust users who are
not deeply involved in Rust’s development, the product release gives a way to
understand Rust’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 “epoch year”, in which we focus on shipping a
quality product, for all of the above reasons. That’s going to require a lot of
discipline, and a steady stream of stabilizations, but I think we’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’m really proud of the work we did in 2017 to grow Rust’s formal teams,
including creating several new subteams and expanding all of the existing
ones. But we’re still suffering from a deficit of technical leadership. That’s
in part because technical leadership is a hard job with mostly intangible
effects; it’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’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’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’s points about impl period
working groups&lt;/a&gt;, which was one such attempt. Splitting up the “tools” team
into “dev tools”, “cargo”, and “infrastructure” 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’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’s adoption approach so far has been relatively “bottom up”: create a
product with some strong potential business value, and focus largely on getting
engineers “on the ground” 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’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’ve commissioned some white papers to do this), being clear
about where Rust makes sense and where it doesn’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’ve talked to production users, the feeling is usually
“we’re too busy writing Rust code and we trust you to get it right”. But the
result is that RFC threads don’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’s global community&lt;/h2&gt;

&lt;p&gt;While we talk about “the Rust community”, 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’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’ve &lt;em&gt;also&lt;/em&gt; heard an increasing plea for more
“intermediate” 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’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’s still a lot more to do in terms of
(1) surfacing crates and tools that “every working Rustacean should know” 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’s
vital that we don’t descend into tribalism or us-versus-them thinking, but
instead to respect each other’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/tech/2017/08/02/modules-part-2/"/>
   <updated>2017-08-02T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2017/08/02/modules-part-2</id>
   <content type="html">&lt;p&gt;It’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’s module system. Unsurprisingly,
the strawman proposal in that post garnered a lot of commentary–174 comments in
one week!–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’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’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’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 “directories-as-modules” proposal.&lt;/li&gt;
  &lt;li&gt;I’ll call the strawman in this post the “use-universally” 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use&lt;/code&gt; (aka the “facade pattern”) when
setting things up today, and I think the proposal clearly streamlines that
story. (There are also variants like “inline” aka “anonymous” modules that bring
in just part of the proposal).&lt;/p&gt;

&lt;p&gt;On the other hand, the proposal didn’t do much to help with issues around “path
confusion”:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The fact that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “spike” 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’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’s often an expectation that adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rs&lt;/code&gt;
file to the source tree, or a dependency to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;, should be all that’s
needed to set up the naming hierarchy. From that perspective, you’d expect to be
able to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt;) in the
right place first. It requires a shift in mental model. And the fact that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;
is much more common than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’m labeling this proposal as “use-universally” is that it
sets up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s a quick summary of the proposal:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Start with today’s module system.&lt;/li&gt;
  &lt;li&gt;Deprecate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; for greater clarity around paths, which I’ll explain below.&lt;/li&gt;
  &lt;li&gt;Modules are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(crate)&lt;/code&gt; unless they are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use&lt;/code&gt;d (so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub mod foo;&lt;/code&gt; becomes
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use foo;&lt;/code&gt; – note that this is using &lt;em&gt;relative&lt;/em&gt; paths, as I’ll explain next).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The meat is in making two adjustments for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; declarations:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Introduce a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;self::&lt;/code&gt;).
    &lt;ul&gt;
      &lt;li&gt;A leading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’s trivial to write a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustfix&lt;/code&gt; tool that mechanically switches today’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; declarations to this new setup, and likewise deals with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;We could introduce and stabilize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from/use&lt;/code&gt; syntax, then deprecate use of
absolute paths in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; (without a leading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&lt;/code&gt;), and employ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustfix&lt;/code&gt; at that
point – 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’t change.&lt;/p&gt;

&lt;p&gt;Here’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; excerpt:&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[dependencies]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;petgraph&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.4.5&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A directory structure excerpt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src/
  lib.rs
  coherence/
    mod.rs
    solve.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;code-in-todays-module-system&quot;&gt;Code in today’s module system&lt;/h4&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;petgraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;prelude&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&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;n&quot;&gt;ItemId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

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

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Solver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;errors&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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ir&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;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&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;c1&quot;&gt;// note relative path; this makes `coherence` pub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;petgraph&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;prelude&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&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;n&quot;&gt;ItemId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&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;n&quot;&gt;Solver&lt;/span&gt;&lt;span class=&quot;p&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;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;errors&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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ir&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;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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’re tied
together:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Introducing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “mounted” in the
current crate’s module hierarchy, usually at root. (In this analogy, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;
        &lt;p&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’s in scope). In any case, making paths
everywhere relative to the current module reduces confusion.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;We want to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use&lt;/code&gt; to export submodules publicly, but with absolute
paths this would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use self::my_submodule&lt;/code&gt; which is awkward and
confusing; people are almost certain to forget &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; much of the time.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Note that there are often arguments that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;-like mechanisms should employ
absolute paths by default because that’s the common case. However, for Rust
I think that’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;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s exports are spread over
multiple files. At the same time, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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—though this does mean that
marking an item &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt; in a module means it, in reality, has &lt;em&gt;at least&lt;/em&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(crate)&lt;/code&gt; visibility (and perhaps more, if it’s exported in a public
module). This is arguably a good thing; today, the fact that you can write
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt; on an item means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt;&lt;/strong&gt;. This was already explained
above. There’s already been some discussion around the downsides (and ways to
mitigate them), so I’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’ll take a brief look at each, and the tradeoffs as
I see them.&lt;/p&gt;

&lt;h3 id=&quot;knob-fromuse-ordering&quot;&gt;Knob: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; ordering&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; syntax follows precedent from Python, but we could instead use the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; ordering from JS.&lt;/p&gt;

&lt;p&gt;Possible benefits of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “jagged edges” of imported names.&lt;/li&gt;
  &lt;li&gt;Arguably more “natural” reading (as a sentence).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Possible benefits of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s interesting to consider the choices when it comes to multi-line imports:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&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;p&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;nn&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;n&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&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;p&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;nn&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;n&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use foo&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub mod foo;&lt;/code&gt; to make a child
module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; public.&lt;/p&gt;

&lt;p&gt;The main advantage would be that it’s more plausible to continue to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;
take absolute paths, which reduces breakage. On the other hand, it seems to
double down on some aspects of “path confusion”, and doesn’t achieve the
unification around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;, but ones
implied from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; would go through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’d most likely wind up with
one of the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use self::my_submodule;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; blocks, in
which case they are not naturally referenced elsewhere. You’d have to explicitly
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rs&lt;/code&gt; files).&lt;/p&gt;

&lt;h3 id=&quot;knob-useing-submodules&quot;&gt;Knob: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt; them before referring to them. I can’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;self::&lt;/code&gt; that’s currently common when facading), it’s
compatible with future extensions that do more.&lt;/p&gt;

&lt;p&gt;For example, we could draw from earlier proposals involving “anonymous modules”
(aka “inline modules”) – say, files beginning with a leading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; – 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’m looking
forward to your feedback!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Revisiting Rust’s modules</title>
   <link href="http://aturon.github.io/tech/2017/07/26/revisiting-rusts-modules/"/>
   <updated>2017-07-26T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod foo;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub use&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.rs&lt;/code&gt; versus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo/mod.rs&lt;/code&gt; distinction, together with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;, you also need to add an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt; declaration.&lt;/li&gt;
      &lt;li&gt;When you add a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rs&lt;/code&gt; file, you also need to write a corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt; item to it, you also have to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a concrete example from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&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;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;fn&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;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;self&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;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;k&quot;&gt;Self&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;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;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;k&quot;&gt;self&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;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&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;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;c1&quot;&gt;// etc&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each of these concrete types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;future&lt;/code&gt; module has code like this:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mod&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;k&quot;&gt;mod&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;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flatten_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&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;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;into_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&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;k&quot;&gt;mod&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;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;or_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&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;k&quot;&gt;mod&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;k&quot;&gt;mod&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;k&quot;&gt;mod&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;AndThen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;FlattenStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Fuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;IntoStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;Join4&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;MapErr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;FromErr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;OrElse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Select2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures&lt;/code&gt; codebase, you have to read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;future&lt;/code&gt; module to understand how its submodules are being used, due to these re-exports. For the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(crate)&lt;/code&gt; would better convey intent, but today’s module system makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;futures&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regex&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rayon&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flate2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clap&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serde&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chalk&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;cfg(unix)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; gives you a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(crate)&lt;/code&gt; module.&lt;/li&gt;
      &lt;li&gt;All other directories give you &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt; modules.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;/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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&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;cm&quot;&gt;/* scoped contents of `these.rs`, `names.rs`, `do_not_matter.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;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;infer&lt;/span&gt; &lt;span class=&quot;p&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&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;cm&quot;&gt;/* scoped contents of `mod.rs`, `impls.rs` and `tests.rs` */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* scoped contents of `baz.rs` */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(self)&lt;/code&gt; means private to the current module. To illustrate, imagine we have the following for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instantiate.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Instantiator&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;p&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;p&quot;&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&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;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;n&quot;&gt;InfTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&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;p&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unify.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Unifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;...&lt;/span&gt; &lt;span class=&quot;p&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;p&quot;&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;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;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UnificationResult&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;p&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;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&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;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;n&quot;&gt;InfTable&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;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;n&quot;&gt;b&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UnificationResult&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* may invoke `instantiate` */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src/
  future/
    mod.rs
    and_then.rs
    flatten.rs
    fuse.rs
    // etc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod.rs&lt;/code&gt;. That is, none of the following boilerplate is needed:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;and_then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&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;k&quot;&gt;mod&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;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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;AndThen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Fuse&lt;/span&gt;&lt;span class=&quot;p&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;/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;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src/
  foo/
    unix.rs
    windows.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unix.rs&lt;/code&gt; starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#![cfg(unix)]&lt;/code&gt; and similarly for windows. Both files are considered part of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(use)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;/div&gt;

&lt;p&gt;This directory structure is excepted from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clap&lt;/code&gt;, which currently has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;_app/mod.rs&lt;/code&gt; you might have a definition like:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&apos;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;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The reader can immediately see something interesting happening: this item is defined within an “internal” (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub(crate)&lt;/code&gt;) module, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib.rs&lt;/code&gt;, we might have:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;use self::item;&lt;/code&gt; However, having to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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/tech/2017/07/08/lifetime-dispatch/"/>
   <updated>2017-07-08T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2017/07/08/lifetime-dispatch</id>
   <content type="html">&lt;p&gt;Rust’s &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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 “A modest proposal” 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’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’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Bad1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&apos;t know if T: &apos;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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What does this program print? Since the string literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;test&quot;&lt;/code&gt; has type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;static str&lt;/code&gt;, you might expect the second, specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; to be used (and
hence to get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;specialized&lt;/code&gt; as the output). But, as explained above, from the
perspective of trans this type will look like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;erased str&lt;/code&gt;, making it
impossible to know whether the more specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; can safely be used.&lt;/p&gt;

&lt;p&gt;Here’s another, less obvious example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;p&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;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;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;k&quot;&gt;for&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;c1&quot;&gt;// Specialization cannot work: trans doesn&apos;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;nv&quot;&gt;&apos;a&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;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;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;nv&quot;&gt;&apos;a&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; is requiring that two lifetimes are the same, and once
more for trans we can’t tell whether the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Good&lt;/span&gt; &lt;span class=&quot;p&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;n&quot;&gt;Good&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Good&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In addition, it’s in principle okay for lifetime constraints to show up as long
as they don’t influence specialization:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;c1&quot;&gt;// Potentially fine: *all* impls impose the &apos;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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;/code&gt;&lt;/pre&gt;&lt;/div&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’s not, at least given the original design of specialization:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&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;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&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;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Uh oh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&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;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem here: specialization as originally designed will allow the
typechecker to conclude that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T::Assoc&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; if it knows that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;static str&lt;/code&gt;. That’s because the impl for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;static str&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; use the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;erased str&lt;/code&gt; instead, and so cannot safely use the
specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;. That means that trans will make the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt; return
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;, but the rest of the code assumed that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; was returned.&lt;/p&gt;

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

&lt;p&gt;(Spoiler alert: the “as originally designed” bit above is a give-away of where
we’re ultimately going to end up…)&lt;/p&gt;

&lt;h2 id=&quot;some-solutions-that-dont-work&quot;&gt;Some “solutions” that don’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’t work out.&lt;/p&gt;

&lt;h3 id=&quot;cant-we-just-rule-out-bad-specializations&quot;&gt;Can’t we just rule out “bad” specializations?&lt;/h3&gt;

&lt;p&gt;It’s very tempting to blame the specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;s for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bad1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “hide” lifetime
constraints within other trait impls that don’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Marker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Default impl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;nn&quot;&gt;marker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Marker impl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;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;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;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;marker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Marker&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;p&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;k&quot;&gt;crate&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;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// prints: Marker impl&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;0u32&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;c1&quot;&gt;// prints: ???&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the relevant specialization depends on the &apos;static lifetime&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;s&quot;&gt;&quot;Activate the marker!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;marker&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client&lt;/code&gt; is accepted today. It’s only when these
crates are plugged together that a problem arises – you end up with a
specialization based on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; lifetime. And the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client&lt;/code&gt; crate may not
even be aware of the existence of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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: “lifetime-dependent” vs “specializable”?&lt;/h3&gt;

&lt;p&gt;Thinking more about the previous example, you might imagine the problem is that
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Marker&lt;/code&gt; trait ends up being used in two incompatible ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s used in a specialization, the second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;It’s used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;s that constrain lifetimes (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[lifetime_sensitive]&lt;/code&gt;, which allows for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Marker&lt;/code&gt; trait could say, in advance, whether the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt;
impls or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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
“constraining lifetimes” is a surprisingly easy thing to do. To wit:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Sneaky&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Sneaky&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// what does this print?&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we have a specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; that doesn’t mention any lifetimes or any
other traits; it just talks about the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(T, T)&lt;/code&gt;. The problem is that it’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function, we’ll be invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sneaky&lt;/code&gt;
on the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;amp;&apos;erased str, &amp;amp;&apos;erased str)&lt;/code&gt;, and we can’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’s always the worry that we’ve missed other sneaky
ways to constrain lifetimes…&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’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’d have to be very smart about
coalescing code with different lifetimes but identical behavior. There’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Arbitrary str: {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Print&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&apos;static str: {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;nf&quot;&gt;.print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello, world!&quot;&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;nf&quot;&gt;.print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&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;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Does this program print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static str: hello, world!&lt;/code&gt; twice?&lt;/p&gt;

&lt;p&gt;No! Because the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;assoc_specialization&lt;/code&gt;, which is needed
whenever you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default type&lt;/code&gt; in an impl. We then focus on stabilizing just
the core &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t always under your
crate’s control.)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s revisit some of the earlier examples in this light:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Specialization cannot work: trans doesn&apos;t know if T: &apos;static:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Bad1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bad1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&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;s&quot;&gt;&quot;test&quot;&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;MustBeStatic&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, both impls impose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; constraints, so the second impl doesn’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;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’re covering, though, it’s possible to do better (we’ll see
more on that later). That means we might want to “improve” 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—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’ve done, and what we’ve learned.&lt;/p&gt;

&lt;p&gt;Here’s an interesting example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Special&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Special&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;nf&quot;&gt;.clone&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;nf&quot;&gt;.special&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using the strategy outlined above, trans will go from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;amp;&apos;erased str, &amp;amp;&apos;erased
str)&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;amp;&apos;a str, &amp;amp;&apos;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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;special&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pair&lt;/code&gt;, and you could imagine communicating that information down
to trans.&lt;/p&gt;

&lt;p&gt;What’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’t tell that two appearances of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;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 “indirection” around trait dispatch:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Special&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;generic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Special&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;specialized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&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;nf&quot;&gt;.clone&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;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now at type checking time, the actual use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;special&lt;/code&gt; occurs in a context where
we &lt;em&gt;don’t&lt;/em&gt; know that we’ll always be using the more specialized version.&lt;/p&gt;

&lt;p&gt;Why harp on this point? Well, for one, it’s the main issue in allowing for sound
specialization of associated types. We can see this in a variant of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bomb&lt;/code&gt;
example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&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;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&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;p&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;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&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;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;p&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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&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;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&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;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Uh oh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&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;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, again, type check knows that the relevant uses of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bomb&lt;/code&gt; all involve types
of the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&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;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&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;p&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;n&quot;&gt;Bomb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&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;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;indirect&lt;/span&gt;&lt;span class=&quot;p&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;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;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&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;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Uh oh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&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;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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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—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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt; that the specialized impl of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bomb&lt;/code&gt; can be used to be used when monomorphizing and generating code for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indirect&lt;/code&gt;. Niko tells me that, in ancient times, the compiler used to do
something much like this—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’s relatively easy to
argue for soundness, seems like the right step to take (@arielb1, here’s where
you prove me wrong).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Negative reasoning in Chalk</title>
   <link href="http://aturon.github.io/tech/2017/04/24/negative-chalk/"/>
   <updated>2017-04-24T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2017/04/24/negative-chalk</id>
   <content type="html">&lt;p&gt;I’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’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’s trait system explicitly in terms of logic programming, by
“lowering” 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’t finished, and it’s currently missing some of the core
pieces of the real trait system.&lt;/p&gt;

&lt;p&gt;I’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 “mode switches” we employ in today’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’s precedence rules that e.g. give more weight to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;where&lt;/code&gt;
clauses than to blanket &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’ve
often been quite fearful about negative reasoning in rustc, since it’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;not P&lt;/code&gt; means you tried but failed to prove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “closed world assumption”: the facts that
follow from the program’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’ll want to have read at least the first
of Niko’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’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 “mode switches”:&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’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’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&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;p&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;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Do these two impls overlap? It depends on whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(): Error&lt;/code&gt; – or more
precisely, whether we can definitively conclude &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { (): Error }&lt;/code&gt;. If we are
allowed to conclude that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { (): Error }&lt;/code&gt;, then we can conclude that the two
impls don’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;
does not implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; trait (both are defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;), and hence the
two impls here do not overlap. However, if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; was ever changed so that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;
implemented &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; adding such an impl would irrevocably break this code! And
we’d like for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;fundamental&lt;/code&gt;, to promise that certain impls won’t be provided in the future,
but we’ll ignore that for now.) By limiting negative reasoning in this way, we
can “future proof” 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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&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;p&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;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyStruct&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;p&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;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyStruct&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we allow the trait system to conclude that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { MyStruct: Error }&lt;/code&gt;,
because whether or not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyStruct: Error&lt;/code&gt; is &lt;strong&gt;entirely under this crate’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’s a more subtle case:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Aux&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;p&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;p&quot;&gt;:&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;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&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;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;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&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;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;p&quot;&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;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;n&quot;&gt;Aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;p&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; you could mention in this crate such that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T: Aux&lt;/code&gt;, and hence no type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;
such that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; and implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Aux&lt;/code&gt; for it, and then suddenly
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyStruct&amp;lt;Foo&amp;gt;&lt;/code&gt; would have &lt;em&gt;two&lt;/em&gt; applicable impls of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&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;p&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&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;nn&quot;&gt;crate_a&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&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;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;’s implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn main&lt;/code&gt; even
in crate A, where all of the relevant impls are under the crate’s direct
control. I consider this a bug.&lt;/p&gt;

&lt;p&gt;In any case, this negative reasoning restriction is called “user-facing
projection mode” (as opposed to “trans-facing”, which we’ll see below). It’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;p&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;k&quot;&gt;-&amp;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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&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;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;p&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;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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;p&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;p&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;k&quot;&gt;-&amp;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;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code compiles and prints “Local”. That’s because, from what this crate can
see, &lt;em&gt;no&lt;/em&gt; type implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar&amp;lt;T&amp;gt;&lt;/code&gt;, so only the second impl of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; is viable.
That conclusion is then fed into type inference, which decides to interpret
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;()&amp;gt;::make()&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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–in part because all of the
questions will involve fully monomorphized types. In particular, we need to
allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s
“negation as failure”/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’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’s
red. That’s the story for “facts”. But the basic rules of logic apply no matter
what world you’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 “in every &lt;em&gt;future&lt;/em&gt; world” or
“in &lt;em&gt;some possible&lt;/em&gt; world” and so on.&lt;/p&gt;

&lt;p&gt;There’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 “possible world” for us will be a full crate graph, with a
particular crate being considered “the current crate” (the one actively being
compiled). In the simplest case, there’s just one crate, like in the following
two examples:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;MyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyTrait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Both crates define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyType&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyTrait&lt;/code&gt;, but in the first one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyType:
MyTrait&lt;/code&gt;, while in the second one, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { MyType: MyTrait }&lt;/code&gt;. The facts on the
ground depend on the crate you’re compiling. And when you’re asking Chalk a
question, that question is normally grounded in the particular crate graph
you’ve lowered to Chalk’s logic. In other words, statements made &lt;em&gt;directly about
the current world&lt;/em&gt; are interpreted in, well, a “closed world” way: we know
precisely what the world is, and can give firm answers on that basis. That’s the
appropriate interpretation for trans, as we saw above.&lt;/p&gt;

&lt;p&gt;Second–and this is really the key idea–&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’re currently in&lt;/strong&gt;. This
is how we capture the idea of “future proofed” 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’s see an example. Suppose we have a two crate dependency graph:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s a compatible world, one that extends crate A in a minor-bump kind of way:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, here’s an interesting thing: in the world 1, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateAType: Foo
}&lt;/code&gt;. But in this new, compatible world 2, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { Foo: Bar }&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo: Bar&lt;/code&gt;, but not the other way around.&lt;/p&gt;

&lt;p&gt;Here’s a world that is incompatible with the world 1:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt; &lt;span class=&quot;p&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;/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 “current crate”, is different in this
world, and that makes it incompatible with world 1. This is how we get a
distinction for the “local” crate, which we control and therefore don’t need to
future-proof against. So if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateBType: Foo }&lt;/code&gt; and crate B is the current
crate, we know that in any compatible world, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateBType: Foo }&lt;/code&gt; will
still be true.&lt;/p&gt;

&lt;p&gt;Now let’s talk about the other kind of change allowed to the world:
arbitrary changes to downstream crates. In world 1, we didn’t have any crates
downstream from crate B. Here’s a world that does:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateCType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateCType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;Finally, let’s look at one more world, this time involving downstream crates:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_b&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt; &lt;span class=&quot;p&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;/div&gt;

&lt;p&gt;This world is not just incompatible with world 1–it’s not even a possible
world! That’s because crate C violates the orphan rule by providing an impl for
a type and trait it does not define (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CrateBType&lt;/code&gt;). In other words,
when we consider “all compatible worlds”, we take into account the orphan rules
when doing so. And that’s why, starting from world 1, we know that in all
compatible worlds, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateBType: Foo }&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-compat-modality&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “surface” that meaning through a modality that we can use
when making statements or asking questions in Chalk. We’ll do this via the
&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality&lt;/em&gt;. (For modal logic aficionados, this is basically the “box”
modality, where the reachable worlds are the “compatible” ones, described
below.)&lt;/p&gt;

&lt;p&gt;The basic idea is that if we pose a query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Q&lt;/code&gt;, that’s understood in terms of the
current world, but if we ask &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { Q }&lt;/code&gt;, we’re asking if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s we’ll be able to deduce&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateAType: Foo }&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { CrateBType: Foo }&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not { exists&amp;lt;T&amp;gt; { T: Foo } }&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { not { CrateBType: Foo } }&lt;/code&gt; – in every compatible world, we &lt;em&gt;still&lt;/em&gt; know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CrateBType&lt;/code&gt; does not implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { not { CrateAType: Foo } }&lt;/code&gt;, because of examples like world 2.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { CrateAType: Foo }&lt;/code&gt;, because of world 1 itself.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Q&lt;/code&gt;, we might not be able to show &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { Q }&lt;/code&gt;
&lt;em&gt;or&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { not { Q } }&lt;/code&gt;, because some compatible worlds satisfy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Q&lt;/code&gt;, and
some don’t. So, within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality, you don’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’s more to say about this modality and how it’s implemented, but we can
already put some cards on the table: when we’re type or coherence checking, the
queries we pose to Chalk will be placed within a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality, which
essentially “future proofs” their conclusions. For trans, we’ll pose queries
directly about the current world.&lt;/p&gt;

&lt;p&gt;In other words, having the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality means we can decide whether to make
a “closed world assumption” or not, depending on what we’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;Display&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you ask &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exists&amp;lt;T&amp;gt; { T: Foo }&lt;/code&gt; in a traditional Prolog engine, you’ll get
something like “Yes, T = u8”; if you ask again, you’ll get “Yes, T = bool”, and
if you ask a final time, you’ll get “No”.&lt;/p&gt;

&lt;p&gt;That’s not quite what we want for Rust. There, “existential” questions come up
primarily when we’re in the middle of type inference and we don’t know what a
particular type is yet. Think about a program using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; trait like so:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When we go to type check this function, we don’t immediately know what the type
returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo::new()&lt;/code&gt; is going to be, or which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; to use. While it’s true
that there &lt;em&gt;do exist&lt;/em&gt; types we could use, we don’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&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;k&quot;&gt;trait&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&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;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&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;nf&quot;&gt;.convert&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&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’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’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’re type checking
a function body, we don’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When we are typechecking the first line, we know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opt&lt;/code&gt; will have type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&amp;lt;?T&amp;gt;&lt;/code&gt;, but we don’t know what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T&lt;/code&gt; is; it’s an inference variable. Later
on in checking, as we encounter further constraints, we’ll learn that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T&lt;/code&gt; must
be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “fallback” if type
checking otherwise can’t make any progress.&lt;/p&gt;

&lt;p&gt;Let’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;where&lt;/code&gt; clause precedence&lt;/h3&gt;

&lt;p&gt;In the current trait system, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;p&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;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;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&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;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&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;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&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;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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&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;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bool&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;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;as&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;p&quot;&gt;::&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;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&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;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The program prints &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;. What’s happening here is that the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;
within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;println!&lt;/code&gt; does not provide enough information by itself to know whether
we want the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&amp;lt;bool&amp;gt;&lt;/code&gt; impl or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&amp;lt;()&amp;gt;&lt;/code&gt; impl, both of which apply. In
other words, there’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’t initially clear how this would carry over to Chalk, where we’re trying
to take a “pure logic” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt; if it gets stuck, but
we’ve made clear that this is a sort of “extra-logical” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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’ve only talked about a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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
“Yes, these could potentially overlap”, 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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;p&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;k&quot;&gt;-&amp;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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&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;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt;&lt;span class=&quot;p&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;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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;p&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;p&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;k&quot;&gt;-&amp;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;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Local&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key point was: can you deduce that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; could possibly apply?&lt;/p&gt;

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

&lt;ul&gt;
  &lt;li&gt;The type checker asks: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { (): Bar&amp;lt;?T&amp;gt; }&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;We return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt;, since we’re within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; and there are indeed some
compatible worlds for which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(): Bar&amp;lt;?T&amp;gt;&lt;/code&gt; for some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T&lt;/code&gt;; but we have no
idea what that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T&lt;/code&gt; should be.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;We check the second impl, and get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Yes&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T = Local&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Since there were multiple possibilities, we don’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;?T&lt;/code&gt; should be unified with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality, and get back a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt; answer with the
suggestion we wanted.&lt;/p&gt;

&lt;p&gt;It’s quite nice that all of the static checking takes place under the “future
proofing” of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;not&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; in Chalk&lt;/h2&gt;

&lt;p&gt;Before we close out this post, it’s worth being a bit more concrete about how
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Yes&lt;/code&gt;, return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;No&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;If we got &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;No&lt;/code&gt;,
        &lt;ul&gt;
          &lt;li&gt;If there are no existential variables within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Q&lt;/code&gt;, return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Yes&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;Otherwise, return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt;, with no type suggestions&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;If we got &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt;, return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t get information about existential
variables, which is the same in traditional Prolog.&lt;/p&gt;

&lt;h3 id=&quot;the-compat-modality-1&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; modality&lt;/h3&gt;

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

&lt;p&gt;We certainly can’t literally construct every such world, as there are an
infinite number of them. But fortunately, we don’t have to. The role of the
world in Chalk, as I said above, is to provide a core source of facts. To model
“some arbitrary compatible world”, we just need to capture the various facts
that might be true in such a world. This can be done in a “lazy” kind of way: in
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s a fact that &lt;em&gt;could&lt;/em&gt; be made
true in some compatible world, and if so yield &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt; (with no suggested types).&lt;/p&gt;

&lt;p&gt;Let’s look at this concretely, revisiting world 1:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateAType&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;crate&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crate_a&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrateBType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we ask &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CrateAType: Foo&lt;/code&gt;, we’ll get No. But if we ask &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { CrateAType:
Foo }&lt;/code&gt;, then Chalk should switch into “compatible world” mode, so that when it’s
consulting the world whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat { not { CrateBType: Foo } }&lt;/code&gt;
returns Yes. (Other than turning on “compatible world” mode, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s two different “global switches”. Moreover, we’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt;, we only need to handle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type:
Trait&lt;/code&gt; kinds of facts; the “applicative fallback” 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 “Maybe” 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’s next&lt;/h2&gt;

&lt;p&gt;Putting together everything proposed in this post, we’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 “modes” in today’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “lifetime
dispatch”, which render rustc’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 “on paper” design. I’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/tech/2017/02/06/specialization-and-coherence/"/>
   <updated>2017-02-06T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2017/02/06/specialization-and-coherence</id>
   <content type="html">&lt;p&gt;Specialization has been available in nightly Rust for over a year, and we’ve
recently been thinking about the steps needed to stabilize it.&lt;/p&gt;

&lt;p&gt;There are a couple of implementation issues that are currently blocked on an
&lt;a href=&quot;https://github.com/rust-lang/rust-roadmap/issues/8&quot;&gt;overhaul of the trait system&lt;/a&gt;
which should be coming in the next couple of months.&lt;/p&gt;

&lt;p&gt;What I want to talk about, though, is some deeper design questions that need to
be resolved prior to stabilization, ones involving potential changes to the core
specialization rules. This is a story that begins with a bold hope, runs
headlong into a tragic discovery, and ultimately ends up close to where it
started.&lt;/p&gt;

&lt;h2 id=&quot;a-new-hope&quot;&gt;A New Hope&lt;/h2&gt;

&lt;p&gt;A rite of passage for learning Rust’s trait system is first encountering a
&lt;em&gt;coherence error&lt;/em&gt;. Coherence is a vital but frustrating property; it
guarantees that there is always a single, unambiguous impl of a trait that is
used for any given type.&lt;/p&gt;

&lt;p&gt;It’s not too hard to see why coherence is vital. Imagine working with a
&lt;code&gt;HashMap&lt;/code&gt; in which multiple implementations of &lt;code&gt;Hash&lt;/code&gt; applied to the key
type. If different pieces of code ended up using different impls, map operations
would return totally bogus results, and it would be very difficult to track down
why.&lt;/p&gt;

&lt;p&gt;What makes coherence frustrating is that, to enforce it, we must limit the kinds
of impls you can write in different crates. We do this through a pair of rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The orphan rule&lt;/strong&gt;, which *very roughly* says that you can write an impl only
if either your crate defined the trait or defined one of the types the impl is
for.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The overlap rule&lt;/strong&gt;, which says that a given trait cannot have two impls that
both apply to a single type (which would introduce ambiguity about which impl
to use), unless one is a specialization of the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These rules work closely together; in particular, the orphan rule ensures that
sibling crates can’t accidentally define overlapping impls for a parent trait,
since their impls must each involve crate-local types.&lt;/p&gt;

&lt;p&gt;Prior to Rust 1.0, we iterated quite a bit on these rules, and arrived at
the current design in the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1023&quot;&gt;Rebalancing coherence RFC&lt;/a&gt;. That RFC was predicated
on a core assumption:&lt;/p&gt;

&lt;blockquote&gt;
The problem is that due to coherence, the ability to define impls is a
zero-sum game: every impl that is legal to add in a child crate is also an
impl that a parent crate cannot add without fear of breaking downstream
crates.
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;However, with specialization, it seems this assumption may not longer hold!&lt;/strong&gt;
The point of specialization is to allow for impls to overlap, and then to select
the “most specific” impl. That means, in particular, that it’s feasible for a
parent and child crate to safely define overlapping impls. Niko wrote a
&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/10/24/supporting-blanket-impls-in-specialization/&quot;&gt;blog post&lt;/a&gt;
proposing to leverage specialization in just this way.&lt;/p&gt;

&lt;h3 id=&quot;the-fundamental-attribute&quot;&gt;The &lt;code&gt;fundamental&lt;/code&gt; attribute&lt;/h3&gt;

&lt;p&gt;The existing orphan rule is based on an idea of “fundamental” types. It’s
easiest to understand how it works through 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 class=&quot;c-Doc&quot;&gt;//// Parent crate ////&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c-Doc&quot;&gt;//// Child crate ////&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChildType&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;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This example is permitted today, and works fine as written. However, it means
that adding the following blanket impl to the parent crate is a &lt;em&gt;breaking
change&lt;/em&gt; (assuming that the new impl is not specializable):&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 class=&quot;c1&quot;&gt;// Add to parent 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;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Box&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;c1&quot;&gt;// note: not specializable, since we didn&amp;#39;t write `default`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This change would introduce an overlap with the child crate’s impl, which
prevents it from compiling.&lt;/p&gt;

&lt;p&gt;To avoid &lt;em&gt;all&lt;/em&gt; such new parent crate impls being breaking changes, the
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1023&quot;&gt;Rebalancing coherence RFC&lt;/a&gt; introduced a restriction on child crates: roughly
speaking, their impls of parent traits much either directly reference a type
defined in the child crate, or reference it within a “fundamental” type
constructor (&lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;&amp;amp;mut&lt;/code&gt;, &lt;code&gt;Box&lt;/code&gt;). In other words:&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 class=&quot;c1&quot;&gt;// These child crate impls are allowed:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChildType&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;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&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;nl&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ... but these impls are NOT allowed:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&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;ChildType&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;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is to strike a balance between the impls that child crates can have,
and the ones that parent crates can add over time. If a parent crate adds a
blanket impl involving a fundamental type constructor, that’s a breaking change
(since it could overlap with a child crate). But if it adds one for
e.g. &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, that’s fine, because no child crate could have an impl involving
that type.&lt;/p&gt;

&lt;p&gt;This “fundamental” restriction is an arbitrary line drawn as part of the
“zero-sum game” of writing non-overlapping impls. It’s applied using an unstable
attribute, &lt;code&gt;#[fundamental]&lt;/code&gt;, which is difficult to understand and has had no
clear path toward stabilization.&lt;/p&gt;

&lt;h3 id=&quot;a-positive-sum-game&quot;&gt;A positive-sum game?&lt;/h3&gt;

&lt;p&gt;But wait. When we introduced specialization, we relaxed the overlap rule to
allow for overlap, &lt;em&gt;as long as one impl specialized the other&lt;/em&gt;. Since the orphan
rule is ultimately about preventing overlap from arising between multiple
crates, maybe there’s a way to leverage specialization there as well?&lt;/p&gt;

&lt;p&gt;If we revisit the above example, but make the new parent crate impl
specializable (by using &lt;code&gt;default&lt;/code&gt;), &lt;strong&gt;it no longer breaks the child crate&lt;/strong&gt;. In
other words, the following impls can all safely coexist:&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 class=&quot;c-Doc&quot;&gt;//// Parent crate ////&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&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;p&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;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Box&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;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c-Doc&quot;&gt;//// Child crate ////&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChildType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Now specializes the blanket impl from the parent crate&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParentTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChildType&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;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Is this always the case? In other words, if you add a new impl in the parent
crate and mark it specializable, are you guaranteed not to break any child
crates? That would allow us to get rid of &lt;code&gt;fundamental&lt;/code&gt;, allowing both parent
and client crates to add more kinds of impls than they can today, without
breakage!&lt;/p&gt;

&lt;p&gt;To make this idea work, you’d need to expand the specialization rules a bit, as
Niko explains in
&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/10/24/supporting-blanket-impls-in-specialization/&quot;&gt;his post&lt;/a&gt;. But
those details won’t be too relevant to the core point of this post.&lt;/p&gt;

&lt;h2 id=&quot;the-trait-system-strikes-back&quot;&gt;The Trait System Strikes Back&lt;/h2&gt;

&lt;p&gt;Half way toward writing up an RFC with the above ideas, trying to prove to
myself that they worked, I started to get worried. And then I started trying to
prove that they didn’t work. And it turns out they don’t.&lt;/p&gt;

&lt;p&gt;The crux of the problem is that the trait system is just too powerful; as we’ve
learned over and over again, the trait system can be used to draw sneaky
connections that are hard to defend against. Let me show you what I mean.&lt;/p&gt;

&lt;p&gt;Imagine we have three crates, arranged in the following 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 class=&quot;c-Doc&quot;&gt;//// Crate A ////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&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;c1&quot;&gt;// Line we want to add:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// impl&amp;lt;T&amp;gt; A for T {}&lt;/span&gt;


&lt;span class=&quot;c-Doc&quot;&gt;//// Crate B ////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&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;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Note: not specializable&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Out&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;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;c-Doc&quot;&gt;//// Crate C ////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Out&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we have &lt;em&gt;two&lt;/em&gt; traits in action, linked by the impl in crate B. The problem
is that, because the traits are connected in this way, adding the impl in crate
A for trait A creates overlap for trait &lt;em&gt;B&lt;/em&gt;. And crucially, it’s not enough to
require that the impl we &lt;em&gt;added&lt;/em&gt; be specializable; the problem is that the
existing impl in crate B, which crate A doesn’t even know about, is not
specializable.&lt;/p&gt;

&lt;p&gt;Like all of our problems around API evolution, this problem boils down to
&lt;em&gt;negative reasoning&lt;/em&gt;. In particular, crate C is initially allowed to write its
impl because it knows, locally, that &lt;code&gt;C&lt;/code&gt; does not implement &lt;code&gt;A&lt;/code&gt; (and thus the
blanket impl in crate B doesn’t apply). The problem is that crate C isn’t the
only crate that gets to decide whether it’s type implements &lt;code&gt;A&lt;/code&gt;. So it’s a
zero-sum game after all, and something like &lt;code&gt;fundemantal&lt;/code&gt; is needed to
adjudicate between different crates.&lt;/p&gt;

&lt;p&gt;You might ask: is it really essential to make specialization opt-in? And indeed,
if &lt;em&gt;all&lt;/em&gt; impls were specializable, the idea would’ve worked out.&lt;/p&gt;

&lt;p&gt;However, it’s not a tenable option. Associated types, in particular,
&lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md#hazard-interactions-with-type-checking&quot;&gt;need to opt in to specialization&lt;/a&gt;,
and these days every method has an implicit associated type.&lt;/p&gt;

&lt;h2 id=&quot;return-of-the-subset-rule&quot;&gt;Return of the Subset Rule&lt;/h2&gt;

&lt;p&gt;So where does that lead us?&lt;/p&gt;

&lt;p&gt;In the short term, it means that we should stick with the
&lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md#permitting-overlap&quot;&gt;subset rule&lt;/a&gt;
as-is. (I didn’t go into detail here, but Niko, Withoutboats and I had been
playing with some changes to support the idea of getting rid of fundamental,
which would also be breaking changes to the specialization rule; we’re backing
off on that).&lt;/p&gt;

&lt;p&gt;In the long term, there are several extensions we’d like to explore for
specialization. While these extensions won’t let us relax the orphan rule, they
will allow for more kinds of overlap, thereby making specialization usable in
more contexts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/&quot;&gt;&lt;strong&gt;Intersection impls&lt;/strong&gt;&lt;/a&gt;,
which allow arbitrary partial overlap between impls as long as there&amp;rsquo;s an
additional impl that covers precisely the area of overlap (thereby avoiding
any ambiguity).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/10/24/supporting-blanket-impls-in-specialization/&quot;&gt;&lt;strong&gt;Type structure precedence&lt;/strong&gt;&lt;/a&gt;,
which considers more specific *type structure* before considering where
clauses. While the idea was originally motivated by relaxing the orphan rules,
which we can&amp;rsquo;t do, it is still a potentially useful expansion of specialization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Child trumps parent&lt;/strong&gt;, in which a child crate impl always specializes any
parent crate impl it overlaps with. This rule is particularly simple and is
usually what you want when such overlap arises.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news is that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current subset rule is forwards-compatible with *all* of these extensions.&lt;/li&gt;
&lt;li&gt;Moreover, these extensions are compatible with each other!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think it’s probably worth ultimately landing all three extensions under
separate feature gates, to gain experience and determine which ones are most
useful. They are all pretty straightforward to implement.&lt;/p&gt;

&lt;p&gt;In the meantime, though, we can press forward with stabilization of today’s
specialization, as soon as the remaining implementation issues are resolved.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Designing futures for Rust</title>
   <link href="http://aturon.github.io/tech/2016/09/07/futures-design/"/>
   <updated>2016-09-07T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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’re looking for
more on the &lt;em&gt;use&lt;/em&gt; of the library, you’ll have to wait; we’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’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s successful
&lt;a href=&quot;https://static.rust-lang.org/doc/master/std/iter/trait.Iterator.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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) “hand-rolled” 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “readiness” style rather than the “completion” style.)
That means that composing futures together does not involve creating
intermediate callbacks. As we’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’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’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’s traits. I won’t attempt a complete introduction here, but I’ll try to hit
the most relevant highlights for making sense of what’s going on.&lt;/p&gt;

&lt;p&gt;Traits provide Rust’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’s a
simplified trait for hashing:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This trait stipulates that the type implementing it must provide a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; and produces a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&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;k&quot;&gt;else&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Hash&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&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;p&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;/div&gt;

&lt;p&gt;Once these implementations are in place, you can make calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The hash is {}&quot;&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;nf&quot;&gt;.hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_hash&lt;/code&gt; function is generic over an unknown type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;, but requires that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hash&lt;/code&gt; trait. That means we can use it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i32&lt;/code&gt;
values:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&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;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// instantiates T = bool&lt;/span&gt;
&lt;span class=&quot;nf&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;c1&quot;&gt;// instantiates T = i32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// The compiled code:&lt;/span&gt;
&lt;span class=&quot;nf&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;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// invoke specialized bool version directly&lt;/span&gt;
&lt;span class=&quot;nf&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;c1&quot;&gt;// invoke specialized i32 version directly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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, “hand-rolled” style.&lt;/p&gt;

&lt;p&gt;Closures in Rust work the same way—in fact, they’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “objects”, which cause the trait methods
to be &lt;em&gt;dynamically&lt;/em&gt; dispatched (so the compiler doesn’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’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’ll want futures to be some kind of trait, since there will be many
different kinds of “values that aren’t ready yet” (e.g. data on a socket, the
return value from an RPC call, etc.). But how do we represent the “not ready
yet” 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’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;type&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;c1&quot;&gt;// Tell the future to invoke the given callback on completion&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;k&quot;&gt;self&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;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&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;nf&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnOnce&lt;/code&gt; here is a trait for closures that will be invoked at most
once. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s consider a basic way of combining two futures:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&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;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;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;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nn&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;where&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;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;Future&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function takes two futures, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt;, and returns a new future that
yields a pair with results from both. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt; using the above definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt;? The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt;ed future will be given a single callback &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;both_done&lt;/code&gt; which expects a
pair. But the underlying futures each want their own callbacks &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_done&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_done&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g_done&lt;/code&gt; so that either can invoke
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;both_done&lt;/code&gt;, and make sure to include appropriate synchronization as well. Given
the type signatures involved, there’s simply no way to do this without
allocating (in Rust, we’d use an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “standard” future abstraction provide
zero-cost composition of futures, and we know of no “standard” 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 “demand-driven” definition of
futures. Here’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;type&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;c1&quot;&gt;// Polls the future, resolving to a value if possible&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/// Represents that a value is immediately ready.&lt;/span&gt;
    &lt;span class=&quot;nf&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;cd&quot;&gt;/// Represents that a value is not ready yet, but may be so later.&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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’s not yet ready and must
be polled again at some later point by returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Async::NotReady&lt;/code&gt; (an
abstraction of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “readiness” 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’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’ve addressed some of the key
problems of the previous version of the trait. But we’ve introduced a new one:
after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt; is returned, who polls the future, and when do they do so?&lt;/p&gt;

&lt;p&gt;Let’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt;. &lt;em&gt;Somehow&lt;/em&gt;, we must arrange for the future to later be “woken
up” (by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;nf&quot;&gt;.and_then&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;p&quot;&gt;{&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.and_then&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;{&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;my_socket&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key point is that there’s a difference between functions like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and_then&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;wait&lt;/code&gt;, polling takes place
immediately; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “blocks”
by yielding back to its executor, &lt;strong&gt;after installing itself as a callback for
the events it’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt; result the
task can be added to the event loop’s dispatch table, so that it will be woken
up when the socket becomes ready, at which point it will re-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;park&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unpark&lt;/code&gt; API for
“blocking” and wakeup:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/// Indicate that the task should attempt to poll its future in a timely fashion.&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Blocking a future is a matter of using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;park&lt;/code&gt; to get a handle to its task,
putting the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Task&lt;/code&gt; in some wakeup queue for the event of interest, and
returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt;. When the event of interest occurs, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;park&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “green” (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’s an essential difference from Rust’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’s revisit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;To implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt; function, we’ll introduce a new concrete type, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Join&lt;/code&gt;,
that tracks the necessary state:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&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;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&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;n&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;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;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;-&amp;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;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;nn&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&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;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&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;n&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;nf&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;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;FirstDone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&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;nn&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&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;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nn&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;c1&quot;&gt;// navigate the state machine&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first thing to notice is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Join&lt;/code&gt; is an &lt;em&gt;enum&lt;/em&gt;, whose variants represent
states in the “join state machine”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BothRunning&lt;/code&gt;: the two underlying futures are both still executing.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’s exactly
what we want—that size represents the “high water mark” of this little state
machine.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt; method here will attempt to make progress through the state machine
by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt;ing the underlying futures as appropriate.&lt;/p&gt;

&lt;p&gt;Recall that the aim of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt;ing their futures will return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt;, effectively
“blocking” the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Join&lt;/code&gt; future, while stashing a handle to the ambient &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Task&lt;/code&gt;, but that’s fine: &lt;strong&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unpark&lt;/code&gt; method for waking a task is
threadsafe, and guarantees that the task will &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt; its future at least once
after any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt; takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut self&lt;/code&gt;, which means that a given
future cannot be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt;ed concurrently—the future has unique access to its
contents while polling. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unpark&lt;/code&gt; synchronization guarantees it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One final point. Combinators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt; embody “small” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt;ing one of the underlying
futures for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Join&lt;/code&gt; state machine. &lt;strong&gt;The fact that the use of the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “big” future being run by a task—made up of a large chain of
futures connected by combinators—embodies a “big” nested state machine in just
this way. Once more, Rust’s enum representation means that the space required is
the size of the state in the “big” machine with the largest footprint. The space
for this “big” future is allocated in &lt;em&gt;one shot&lt;/em&gt; by the task, either on the
stack (for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wait&lt;/code&gt; executor) or on the heap (for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’re no longer interested in its
result.&lt;/p&gt;

&lt;p&gt;In the demand-driven model, cancellation largely “falls out”. All you have to do
is stop polling the future, instead “dropping” it (Rust’s term for destroying
the data). And doing so is usually a natural consequence of nested state
machines like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’s because tasks can be indefinitely “blocked” by a future/stream
returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotReady&lt;/code&gt; to slow down
requests. Often, such &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;park&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “epoll for everyone”:
the ability to associate “unpark events” with a given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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
“callback” 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’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’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/tech/2016/08/26/tokio/"/>
   <updated>2016-08-26T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2016/08/26/tokio</id>
   <content type="html">&lt;p&gt;If you’ve been following Rust in the last month, you’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’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’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-io-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;
    &lt;p&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’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 – all of which can be
written independently from any particular service or protocol. Read
&lt;a href=&quot;https://monkey.org/~marius/funsrv.pdf&quot;&gt;Your Server as a Function&lt;/a&gt; for the inspiration.&lt;/p&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;/li&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 “dispatch” 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 “middleware” 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’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’s the entry point for you; it’s particularly useful for cases
that don’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 “one stop shop” 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’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’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’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’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’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’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’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’re interested in any of this, any other integrations, or
the core libraries, we’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’re coming to RustConf, we’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/tech/2016/08/11/futures/"/>
   <updated>2016-08-11T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2016/08/11/futures</id>
   <content type="html">&lt;p&gt;One of the key gaps in Rust’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’re very low level: you
have to wire up state machines and juggle callbacks directly.&lt;/p&gt;

&lt;p&gt;We’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’s the same goal that’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’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’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’s features come together in
the design of this zero-cost abstraction. And there’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-io&quot;&gt;Why async I/O?&lt;/h2&gt;

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

&lt;p&gt;Let’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;read_exact&lt;/code&gt;&lt;/a&gt;,
to do this:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;nf&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;n&quot;&gt;my_vec&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;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Quick quiz: what happens if we haven’t received enough bytes from the socket yet?&lt;/p&gt;

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

&lt;p&gt;Early on, Rust had a “green threading” model, not unlike Go’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 “M:N threading”). In the green threading model, a
function like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’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 – and in fact, it’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’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 – 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’s a lot of painful work tracking all of the I/O events
you’re interested in, and dispatching those to the right callbacks (not to
mention programming in a purely callback-driven way). That’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’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’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; (the “unit” 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
– 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… 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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&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;c1&quot;&gt;// ... lots more elided ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt; type says what kind of value the future will yield once it’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; syntax&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;o&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;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;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;RpcServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&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;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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TcpStream&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;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;o&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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.and_then(|val| some_new_future(val))&lt;/code&gt;. Gives you a future that executes the
future &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, takes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt; it produces to build another future
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.map(|val| some_new_value(val))&lt;/code&gt;. Gives you a future that
executes the future &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; and yields the result of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.join(g)&lt;/code&gt;. Gives you a future that executes the futures &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.select(g)&lt;/code&gt;. Gives you a future that executes the futures &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;nf&quot;&gt;.and_then&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;p&quot;&gt;{&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.and_then&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;{&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;my_socket&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Iterator&lt;/code&gt; in the standard library.)  Ergonomic, high-level code that compiles
to state-machine-and-callbacks: that’s what we were after!&lt;/p&gt;

&lt;p&gt;It’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 – there’s more! As you keep pushing on the future “combinators”,
you’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; is a stream, you can write:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.and_then&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;nf&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code will give you a new stream that works by first pulling a value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt;
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;, then computing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;some_future(val)&lt;/code&gt; from it, then executing that future
and yielding its value – then doing it all over again to produce the next value
in the stream.&lt;/p&gt;

&lt;p&gt;Let’s see a real example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ParseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// For each request, run our service&apos;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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.and_then&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;service&lt;/span&gt;&lt;span class=&quot;nf&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;c1&quot;&gt;// Create a new future that&apos;ll write out each response to an `output` I/O object&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;StreamWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;responses&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we’ve written the core of a simple server by operating on streams. It’s
not rocket science, but it is a bit exciting to be manipulating values like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;responses&lt;/code&gt; that represent the entirety of what the server is producing.&lt;/p&gt;

&lt;p&gt;Let’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ParseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&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;service&lt;/span&gt;&lt;span class=&quot;nf&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;nf&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;c1&quot;&gt;// &amp;lt;--&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;StreamWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;responses&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;and_then&lt;/code&gt;, not only are we not allocating, we are in fact
building up a big &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; that represents the state machine. (There is one
allocation needed per “task”, 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;amp;hw=peak&amp;amp;test=plaintext&quot;&gt;TechEmpower “plaintext” benchmark&lt;/a&gt;. This
microbenchmark tests a “hello world” HTTP server by throwing a huge number of
concurrent and pipelined requests at it. Since the “work” 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’s standard library’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’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 “Hello world!”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’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 “raw
  mio” 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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’re actively working
with several people in the Rust community to integrate with their work; if
you’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 “middleware” for servers, and has gotten a lot
of traction in Twitter’s &lt;a href=&quot;https://twitter.github.io/finagle/&quot;&gt;Finagle&lt;/a&gt; library
for Scala; it’s also being used in Facebook’s
&lt;a href=&quot;https://github.com/facebook/wangle&quot;&gt;Wangle&lt;/a&gt; library. In the Rust world, there’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’s an enormous amount of work ahead:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;First off, we’re eager to hear feedback on the core future and stream
abstractions, and there are some specific design details for some combinators
we’re unsure about.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Second, while we’ve built a number of future abstractions around basic I/O
concepts, there’s definitely more room to explore, and we’d appreciate help
exploring it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;More broadly, there are endless futures “bindings” for various libraries (both
in C and in Rust) to write; if you’ve got a library you’d like futures bindings
for, we’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’d love to hear from you – we’re &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acrichto&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aturon&lt;/code&gt; on Rust’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/tech/2016/07/27/rust-platform/"/>
   <updated>2016-07-27T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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’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 –
&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;
– 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’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
“core”: today, essentially it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libstd&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 (“&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; is where code goes to die”).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short, there are batteries out there, but we’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 “batteries included” experience for Rust that doesn’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’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 “The Rust Platform”?&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;Distribute a wide range of artifacts in a single “Rust Platform Package”, including:
    &lt;ul&gt;
      &lt;li&gt;The compiler, Cargo, rust-lang crates (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;Periodically curate the ecosystem, determining consensus choices for what
artifacts, and at what versions, to distribute.&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’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’d expect, the real meat here is in the details. It’s probably unclear
what it even means to “distribute” a library, given Cargo’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “packaging” 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;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[dependencies]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;rust-platform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.7&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which is effectively then shorthand for something like:&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[dependencies]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mio&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.2&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;regex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.0&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.1&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;serde&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 “Rust Platform
2.0 Series” as a chapter in Rust’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’s look at the ways that the platform is,
and is not, like a bigger &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; is effectively coupled with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s simply not feasible to do a new, major version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; with breaking
changes. Moreover, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’ve
chosen to take a minimalist route with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; (see below for more on
that). But it doesn’t suffer from the deficits of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustup&lt;/code&gt; to the latest platform will never break your
existing code, for one simple reason: existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; file. So, for example, if you say:&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[dependencies]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;rust-platform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.7&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;regex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;you’re getting the versions stipulated by platform 2.7 in general, but
specifying a different version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt; itself.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo new&lt;/code&gt;&lt;/strong&gt;. A simple step: have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo new&lt;/code&gt; automatically insert a
dependency on the current toolchain’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’re going to be
compiling some large number of crates that you’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustup&lt;/code&gt; – much like we already
do for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt;&lt;/strong&gt;. Getting a bit more aggressive, we might drop the need
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt; when using platform crates, giving a truly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;-like
feel. (In general, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate&lt;/code&gt; is already redundant with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’ve already alluded to “major versions” of the platform in a few senses. Here’s
what I’m thinking in more detail:&lt;/p&gt;

&lt;p&gt;First off, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustc&lt;/code&gt; itself is separately versioned. Conceivably, the Rust
Platform 5.0 ships with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’s also helpful
externally, because people less immediately involved in Rust’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 “north star” 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’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’ll want to
be quite selective about what’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’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: “Parsing”,
“Networking”, “Serialization”, “Debugging”. 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 “see more” 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 “see more”; 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 “see more” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;rust-lang&lt;/code&gt; crates&lt;/h2&gt;

&lt;p&gt;One small note: our previous attempt at a kind of “extended &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;” 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 “owned” by the Rust community, and governed by the RFC process, much
like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;. They’re also held to similar quality standards.&lt;/p&gt;

&lt;p&gt;Ultimately, it’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 “federated” 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 “owned by the community”. 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’t
run entirely through the libs team; that doesn’t scale, and the team doesn’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 –
let’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’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’s evolution, and lets us rally around that story as we hammer
out the work needed to bring it to life. I’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/tech/2016/07/05/rfc-refinement/"/>
   <updated>2016-07-05T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2016/07/05/rfc-refinement</id>
   <content type="html">&lt;p&gt;At the heart of Rust’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’s not all roses. There’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’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’ve never had quite as clear of a “north star”. We’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’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’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 “major initiatives” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 “MIR” doesn’t fly, but “Get
MIR-trans working on all of crates.io” 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’ve often found that
there are recurring questions (“When is MIR going to be turned on by default?”)
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’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’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’t allow for cross-cutting initiatives very easily.&lt;/li&gt;
  &lt;li&gt;Can we find less boring terms than “Roadmap” and “Initiative”?&lt;/li&gt;
  &lt;li&gt;Can we also include the “feature pipeline” 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-1&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;RFCs are hard to keep up with in part because reading a full design – and all
the commentary around it – 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 “controversial”
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 “competing” (offering
alternative proposals for a common problem), or to correlate discussion between
the discuss forum and github.&lt;/p&gt;

&lt;p&gt;It’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 “postponed”, 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-1&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’s call this venue the “Problem Tracker”.&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 – solving problems – 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 “pre-RFC” &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 – and
indeed, this is a good way to take the “Alternatives” 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’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’t ever open an RFC PR out of hand – 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’ll
see) by decentralizing the process a bit more. In addition, it makes it easier
to cope with the problem of “Does this need an RFC?”&lt;/p&gt;

&lt;p&gt;As part of this proposal, &lt;strong&gt;I think we should “reboot” 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’t necessarily responsible for the final decision. So, for example, we
would have a larger set of “lang shepherds” 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;“Calling to question” – 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 “scribe” for the RFC process, by keeping the Problem Tracker up
to date. In particular, the subteams currently attempt to provide “summary”
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’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 “problem tracker” live?&lt;/li&gt;
  &lt;li&gt;What are good guidelines around an initial “motivation”?&lt;/li&gt;
  &lt;li&gt;How and where can we keep an “official record” 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-2&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 “reactive” mode, more than
actively leading&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another issue is that meetings provide, in some sense, the “wrong defaults” 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 – 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-2&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 – or anyone else – 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 “forcing function” 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 – and that list needs to be kept manageably
short.&lt;/p&gt;

&lt;p&gt;We’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;“process: fcp”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Approving/disapproving FCP
    &lt;ul&gt;
      &lt;li&gt;“process: fcp r+”&lt;/li&gt;
      &lt;li&gt;“process: fcp r-“&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Extending FCP
    &lt;ul&gt;
      &lt;li&gt;“process: fcp extend” (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;“process: r+” (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 “process: r+” once you are satisfied
that the objection is addressed or that it’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;“process: r-“ (followed up with objection)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Abstaining (possibly?)
    &lt;ul&gt;
      &lt;li&gt;“process: ack”&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’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/tech/2015/09/28/impl-trait/"/>
   <updated>2015-09-28T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “elision” terminology, which was more confusing than
helpful. I also now mention some implementation issues for the return type
inference proposal. And I’ve toned down my preference in the wrapup; I’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 – my
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/105&quot;&gt;first Rust RFC&lt;/a&gt;! – which is known
as the “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt;” proposal. The RFC termed these “unboxed abstract types”,
and it’s easiest to start with the motivation given there:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In today’s Rust, you can write a function signature like&lt;/p&gt;

  &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;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;nb&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;:&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;nb&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;/code&gt;&lt;/pre&gt;&lt;/div&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 “abstract”, 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;-&amp;gt;&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;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&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;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;That is, in today’s Rust, abstract return types can only be written using trait objects, which
can be a significant performance penalty. This RFC proposes “unboxed abstract
types” as a way of achieving signatures like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rev&amp;lt;Splits&amp;lt;&apos;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 class=&quot;language-plaintext highlighter-rouge&quot;&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;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&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;n&quot;&gt;SkipWhile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&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;/code&gt;&lt;/pre&gt;&lt;/div&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;/li&gt;
    &lt;li&gt;
      &lt;p&gt;&lt;em&gt;Documentation&lt;/em&gt;. In today’s Rust, reading the documentation for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Chain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Zip&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;/p&gt;
    &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’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 “gap” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&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;nb&quot;&gt;u8&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Iterator&amp;lt;u8&amp;gt;&lt;/code&gt; should be understood as “some type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; such that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;iter&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;iter&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;iter&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&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;/code&gt;&lt;/pre&gt;&lt;/div&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’t really been discussed. But they all have to be tackled.&lt;/p&gt;

&lt;p&gt;First I’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt; a type?&lt;/h3&gt;

&lt;p&gt;Can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt; “sealed”?&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;-&amp;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;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BigLongIterator&lt;/span&gt; &lt;span class=&quot;o&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;/code&gt;&lt;/pre&gt;&lt;/div&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nsa&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Works with any T!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&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;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;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;o&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;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;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here “type inference” means something akin to leaving off a type
annotation that’s required today (like the return type of a function),
without any change to semantics.  By contrast, “type abstraction”
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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clone&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Iterator&lt;/code&gt; adapters?&lt;/h3&gt;

&lt;p&gt;It’s pretty common that a trait is &lt;em&gt;conditionally&lt;/em&gt; implemented:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;p&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But that poses a problem for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clone&lt;/code&gt; if the original
iterator is, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync&lt;/code&gt;, …) 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’s also an extensibility problem: new libraries can add new
“OIBIT”-style marker traits which are supposed to automatically apply to types,
but forcing those markers to be explicitly opted in to for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt; means
they often won’t apply. We’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’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 “hiding” that @Ericson2314 was talking about)&lt;/li&gt;
  &lt;li&gt;more ergonomic newtypes (where you don’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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;-&amp;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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&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;p&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;k&quot;&gt;-&amp;gt;&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;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(||&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;first closure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;second closure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The idea here is that the actual return type is fully concrete – 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt;, like:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;-&amp;gt;&lt;/span&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&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;p&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;k&quot;&gt;-&amp;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;nf&quot;&gt;FnOnce&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;nf&quot;&gt;FnOnce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(||&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;first closure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;second closure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The idea is that these trait bounds don’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;~FnOnce()&lt;/code&gt; means “an elided type with interface roughly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnOnce()&lt;/code&gt;”.) Usually,
there is one “primary” trait for a given return type, though of course you can
list as many as you like using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&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;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;k&quot;&gt;self&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;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nf&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To be clear about the “roughly” here: in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; example, the return type also
implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clone&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExactSizeIterator&lt;/code&gt; – 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 – the typechecker will need to
check function definitions in a particular order to discover concrete types, and
must ensure that return type inference isn’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’s dead simple from the programmer’s perspective. There are no
thorny questions about type equality, scoping of type abstractions,
or what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; means in various contexts. It’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 “OIBITs” without any fuss.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This kind of “leakage” is already prevalent – and important! – 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;, &lt;em&gt;everything&lt;/em&gt; about the associated type is revealed:&lt;/p&gt;

    &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&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;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assoc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// we know that u8::Assoc == u8! We&apos;re only limited to the bound when writing&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;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&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’d have to do
something like assign it to a suitably-typed mutable variable:&lt;/p&gt;

    &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&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;n&quot;&gt;SkipWhile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nb&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;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;some_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design addresses all of the hard constraints and strong desires – 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’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’m going to give one particular strawman proposal and syntax here, and only at
a high level – it’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 “type abstraction operator” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; that is used to
“seal” a concrete type to a particular interface:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;o&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Seek&lt;/span&gt; &lt;span class=&quot;o&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should read this as “at”, meaning that you are viewing a type “at” some
specific bounds.&lt;/p&gt;

&lt;p&gt;This definition is roughly equivalent to:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&apos;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&apos;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Seek&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&apos;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// forward to FileDesc&apos;s Read impl&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;File = FileDesc&lt;/code&gt; is
known. Within that scope (“inside the abstraction boundary”), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt; is a simple
type alias for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileDesc&lt;/code&gt;. Outside that scope, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t have to explicitly project using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.0&lt;/code&gt; or
construct using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t try to answer here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Aside from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; definitions, where else can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; be used? We’ll explore one
other location – function signatures – in this post, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt;? Inherent methods? What if they conflict with traits/methods
on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt; position? For
example, there is also an impl of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Read&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; proposal is that, when used in function signatures,
you can leave off the type before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; (i.e., the concrete type being
abstracted):&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;k&quot;&gt;-&amp;gt;&lt;/span&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlike the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’t know that the iterator
is also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “sealing” work, we’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync&lt;/code&gt; are often “defaulted” (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt; impls, AKA
OIBITs). When you follow the newtype pattern, these “defaulted” traits come
along for the ride, whether you ask for them or not – they leak through. They
are also often conditional (e.g., one type is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt; if some other types are
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send&lt;/code&gt;). It’s probably simplest to say that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Trait&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;p&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To deal with this situation, we’d need conditional bounds like:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;o&quot;&gt;+&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&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;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;o&quot;&gt;+&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;DoubleEndedIterator&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;o&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;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These aliases still have documentation advantages over the current adapter API,
since you’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;benefitsdrawbacks&quot;&gt;Benefits/drawbacks&lt;/h3&gt;

&lt;p&gt;So in all, it seems feasible to introduce a type abstraction feature, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “principled” than the pure type inference design:
except for OIBIT traits, the entire interface to a type must be written
explicitly, so there’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; gives a lighter weight form of newtypes that doesn’t require
manually forwarding trait impls (akin to “generalized newtype deriving” from
the Haskell world). However, these types would likely not function as complete
newtypes from the perspective of impl coherence – it probably doesn’t make
sense to impl new traits for them, for example. So they don’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’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 “newtype deriving” 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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; can no
longer be understood as a straight-up alias, since repeated uses of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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/tech/2015/09/18/reuse/"/>
   <updated>2015-09-18T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/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
“virtual structs” 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’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’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’ve been pursuing, &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; specialization&lt;/a&gt; plays a key
role. That’s appealing because specialization is something we’ve long wanted for
other reasons, and is a natural deepening of our trait system. But it’s not
quite enough, by itself, to meet all of the constraints above.&lt;/p&gt;

&lt;p&gt;I’m going to start by recapping the specialization design. Then I’ll explore two
competing avenues for building on specialization to meet the design constraints,
choose-your-own-adventure style. At the end, I’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 “most specific” impl that applies to a given concrete type.
The more general impl uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; to signal which items can be specialized –
sort of the opposite of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;final&lt;/code&gt; in Java, or a bit like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Extend&lt;/code&gt; trait:&lt;/p&gt;

  &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterable&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;k&quot;&gt;where&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;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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;iterable&lt;/code&gt; that it’s given except that it can be transformed into
an iterator. That means the code must work by repeatedly calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 – and the optimizer isn’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Extend&lt;/code&gt; we need to refactor a bit:&lt;/p&gt;

  &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterable&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;p&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;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;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;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;k&quot;&gt;where&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;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;c1&quot;&gt;// the `default` qualifier allows this method to be specialized below&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterable&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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// implementation using push (like today&apos;s extend)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;k&quot;&gt;for&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterable&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;nv&quot;&gt;&apos;a&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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because the generic impl uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; for its implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extend&lt;/code&gt;, it’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’t have to provide all the items for a trait; whatever
it doesn’t provide is automatically inherited from the generic impl it’s
specializing. And conversely, it can &lt;em&gt;only&lt;/em&gt; override items marked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Going a bit farther, it’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt;, such that
they are always overloaded together:&lt;/p&gt;

  &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nb&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;k&quot;&gt;Self&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;k&quot;&gt;type&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;Rhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;In this case, there’s no natural way to provide a default implementation of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_assign&lt;/code&gt;, since we do not want to restrict the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add&lt;/code&gt; trait to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;partial&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;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&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;nb&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;k&quot;&gt;for&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;c1&quot;&gt;// the `default` qualifier allows further specialization&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&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;rhs&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;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;This partial impl does &lt;em&gt;not&lt;/em&gt; mean that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add&lt;/code&gt; is implemented for all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clone&lt;/code&gt;
data, but jut that when you do impl &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self: Clone&lt;/code&gt;, you can leave off
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_assign&lt;/code&gt;:&lt;/p&gt;

  &lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;#[derive(Copy,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;Clone)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&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;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;nb&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;k&quot;&gt;for&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;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Output&lt;/span&gt; &lt;span class=&quot;o&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;Complex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;c1&quot;&gt;// no fn add_assign necessary&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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’t actually specify, a way to
“access” the implementation you’re overriding (akin to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super&lt;/code&gt; in the OO world).&lt;/p&gt;

&lt;p&gt;For the sake of this post, I’ll assume we’ve added such a mechanism by way of a
UFCS-like use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// do some complicated stuff&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;o&quot;&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;About to `foo` on {:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The idea is that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default::&lt;/code&gt; prefix accessing the generic impl that’s being
overridden, and works like UFCS (in that methods become functions taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;
explicitly).&lt;/p&gt;

&lt;p&gt;The details here aren’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’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’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’s an example, using a lightly simplified extract from Servo’s DOM
implementation.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&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;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;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child&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;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&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;c1&quot;&gt;// additional methods here&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Element&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;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&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;p&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;c1&quot;&gt;// additional Element methods&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&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;p&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;partial&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;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;p&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;n&quot;&gt;partial&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;n&quot;&gt;Activatable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Activatable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&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;c1&quot;&gt;// HtmlImageElement ////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&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;nb&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;c1&quot;&gt;// moar fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&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;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&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;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hspace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&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;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vspace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;mi&quot;&gt;0&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;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt; &lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This example is following a basic pattern:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Abstract base classes” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 … defaulted methods!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;“Concrete classes” 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, “overriding” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;partial impl&lt;/code&gt;. This is because there are usually still some “abstract” aka
“pure virtual” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;.&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as_activatable&lt;/code&gt; method is overridden for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T:
Activatable&lt;/code&gt; with a “final” version that cannot be further overridden.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’t have to add anything beyond specialization (which we’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’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 “fat pointers”: 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt; type, at least not if you want separate
compilation. After all, the crate defining a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;repr&lt;/code&gt; attribute. So we can address the desire for thin pointers to traits by
introducing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[repr(thin)]&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;#[repr(thin)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyThinTrait&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyThinTrait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyType&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&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;p&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;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;MyThinTrait&lt;/span&gt;&lt;span class=&quot;p&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;nf&quot;&gt;.doit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[repr(thin)]&lt;/code&gt; to a trait like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;MyThinTrait&lt;/code&gt; (used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 “inheritance”.&lt;/p&gt;

&lt;h3 id=&quot;incorporating-fields&quot;&gt;Incorporating fields&lt;/h3&gt;

&lt;p&gt;Now all that’s left to handle is fields. To get maximal performance, we need
some way for a trait to require that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’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’s a very simple way, in today’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventTarget&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;nb&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;c1&quot;&gt;// Note: this refers to the Node *trait*! see below.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;first_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;last_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;next_sibling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;prev_sibling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&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;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node_fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Element&lt;/code&gt; “inherits” the fields of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt; here is already a partly-constructed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s one possibility:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&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;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;ElementFields&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NodeFields&lt;/code&gt;
above). The chain then ends in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt; type implementing the trait.&lt;/p&gt;

&lt;p&gt;So, to complete the DOM example, we’d have:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;element_fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// internally, contains a leading NodeFields&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&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;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.parent_node&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(A more verbose alternative might be some UFCS-style &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 – in particular, this rules out
reordering of the field. If we don’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventTarget&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;nb&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;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;ElementFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Style 1: all fields&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;parent_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more NodeFields fields&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more ElementFields fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Style 2: using parent struct&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&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;NodeFields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;event_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;parent_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more NodeFields fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ElementFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;local_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more ElementFields fields&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;/code&gt;&lt;/pre&gt;&lt;/div&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&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;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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.parent_node&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeFields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In all cases, using a struct as a bound like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T: NodeFields&lt;/code&gt; means that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;
&lt;em&gt;must inherit from&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt; above, if we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n: &amp;amp;Node&lt;/code&gt;, we could write
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n.parent_node&lt;/code&gt; and that would compile as if we had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n: NodeFields&lt;/code&gt; instead.
Because inheritance is explicit at the point of struct definition, we don’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’s plausible that struct inheritance is generally useful outside of OO-like
hierarchies; certainly it avoids long chains like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s not necessary to address our goals here, you could also imagine
adding coercions from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;ElementFields&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&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;nb&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;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;?&lt;/li&gt;
  &lt;li&gt;Can the fields be hooked up arbitrarily to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt;, and you don’t have to say anything in an
impl. Furthermore, if you write:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DomTokenList&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;you automatically include the fields mentioned in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Element&lt;/code&gt; trait (including
those from its super-trait &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&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;nn&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nn&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;event_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;parent_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more Node fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&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;nn&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nn&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;n&quot;&gt;local_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more Element fields&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rel_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;c1&quot;&gt;// more HtmlAnchorElement fields&lt;/span&gt;
    &lt;span class=&quot;o&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;/code&gt;&lt;/pre&gt;&lt;/div&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 “abstract base classes” (like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NodeFields&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ElementFields&lt;/code&gt;); instead, these are implicit via the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “falls out” 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 – traits and &lt;em&gt;match expressions&lt;/em&gt; –
corresponding to “open” (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’t recap the whole proposal here (it’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&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;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&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;p&quot;&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;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TextElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParagraphElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given such a hierarchy, you can write:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;p&quot;&gt;:&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;n&quot;&gt;n&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;p&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&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 “any type under this
point in the hierarchy”, 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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_plain_attribute&lt;/code&gt; on an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HtmlAnchorElement&lt;/code&gt;, you’ll get the correct behavior.&lt;/p&gt;

&lt;p&gt;But if you’ve upcasted to an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Element&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt;, &lt;em&gt;the behavior will revert to
the defaults for those types&lt;/em&gt;! That’s because you’re not getting dynamic
dispatch here, which for enums we said should go through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;atom!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;self&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;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that we’re now using specialization &lt;em&gt;without any explicit blanket
impls&lt;/em&gt;. In this proposal, when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt; type is an enum, it’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; to dispatch to most specialized
implementation. That is, it’s as if we’d written the following for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;p&quot;&gt;:&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;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;default&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;AttrValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&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;n&quot;&gt;ParsePlainAttribute&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;self&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;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Atom&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;n&quot;&gt;DomString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AttrValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;ref&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;nn&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlAnchorElement&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;this&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;n&quot;&gt;name&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;k&quot;&gt;ref&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;nn&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HtmlImageElement&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;this&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;n&quot;&gt;name&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;c1&quot;&gt;// ...&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And of course:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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’s completely natural (just a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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 “fit” with the existing language.&lt;/p&gt;

&lt;p&gt;The main downside of my preferred struct/trait approach is that there’s some
amount of boilerplate: “abstract base classes” like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt; turn into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt;
trait and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s possible that in the long run, we’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’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 “common fields” (which included an associated
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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/tech/2015/08/27/epoch/"/>
   <updated>2015-08-27T00:00:00+00:00</updated>
   <id>http://aturon.github.io/tech/2015/08/27/epoch</id>
   <content type="html">&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;It’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’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’s as easy
to write.&lt;/p&gt;

&lt;p&gt;I’ve implemented “epoch-based memory reclamation” 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&apos;s-stack&quot;&gt;Treiber’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointers&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#atomic&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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&apos;s-stack-on-epochs&quot;&gt;Treiber’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’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.cs.rochester.edu/~scott/papers/1996_PODC_queues.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 “good GC” 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 “segmented” 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 “contention” – 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’s built-in
channels, which is optimized for this scenario (and hence doesn’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 – which has not been
tuned – is competitive in all cases. It’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’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 class=&quot;language-plaintext highlighter-rouge&quot;&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 – so let’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 – 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mutex&lt;/code&gt;&lt;/a&gt; and
calling it a day.&lt;/p&gt;

&lt;p&gt;Problem is, that kind of “coarse-grained” 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 – 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’t try to give a full tutorial to lock-free programming in this post, but a
key point is that, if you don’t have global synchronization, it’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
– and that’s what this blog post is all about.&lt;/p&gt;

&lt;h3 id=&quot;treibers-stack&quot;&gt;Treiber’s stack&lt;/h3&gt;

&lt;p&gt;To make things more concrete, let’s look at the “Hello world” of lock-free data
structures: Treiber’s stack. The stack is represented as a singly-linked list,
with all modifications happening on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; pointer:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;#![feature(box_raw)]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&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;n&quot;&gt;Release&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;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;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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&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;n&quot;&gt;data&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;next&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;k&quot;&gt;mut&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;p&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;-&amp;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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Stack&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;nn&quot;&gt;AtomicPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;nf&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s easiest to start with popping. To pop, you just loop, taking a snapshot of
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;compare_and_swap&lt;/code&gt; atomically changes the value of an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Acquire&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Release&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Relaxed&lt;/code&gt; labels if you’re
not familiar with them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;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;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// take a snapshot&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;c1&quot;&gt;// we observed the stack empty&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&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;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&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;unsafe&lt;/span&gt; &lt;span class=&quot;p&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;py&quot;&gt;.next&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&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;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;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
                    &lt;span class=&quot;c1&quot;&gt;// **NOTE**: leaks the node!&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;py&quot;&gt;.data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ptr::read&lt;/code&gt; function is Rust’s way of extracting ownership of data without
static or dynamic tracking. Here we are using the atomicity of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compare_and_swap&lt;/code&gt; to guarantee that only one thread will call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ptr::read&lt;/code&gt; –
and as we’ll see, this implementation never frees &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Node&lt;/code&gt;s, so the destructor on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; is never invoked. Those two facts together make our use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ptr::read&lt;/code&gt;
safe.&lt;/p&gt;

&lt;p&gt;Pushing is similar:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;into_raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;Node&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;n&quot;&gt;t&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;nf&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// snapshot current head&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;c1&quot;&gt;// update `next` pointer with snapshot&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&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;py&quot;&gt;.next&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;p&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&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;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;k&quot;&gt;break&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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’d be done. But as written
in Rust, it leaks memory. In particular, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop&lt;/code&gt; implementation doesn’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;py&quot;&gt;.data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// free the node&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem is that other threads could also be running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;(*head).next&lt;/code&gt; on that snapshot just after we
deallocate the node they’re pointing to – a use-after-free bug in the making!&lt;/p&gt;

&lt;p&gt;So that’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’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 – 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’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 “active” 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’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 “active” 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’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 “active” 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 “garbage collection” is done concurrently,
it’s possible for threads to be in one of two epochs at any time (the “old” one,
and the “new” 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 “GC” 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’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
“active” 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’ll leverage Rust’s ownership system – in particular, ownership-based
resource management (aka RAII) – 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 class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;-&amp;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guard&lt;/code&gt; represents “being active”, a borrow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;a Guard&lt;/code&gt; guarantees
that the thread is active for the entire lifetime &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; – 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&amp;lt;T&amp;gt;&lt;/code&gt;, akin to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&amp;lt;&apos;a, T&amp;gt;&lt;/code&gt;, akin to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&amp;lt;T&amp;gt;&lt;/code&gt;, akin to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::sync::atomic::AtomicPtr&lt;/code&gt;, which provides atomic
updates to a pointer using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; types, and connects them
to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guard&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll look at each of these in turn.&lt;/p&gt;

&lt;h3 id=&quot;owned-and-shared-pointers&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointers&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt; pointer has an interface nearly identical to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Box&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nb&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;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&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;nb&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;k&quot;&gt;pub&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;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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&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;p&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;n&quot;&gt;Deref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&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;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Target&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;p&quot;&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;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;n&quot;&gt;DerefMut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&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;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&amp;lt;&apos;a, T&amp;gt;&lt;/code&gt; pointer is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;a T&lt;/code&gt; – it is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Copy&lt;/code&gt; – but it
dereferences to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&apos;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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;nv&quot;&gt;&apos;a&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;nv&quot;&gt;&apos;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;...&lt;/span&gt; &lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;nv&quot;&gt;&apos;a&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;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;...&lt;/span&gt; &lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;nv&quot;&gt;&apos;a&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;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;...&lt;/span&gt; &lt;span class=&quot;p&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Deref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt;, there is no way to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer directly. Instead,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointers are acquired by reading from an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&lt;/code&gt;, as we’ll see
next.&lt;/p&gt;

&lt;h3 id=&quot;atomic&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The heart of the library is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;p&quot;&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;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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/// Create a new, null atomic pointer.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;-&amp;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;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;_&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;nv&quot;&gt;&apos;a&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;k&quot;&gt;-&amp;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;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to perform the load, we must pass in a borrow of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;. In return, you get an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer back
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&lt;/code&gt; is currently null), with lifetime tied to the guard.&lt;/p&gt;

&lt;p&gt;It’s interesting to compare this to the standard library’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AtomicPtr&lt;/code&gt;
interface, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;load&lt;/code&gt; returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*mut T&lt;/code&gt;. Due to the use of epochs, we’re able
to guarantee safe dereferencing of the pointer within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;, whereas with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’t need any assurance about the lifetimes of pointers:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&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;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 – for example,
because we want to add additional links to the same node in the data
structure. In that case, we’ll need to tie the lifetime to a guard:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_and_ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;k&quot;&gt;self&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;nb&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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;_&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;nv&quot;&gt;&apos;a&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;k&quot;&gt;-&amp;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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the runtime representation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt; and the return value is exactly
the same – we’re passing a pointer in, and getting the same pointer out. But
the &lt;em&gt;ownership&lt;/em&gt; situation from Rust’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;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&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;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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This operation does not require a guard, because we’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer with a fresh &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Owned&lt;/code&gt; one:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&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;nb&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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;k&quot;&gt;-&amp;gt;&lt;/span&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;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;store&lt;/code&gt;, this operation does not require a guard; it produces no new
lifetime information. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; indicates whether the CAS succeeded; if not,
ownership of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;store_and_ref&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cas_and_ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;_&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;nv&quot;&gt;&apos;a&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;k&quot;&gt;-&amp;gt;&lt;/span&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;nv&quot;&gt;&apos;a&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;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case, on a successful CAS we acquire a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer to the data we
inserted.&lt;/p&gt;

&lt;p&gt;Finally, we can replace one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer with another:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&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;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;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&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;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The boolean return value is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guard&lt;/code&gt; that the memory should be reclaimed:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&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;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&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;k&quot;&gt;self&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;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;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This operation adds the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shared&lt;/code&gt; pointer
here and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Guard&lt;/code&gt;; if we have a reachable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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’s stack on epochs&lt;/h3&gt;

&lt;p&gt;Without further ado, here is the code for Treiber’s stack using the Crossbeam
epoch API:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&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;n&quot;&gt;Release&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;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&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;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;crossbeam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&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;nb&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&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;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;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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&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;n&quot;&gt;data&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;next&lt;/span&gt;&lt;span class=&quot;p&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;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;p&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;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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;-&amp;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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TreiberStack&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;nn&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&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;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// allocate the node via Owned&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;Node&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;n&quot;&gt;t&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;nn&quot;&gt;Atomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;p&quot;&gt;});&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// become active&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// snapshot current head&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;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;c1&quot;&gt;// update `next` pointer with snapshot&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.next&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;n&quot;&gt;head&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;c1&quot;&gt;// if snapshot is still good, link in the new node&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&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;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;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nf&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;k&quot;&gt;=&amp;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;nf&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;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&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;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&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;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;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;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;c1&quot;&gt;// become active&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;epoch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&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;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// take a snapshot&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&lt;/span&gt;&lt;span class=&quot;nf&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;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;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// the stack is non-empty&lt;/span&gt;
                &lt;span class=&quot;nf&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;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;c1&quot;&gt;// read through the snapshot, *safely*!&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;let&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;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.next&lt;/span&gt;&lt;span class=&quot;nf&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;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;c1&quot;&gt;// if snapshot is still good, update from `head` to `next`&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.head&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;nf&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;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;c1&quot;&gt;// mark the node as unlinked&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;nf&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;c1&quot;&gt;// extract out the data from the now-unlinked node&lt;/span&gt;
                            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&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;py&quot;&gt;.data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;c1&quot;&gt;// we observed the stack empty&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&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;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 “unlinked”. In general,
it’s possible to take lock-free algorithms “off the shelf” (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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe&lt;/code&gt;,
because the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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’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 “unlinked” 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 class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&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’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’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 “collect” 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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;unlinked&lt;/code&gt;
– that’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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atomic&lt;/code&gt; fields), and the actual data
contained (like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; field in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;static&lt;/code&gt; (and non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&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 –
including a lock-free hashmap, work-stealing deques, and lightweight task
engine. If you’re interested in this work, I’d love to have help!&lt;/p&gt;
</content>
 </entry>
 

</feed>
