<?xml version="1.0" encoding="UTF-8"?>

<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>joshlf.com</title>
  
  <subtitle>The homepage of Josh Liebow-Feeser</subtitle>
  
  <link rel="self" type="application/atom+xml" href="https://joshlf.com/atom.xml"/>
  <link rel="alternate" type="text/html" href="https://joshlf.com/posts/"/>
  <generator uri="https://www.getzola.org/">Zola</generator>
  
  
    
    
  <updated>2026-07-27T00:00:00+00:00</updated>
      
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
    
    
  
  <id>https://joshlf.com/atom.xml</id>
  
    
    
  <entry xml:lang="en">
    <title>Safety in an `unsafe { world }`</title>
    <published>2026-07-27T00:00:00+00:00</published>
    <updated>2026-07-27T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/safety-unsafe-world/"/>
    <id>https://joshlf.com/posts/safety-unsafe-world/</id>
    
      
    <category term="Rust"/>
      
    <category term="Unsafe"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/safety-unsafe-world/">&lt;p&gt;&lt;em&gt;This post is a nearly verbatim adaptation of my RustConf 2024 talk. I&#x27;ve kept everything in the present tense as it was in September 2024. Towards the end, I&#x27;ve also included a bit of content that I had planned on presenting but had to skip during the presentation for time.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=qd3x5MCUrhw&quot;&gt;Watch the talk&lt;&#x2F;a&gt; · &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;joshlf.com&#x2F;files&#x2F;talks&#x2F;Safety%20in%20an%20Unsafe%20World.pdf&quot;&gt;See the slides&lt;&#x2F;a&gt; · &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;joshlf&#x2F;65ccb20e034445a0fc6595f3a270653d&quot;&gt;See the full references&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;netstack3&quot;&gt;Netstack3&lt;&#x2F;h2&gt;
&lt;p&gt;So what is this talk about? Well, I&#x27;m going to bury the lede a bit.&lt;&#x2F;p&gt;
&lt;p&gt;First, let&#x27;s talk about Netstack3. Netstack3 is Fuchsia&#x27;s next-generation, pure-Rust networking stack. It aims to replace Netstack2, which is written in Go.&lt;&#x2F;p&gt;
&lt;p&gt;I started Netstack3 about six years ago, and led its development for four years, and then for the past two years it&#x27;s been led by a different team. I haven&#x27;t been on the project for two years, so obviously this is beyond me now – it&#x27;s a huge team effort – I&#x27;m going to be bragging a lot about those folks. There are some really good engineers who work on that now.&lt;&#x2F;p&gt;
&lt;p&gt;Writing a networking stack is a serious undertaking. It&#x27;s responsible for almost all network traffic in the entire operating system. It implements dozens of protocols, each of which is specified in documents that can run into the hundreds of pages. And it&#x27;s the first line of defense against any attacker who isn&#x27;t physically sitting in front of a device.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also just &lt;em&gt;big&lt;&#x2F;em&gt;. As I said a second ago, it&#x27;s taken us six years to get to this point, there have been plus or minus ten developers that whole time, and it&#x27;s split across 63 crates totaling 192,000 lines of code. That&#x27;s more code than the top ten crates on crates.io combined.&lt;&#x2F;p&gt;
&lt;p&gt;Over the past year, the team has been preparing to launch Netstack3. Those of you with networking backgrounds will know that you don&#x27;t &lt;em&gt;just&lt;&#x2F;em&gt; deploy networking code into production.&lt;&#x2F;p&gt;
&lt;p&gt;Networking code is famously difficult to test, and so you have to assume that, despite your best efforts, your code is riddled with bugs.&lt;&#x2F;p&gt;
&lt;p&gt;For a project of this scale — deploying an entirely new, ground-up rewrite of a netstack — you would expect to dogfood in the field for months or maybe even years before shipping to real users. In that time, you would expect to uncover tens to hundreds of bugs that you hadn&#x27;t seen during development. And only once you had burned down most of those bugs and seen relatively stable behavior for a while, only then would you finally deploy to real users.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s talk about what the process has looked like for Netstack3. For 11 months, the team has been ramping up a dogfooding program. At peak, that program has seen about 60 devices running nearly 24&#x2F;7 in developers&#x27; homes.&lt;&#x2F;p&gt;
&lt;p&gt;Again, if this were any other netstack, we would have expected to uncover a giant mountain of bugs in that time. So, over the past year, how many bugs did the team uncover in the field?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Three.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note from the future&lt;&#x2F;strong&gt;: As of posting, Netstack3 is now in production, running on millions of devices. Immediately after its first deployment, the team observed a ~20x lower rate of crashes per million devices per day and a 50% reduction in memory usage compared to its predecessor, Netstack2.&lt;&#x2F;p&gt;
&lt;p&gt;The three dogfooding bugs (actually four – the last observed failure was due to two separate bugs) were:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bugs.fuchsia.dev&#x2F;p&#x2F;fuchsia&#x2F;issues&#x2F;detail?id=419219829&quot;&gt;419219829&lt;&#x2F;a&gt;, fixed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fuchsia-review.googlesource.com&#x2F;c&#x2F;fuchsia&#x2F;+&#x2F;1282284&quot;&gt;1282284&lt;&#x2F;a&gt;: An operator-precedence mistake defined &lt;code&gt;WindowSize::MAX&lt;&#x2F;code&gt; as &lt;code&gt;1 &amp;lt;&amp;lt; (30 - 1)&lt;&#x2F;code&gt; rather than &lt;code&gt;(1 &amp;lt;&amp;lt; 30) - 1&lt;&#x2F;code&gt;. Netstack3 therefore imposed an artificially low TCP receive-window maximum and could panic on connections with windows above roughly 500 MB.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bugs.fuchsia.dev&#x2F;p&#x2F;fuchsia&#x2F;issues&#x2F;detail?id=420719068&quot;&gt;420719068&lt;&#x2F;a&gt;, fixed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fuchsia-review.googlesource.com&#x2F;c&#x2F;fuchsia&#x2F;+&#x2F;1286767&quot;&gt;1286767&lt;&#x2F;a&gt;: The DHCP client treated &lt;code&gt;ENOBUFS&lt;&#x2F;code&gt; as an impossible out-of-memory condition and panicked. On a packet socket, however, &lt;code&gt;ENOBUFS&lt;&#x2F;code&gt; can legitimately occur when the network device’s transmit queue is full.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bugs.fuchsia.dev&#x2F;p&#x2F;fuchsia&#x2F;issues&#x2F;detail?id=422307328&quot;&gt;422307328&lt;&#x2F;a&gt; was one observed failure caused by two bugs:
&lt;ul&gt;
&lt;li&gt;Fixed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fuchsia-review.googlesource.com&#x2F;c&#x2F;fuchsia&#x2F;+&#x2F;1334968&quot;&gt;1334968&lt;&#x2F;a&gt;: Netstack3 discarded IPv6 Neighbor Advertisements that omitted the Target Link-Layer Address option, even though RFC 4861 permits the omission in some unicast cases. This prevented otherwise valid reachability signals from updating the cached neighbor state.&lt;&#x2F;li&gt;
&lt;li&gt;Fixed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fuchsia-review.googlesource.com&#x2F;c&#x2F;fuchsia&#x2F;+&#x2F;1335018&quot;&gt;1335018&lt;&#x2F;a&gt;: Netstack3 propagated a Path-MTU error to TCP only when the error changed the PMTU cache. Repeated Packet Too Big or Fragmentation Required errors were therefore suppressed after the first cache update, preventing TCP from updating its MSS correctly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;So this talk is going to be something of a flashback.&lt;&#x2F;p&gt;
&lt;p&gt;Netstack3 was designed around a particular methodology for how to architect robust systems. Hopefully I&#x27;ve convinced you that we did at least &lt;em&gt;something&lt;&#x2F;em&gt; right on the robustness front.&lt;&#x2F;p&gt;
&lt;p&gt;In a sentence, that methodology says:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Buggy programs don&#x27;t compile.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Obviously, I am far from the first person to suggest this methodology. Here is just a small sample of crates that use this methodology somewhere in their APIs:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ghost-cell&lt;&#x2F;code&gt;, &lt;code&gt;session_types&lt;&#x2F;code&gt;, &lt;code&gt;nalgebra&lt;&#x2F;code&gt;, &lt;code&gt;mundane&lt;&#x2F;code&gt;, &lt;code&gt;indexing&lt;&#x2F;code&gt;, &lt;code&gt;zerocopy&lt;&#x2F;code&gt;, and &lt;code&gt;bytemuck&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And here is a small sample of what has been written on the topic, both about Rust and about other languages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;references-are-like-jumps&#x2F;&quot;&gt;References are like jumps&lt;&#x2F;a&gt;, by withoutboats&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lexi-lambda.github.io&#x2F;blog&#x2F;2019&#x2F;11&#x2F;05&#x2F;parse-don-t-validate&#x2F;&quot;&gt;Parse, don&#x27;t validate&lt;&#x2F;a&gt;, by Alexis King&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.parsonsmatt.org&#x2F;2017&#x2F;10&#x2F;11&#x2F;type_safety_back_and_forth.html&quot;&gt;Type Safety Back and Forth&lt;&#x2F;a&gt;, by Matt Parsons&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.iog.io&#x2F;papers&#x2F;ghosts-of-departed-proofs-functional-pearls&quot;&gt;Ghosts of Departed Proofs&lt;&#x2F;a&gt;, by Matt Noonan&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cliffle.com&#x2F;blog&#x2F;rust-typestate&#x2F;&quot;&gt;The Typestate Pattern in Rust&lt;&#x2F;a&gt;, by Cliff Biffle&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Kdpfhj3VM04&quot;&gt;Compiler-Driven Development in Rust&lt;&#x2F;a&gt;, by No Boilerplate&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;graydon2.dreamwidth.org&#x2F;312681.html&quot;&gt;Some notes on Rust, mutable aliasing and formal verification&lt;&#x2F;a&gt;, by Graydon Hoare&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So my goal for this talk is not to introduce a new idea.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, my goals are:&lt;&#x2F;p&gt;
&lt;p&gt;First, I&#x27;m going to propose a concrete but general framework that attempts to unify all of the different ways this methodology shows up in practice, and explain them in terms of the same basic concepts.&lt;&#x2F;p&gt;
&lt;p&gt;Second, I&#x27;m going to walk through two examples — one from the standard library and one from Netstack3 — and show how we can explain them in terms of this framework.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately 25 minutes isn&#x27;t enough time to present more than two examples in the depth I&#x27;d like. I had to leave a lot on the cutting-room floor when I was writing this talk. But I promise that these two examples only scratch the surface of what&#x27;s possible. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;joshlf&#x2F;65ccb20e034445a0fc6595f3a270653d&quot;&gt;full list of references&lt;&#x2F;a&gt; contains a surprising diversity of problems  which this methodology has already been applied to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-do-we-mean-by-buggy-programs-don-t-compile&quot;&gt;What do we mean by “buggy programs don&#x27;t compile”?&lt;&#x2F;h2&gt;
&lt;p&gt;On its website, Rust advertises three properties: performance, reliability, and productivity. Let&#x27;s zoom in on reliability.&lt;&#x2F;p&gt;
&lt;p&gt;The website says:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust&#x27;s rich type system and ownership model guarantee memory-safety and thread-safety.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In other words, out of the box, Rust guarantees that &quot;buggy programs don&#x27;t compile,&quot; but only if we restrict our definition of &quot;bug&quot; to memory bugs or threading bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong: memory safety and thread safety are huge on their own. For example, Netstack3 is able to pull all sorts of crazy buffer-sharing tricks in the name of performance that would be wildly dangerous in C or C++. I &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UfMOOxOGCmA&amp;amp;list=PLgC1L0fKd7UlpVTHVfLYVtudVx8CzbSxW&quot;&gt;gave a talk on those techniques&lt;&#x2F;a&gt; at Rust Belt Rust in 2018 if you&#x27;re curious about the details.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s only half the story.&lt;&#x2F;p&gt;
&lt;p&gt;Many critical bugs that we&#x27;d like to prevent are neither memory bugs nor threading bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Take TCP, for example. If you want to implement what &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;info&#x2F;rfc4614&quot;&gt;RFC 4614&lt;&#x2F;a&gt; refers to as &quot;basic functionality&quot; for TCP, you need to implement six different standards that run a combined 270 pages.&lt;&#x2F;p&gt;
&lt;p&gt;Add in the &quot;recommended enhancements&quot; and you&#x27;re up to a total of 18 standards spanning 476 pages.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s just one protocol. Add Ethernet, ARP, NDP, IPv4, IPv6, ICMP, IGMP, MLD, UDP, and a host of others, and all the subtle interactions between them, and you start to realize that memory and threading bugs are just the tip of the iceberg of all the fun and exciting ways that you could fuck it up.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why uncovering only three bugs in almost a year of dogfooding is so surprising. There&#x27;s just no way that memory safety or thread safety alone would get you that level of robustness.&lt;&#x2F;p&gt;
&lt;p&gt;So the points I&#x27;m trying to make are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Out of the box, Rust guarantees that &quot;buggy programs don&#x27;t compile&quot; only with respect to a small subset of the bugs we actually care about.&lt;&#x2F;li&gt;
&lt;li&gt;Netstack3 would not have been able to achieve the level of robustness that it has by relying only on what the language provides out of the box.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;However, what Netstack3 has done — and what I believe any project can do — is to extend the Rust language to guarantee freedom from &lt;em&gt;almost any class of bugs&lt;&#x2F;em&gt;, not just memory or threading bugs.&lt;&#x2F;p&gt;
&lt;p&gt;This is what I mean by &quot;X-safety&quot; in the talk&#x27;s abstract.&lt;&#x2F;p&gt;
&lt;p&gt;As it stands today, Rust provides a core set of abstractions — lifetimes, references, RAII, traits, etc — and guarantees various safety properties related to those abstractions.&lt;&#x2F;p&gt;
&lt;p&gt;But the majority of abstractions in the ecosystem are provided by libraries: JSON, random-number generators, cryptography, regular expressions, logging, time, TCP, PNG, SQL, command-line interfaces, linear algebra, browser APIs, and so on. Those libraries generally don&#x27;t provide the same degree of safety with respect to their abstractions that we might expect from the language.&lt;&#x2F;p&gt;
&lt;p&gt;But it doesn&#x27;t have to be that way.&lt;&#x2F;p&gt;
&lt;p&gt;As we&#x27;ll see in the following examples, Rust&#x27;s core abstractions alone are sufficient to express almost any safety property that we might care about. &lt;strong&gt;I claim that every library can and should provide the same level of safety with respect to its abstractions that we already expect of the language itself.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-general-framework-for-safety&quot;&gt;A general framework for safety&lt;&#x2F;h2&gt;
&lt;p&gt;To explain the framework, we&#x27;re going to turn to the humble binary tree:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For our binary tree to be correct, we of course need memory safety, but we need another safety property as well. We have to ensure that the tree is ordered: every value in the left subtree is less than our node&#x27;s value, and our node&#x27;s value is less than every value in the right subtree.&lt;&#x2F;p&gt;
&lt;p&gt;Rust can guarantee memory safety, but it has no visibility into this ordering requirement, and so it can&#x27;t enforce it for us. So how do we make sure that we never produce an invalidly-ordered tree?&lt;&#x2F;p&gt;
&lt;p&gt;We use the concept of an &lt;em&gt;invariant&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, we document an ordering invariant that we expect to always hold for any &lt;code&gt;Node&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; INVARIANT: All values in `left` are less than `value`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; INVARIANT: All values in `right` are greater than `value`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we ensure that every time we create a new &lt;code&gt;Node&lt;&#x2F;code&gt;, the ordering invariant holds:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Post-condition: `Node`&amp;#39;s internal field invariants hold.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Node&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            value,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, we ensure that every time we modify an existing &lt;code&gt;Node&lt;&#x2F;code&gt;, we preserve the ordering invariant, assuming it held to begin with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Pre-condition: `Node`&amp;#39;s internal field invariants hold.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Post-condition: `Node`&amp;#39;s internal field invariants hold.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;, value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now imagine that you are code outside of this module. (We&#x27;ll restrict ourselves here to safe code; obviously &lt;code&gt;unsafe&lt;&#x2F;code&gt; code can do whatever it wants.)&lt;&#x2F;p&gt;
&lt;p&gt;I claim that, from the perspective of safe code outside of this module, there is no difference whatsoever between the safety invariants provided by the language and the ordering invariant provided by this module.&lt;&#x2F;p&gt;
&lt;p&gt;If you write code which, if run, would violate Rust&#x27;s memory-safety guarantees, Rust guarantees that the code will not compile. By a similar token, if you write code outside this module which, if run, would violate the ordering invariant, then similarly Rust guarantees that the code will not compile.&lt;&#x2F;p&gt;
&lt;p&gt;In other words, by structuring our code in this way, we have in some sense &quot;taught&quot; Rust about a new safety property that it didn&#x27;t know about before.&lt;&#x2F;p&gt;
&lt;p&gt;We can use this &lt;code&gt;Node&lt;&#x2F;code&gt; example to explain the framework. It has three components.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;&#x2F;h3&gt;
&lt;p&gt;First, &lt;strong&gt;definition&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We define an object that the Rust type system can reason about. In this case, we define the &lt;code&gt;Node&lt;&#x2F;code&gt; struct. We attach to this object a safety property that Rust cannot reason about. In this case, that is the ordering property.&lt;&#x2F;p&gt;
&lt;p&gt;Because Rust can&#x27;t reason about this safety property, it&#x27;s up to us, as the authors of the abstraction, to make sure never to violate it. This brings us to the second component.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enforcement&quot;&gt;Enforcement&lt;&#x2F;h3&gt;
&lt;p&gt;Second, &lt;strong&gt;enforcement&lt;&#x2F;strong&gt;. Here, we enforce that our safety property is upheld – that responsibility is on us as the programmers.&lt;&#x2F;p&gt;
&lt;p&gt;In this case, we use field privacy – we make sure that our struct fields are private. If they were public, external code could modify them and violate our safety property.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we make sure that all the code &lt;em&gt;we&lt;&#x2F;em&gt; write preserves the safety property. In this case, the methods that modify the tree are responsible for maintaining its order.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;consumption&quot;&gt;Consumption&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, &lt;strong&gt;consumption&lt;&#x2F;strong&gt;. This is where we get the bang for our buck.&lt;&#x2F;p&gt;
&lt;p&gt;We write code that consumes the safety property as a precondition, and is only correct in virtue of that safety property being upheld. In this case, our methods can find the correct location in the tree for a particular value in &lt;code&gt;O(log N)&lt;&#x2F;code&gt; time, without having to traverse the entire tree.&lt;&#x2F;p&gt;
&lt;p&gt;That optimization is only valid because we are guaranteed that the tree is ordered. And the tree is only guaranteed to be ordered because we structured our code to &lt;strong&gt;define&lt;&#x2F;strong&gt; and &lt;strong&gt;enforce&lt;&#x2F;strong&gt; this ordering property so that we could later consume it as a precondition.&lt;&#x2F;p&gt;
&lt;p&gt;With that framework in mind, Let&#x27;s get to our first example.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-1-thread-safety&quot;&gt;Example 1: Thread safety&lt;&#x2F;h2&gt;
&lt;p&gt;Our first example is from the standard library and concerns thread safety.&lt;&#x2F;p&gt;
&lt;p&gt;What I&#x27;m going to demonstrate is that not only can libraries use the language&#x27;s core features to build new safety guarantees, but the standard library &lt;em&gt;itself&lt;&#x2F;em&gt; already uses this technique.&lt;&#x2F;p&gt;
&lt;p&gt;In fact, the thread safety that Rust advertises as one of its core features is not actually a language feature at all. It is implemented in the standard library and, in principle, could have been implemented in a third-party crate. It&#x27;s just convenient to have it in the standard library.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine that you&#x27;re writing &lt;code&gt;spawn&lt;&#x2F;code&gt;. &lt;code&gt;spawn&lt;&#x2F;code&gt; is a real function from the &lt;code&gt;thread&lt;&#x2F;code&gt; module in the standard library (although I&#x27;ve stripped down its signature for simplicity):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FnOnce&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;()&amp;gt;(f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It takes a function and spawns a new thread that will run that function.&lt;&#x2F;p&gt;
&lt;p&gt;If we think about how we might implement &lt;code&gt;spawn&lt;&#x2F;code&gt;, we immediately run into a limitation in the language: the Rust language itself doesn&#x27;t provide any mechanism to interact with threads. Threads are an operating system concept, and so creating a new thread requires going outside the language and making use of an API provided by the operating system itself.&lt;&#x2F;p&gt;
&lt;p&gt;For example, on a POSIX system, this might require calling &lt;code&gt;libc&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;pthread_create&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FnOnce&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;()&amp;gt;(f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pthread_create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is where we run into the first core abstraction that we&#x27;ll need to use as a building block.&lt;&#x2F;p&gt;
&lt;p&gt;Since &lt;code&gt;libc&lt;&#x2F;code&gt; functions like &lt;code&gt;pthread_create&lt;&#x2F;code&gt; are implemented outside the language, Rust has no visibility into their behavior, and so it has no way of guaranteeing that calling such a function won&#x27;t violate memory safety.&lt;&#x2F;p&gt;
&lt;p&gt;This is why Rust introduces the notion of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code. &lt;code&gt;unsafe&lt;&#x2F;code&gt; code is code that Rust can&#x27;t guarantee won&#x27;t violate memory safety. That doesn&#x27;t mean it definitely &lt;em&gt;will&lt;&#x2F;em&gt; violate memory safety. It just means that, on its own, Rust isn&#x27;t smart enough to prove that it won&#x27;t. Instead, Rust has to rely on the programmer to do the heavy lifting and confirm that the &lt;code&gt;unsafe&lt;&#x2F;code&gt; code is correct — or &lt;em&gt;sound&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is the purpose of an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block like the one above. Inside an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block, Rust gives the programmer free rein to perform operations that Rust can&#x27;t reason about. In exchange, the programmer takes responsibility for upholding memory safety. If they mess it up, all bets are off.&lt;&#x2F;p&gt;
&lt;p&gt;This is our first example of using a core abstraction to extend the power of the language. Rust itself provides &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions and &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks, but it doesn&#x27;t provide any mechanism for interacting with threads. However, by using &lt;code&gt;unsafe&lt;&#x2F;code&gt; in combination with external APIs like &lt;code&gt;pthread_create&lt;&#x2F;code&gt;, we can &quot;teach&quot; the language about threads.&lt;&#x2F;p&gt;
&lt;p&gt;As written, though, this implementation of &lt;code&gt;spawn&lt;&#x2F;code&gt; is unsound.&lt;&#x2F;p&gt;
&lt;p&gt;Not all values are thread-safe, meaning that not all values are sound to send between threads. Think of the difference between &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Arc.html&quot;&gt;&lt;code&gt;Arc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;rc&#x2F;struct.Rc.html&quot;&gt;&lt;code&gt;Rc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. As written, there&#x27;s nothing to stop you from passing a closure that captures some value that is not thread-safe.&lt;&#x2F;p&gt;
&lt;p&gt;So the standard library encodes the notion of thread safety in the type system.&lt;&#x2F;p&gt;
&lt;p&gt;First, we introduce a new trait called &lt;code&gt;Send&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; `Self` is thread-safe.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the standard-library &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Send.html&quot;&gt;&lt;code&gt;Send&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that you all know and love.&lt;&#x2F;p&gt;
&lt;p&gt;Note that &lt;code&gt;Send&lt;&#x2F;code&gt; is an &lt;code&gt;unsafe&lt;&#x2F;code&gt; trait. Just like &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions, &lt;code&gt;unsafe&lt;&#x2F;code&gt; traits tell the type system: &quot;This trait has safety implications that you can&#x27;t reason about.&quot; Just as calling an &lt;code&gt;unsafe&lt;&#x2F;code&gt; function can only happen inside an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block, implementing an &lt;code&gt;unsafe&lt;&#x2F;code&gt; trait requires an &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; block. The programmer must opt into taking responsibility for upholding memory safety.&lt;&#x2F;p&gt;
&lt;p&gt;Since the language can&#x27;t reason about the meaning of &lt;code&gt;Send&lt;&#x2F;code&gt; – it&#x27;s just an opaque trait with some name – we have to document its meaning in prose like we&#x27;ve done here. In this case, we say that a type can only be &lt;code&gt;Send&lt;&#x2F;code&gt; if it&#x27;s thread-safe.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we&#x27;ve introduced this trait, we can use it as a bound elsewhere in our program:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FnOnce&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;&amp;gt;(f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pthread_create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By requiring that &lt;code&gt;F&lt;&#x2F;code&gt; implement &lt;code&gt;Send&lt;&#x2F;code&gt;, we can make &lt;code&gt;spawn&lt;&#x2F;code&gt; sound. There&#x27;s no longer a risk that a programmer could accidentally call &lt;code&gt;spawn&lt;&#x2F;code&gt; with a non-thread-safe value, because that wouldn&#x27;t type-check.&lt;&#x2F;p&gt;
&lt;p&gt;So we&#x27;ve introduced this &lt;code&gt;Send&lt;&#x2F;code&gt; trait that encodes the notion of thread safety, but we haven&#x27;t actually implemented it for anything. Let&#x27;s do that.&lt;&#x2F;p&gt;
&lt;p&gt;First, we can implement &lt;code&gt;Send&lt;&#x2F;code&gt; for any built-in type that we know is always thread-safe:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From Rust&#x27;s perspective, this is axiomatic. Using these &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; blocks, we&#x27;ve declared by fiat that the &lt;code&gt;Send&lt;&#x2F;code&gt; property holds of these types.&lt;&#x2F;p&gt;
&lt;p&gt;Again, Rust has no way of knowing what &lt;code&gt;Send&lt;&#x2F;code&gt; means, and so it has no way of knowing whether these implementations are correct. It&#x27;s just taking our word for it.&lt;&#x2F;p&gt;
&lt;p&gt;We can also implement &lt;code&gt;Send&lt;&#x2F;code&gt; for more complex types. For example, a mutex is thread-safe by design, and so it&#x27;s okay to send mutex references between threads:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we can permit arbitrary composite types to implement &lt;code&gt;Send&lt;&#x2F;code&gt; by writing a custom derive:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Send&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, in reality, &lt;code&gt;Send&lt;&#x2F;code&gt; uses a special mechanism known as an &lt;em&gt;auto trait&lt;&#x2F;em&gt; to accomplish the same thing for ergonomics reasons. My point here is that there is no reason in principle that &lt;code&gt;Send&lt;&#x2F;code&gt; couldn&#x27;t have been developed as a library maintained by somebody other than the Rust project. Again, the core abstractions provided by the language are enough on their own to permit somebody to build an abstraction as powerful as &lt;code&gt;Send&lt;&#x2F;code&gt; outside the Rust language project itself&lt;&#x2F;p&gt;
&lt;p&gt;Sticking with the hypothetical, our custom derive would automatically emit an &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; block with the appropriate bounds. In particular, a type can be &lt;code&gt;Send&lt;&#x2F;code&gt; if all its fields are &lt;code&gt;Send&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Send&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; Derive-generated code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    U&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since &lt;code&gt;Send&lt;&#x2F;code&gt; is just a normal trait, once we&#x27;ve written our implementations, it works like any other trait:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; use `foo`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We know that this &lt;code&gt;Foo&lt;&#x2F;code&gt; type is &lt;code&gt;Send&lt;&#x2F;code&gt; because:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We derived &lt;code&gt;Send&lt;&#x2F;code&gt; for &lt;code&gt;Foo&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We manually implemented &lt;code&gt;Send&lt;&#x2F;code&gt; for &lt;code&gt;Mutex&lt;&#x2F;code&gt; references.&lt;&#x2F;li&gt;
&lt;li&gt;We manually implemented &lt;code&gt;Send&lt;&#x2F;code&gt; for primitive types.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;How does this example fit into our framework?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;definition-1&quot;&gt;Definition&lt;&#x2F;h3&gt;
&lt;p&gt;We define &lt;code&gt;Send&lt;&#x2F;code&gt;, teaching Rust about a new trait. We use prose to document that &lt;code&gt;Send&lt;&#x2F;code&gt; carries a special safety property that Rust can&#x27;t reason about: thread safety.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enforcement-1&quot;&gt;Enforcement&lt;&#x2F;h3&gt;
&lt;p&gt;We define &lt;code&gt;Send&lt;&#x2F;code&gt; as an unsafe trait so users can&#x27;t violate the safety property without writing the &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword.&lt;&#x2F;p&gt;
&lt;p&gt;We manually implement &lt;code&gt;Send&lt;&#x2F;code&gt; for types that we know satisfy the safety property.&lt;&#x2F;p&gt;
&lt;p&gt;And, in our hypothetical version, we write a custom derive that generates an implementation that guarantees thread safety by requiring every field to be &lt;code&gt;Send&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;consumption-1&quot;&gt;Consumption&lt;&#x2F;h3&gt;
&lt;p&gt;In &lt;code&gt;spawn&lt;&#x2F;code&gt;, we use a &lt;code&gt;Send&lt;&#x2F;code&gt; bound to justify that our internal call to &lt;code&gt;pthread_create&lt;&#x2F;code&gt; is sound.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s how Rust guarantees thread safety without any support from the language itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-2-deadlock-prevention&quot;&gt;Example 2: Deadlock prevention&lt;&#x2F;h2&gt;
&lt;p&gt;Our second example is about preventing deadlocks. This is work by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;akonradi&quot;&gt;Alex Konradi&lt;&#x2F;a&gt;, who was on the Netstack3 team at the time – I&#x27;m basically just bragging for him.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine you&#x27;re writing a netstack and you want to make your stack multithreaded. You care about performance, so instead of putting one mutex around all your state, you do fine-grained locking, using small mutexes around different pieces of state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Stack&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IpState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;DeviceState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As we saw in the previous example, Rust will guarantee that anything you do with these mutexes is thread-safe, but it won&#x27;t prevent you from deadlocking.&lt;&#x2F;p&gt;
&lt;p&gt;For example, imagine two different threads acquire these mutexes in different orders:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; Thread A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; Thread B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a classic deadlock scenario. If we&#x27;re unlucky, Thread A will successfully acquire the IP mutex and Thread B will successfully acquire the device mutex. Now, to make progress, they&#x27;re each blocked on the other.&lt;&#x2F;p&gt;
&lt;p&gt;You can conceptualize this as a graph of the locks we might want to acquire. All threads start in an &lt;code&gt;Unlocked&lt;&#x2F;code&gt; state, and can take different paths through the graph in order to acquire different locks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%%{init: {&amp;quot;theme&amp;quot;:&amp;quot;base&amp;quot;,&amp;quot;securityLevel&amp;quot;:&amp;quot;loose&amp;quot;,&amp;quot;flowchart&amp;quot;:{&amp;quot;htmlLabels&amp;quot;:true,&amp;quot;padding&amp;quot;:1,&amp;quot;diagramPadding&amp;quot;:0,&amp;quot;wrappingWidth&amp;quot;:520},&amp;quot;themeCSS&amp;quot;:&amp;quot;.diagram-box{stroke:none!important}.box-unlocked{fill:#e0e0e0!important}.box-ip{fill:#f2d4d3!important}.box-device{fill:#d3d2f5!important}.diagram-black{fill:none!important;stroke:#000!important;stroke-linecap:butt!important;stroke-linejoin:miter!important}.black-left{stroke-width:1.4px!important}.black-right{stroke-width:1.4px!important}.diagram-red{fill:none!important;stroke:#db3b26!important;stroke-width:2.8px!important;stroke-linecap:butt!important;stroke-linejoin:miter!important}.diagram-arrow{fill:#db3b26!important;stroke:none!important}.diagram-label{fill:#000!important;font-family:Liberation Mono,Menlo,Monaco,Consolas,Courier New,monospace!important;font-weight:400!important}.diagram-node-label{font-size:38px!important;letter-spacing:0.375px!important;stroke:#000!important;stroke-width:0.8px!important;paint-order:stroke fill!important}.diagram-thread-label{font-size:26.75px!important;letter-spacing:0.125px!important;stroke:#000!important;stroke-width:0.5px!important;paint-order:stroke fill!important}&amp;quot;}}%%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;flowchart TB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  canvas[&amp;quot;&amp;lt;svg xmlns=&amp;#39;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&amp;#39; width=&amp;#39;520&amp;#39; height=&amp;#39;399&amp;#39; viewBox=&amp;#39;0 0 586 450&amp;#39; style=&amp;#39;display:block&amp;#39;&amp;gt;&amp;lt;g transform=&amp;#39;translate(-2,-1)&amp;#39;&amp;gt;&amp;lt;rect class=&amp;#39;diagram-box box-unlocked&amp;#39; x=&amp;#39;197&amp;#39; y=&amp;#39;23&amp;#39; width=&amp;#39;198&amp;#39; height=&amp;#39;128&amp;#39;&#x2F;&amp;gt;&amp;lt;rect class=&amp;#39;diagram-box box-ip&amp;#39; x=&amp;#39;21&amp;#39; y=&amp;#39;240&amp;#39; width=&amp;#39;198&amp;#39; height=&amp;#39;198&amp;#39;&#x2F;&amp;gt;&amp;lt;rect class=&amp;#39;diagram-box box-device&amp;#39; x=&amp;#39;373&amp;#39; y=&amp;#39;240&amp;#39; width=&amp;#39;198&amp;#39; height=&amp;#39;198&amp;#39;&#x2F;&amp;gt;&amp;lt;line class=&amp;#39;diagram-red&amp;#39; x1=&amp;#39;127&amp;#39; y1=&amp;#39;307.6&amp;#39; x2=&amp;#39;365&amp;#39; y2=&amp;#39;307.6&amp;#39;&#x2F;&amp;gt;&amp;lt;polygon class=&amp;#39;diagram-arrow&amp;#39; points=&amp;#39;361.5,301.5 373,307.5 361.5,313.5&amp;#39;&#x2F;&amp;gt;&amp;lt;line class=&amp;#39;diagram-red&amp;#39; x1=&amp;#39;230&amp;#39; y1=&amp;#39;375&amp;#39; x2=&amp;#39;465&amp;#39; y2=&amp;#39;375&amp;#39;&#x2F;&amp;gt;&amp;lt;polygon class=&amp;#39;diagram-arrow&amp;#39; points=&amp;#39;231,369 219,375 231,381&amp;#39;&#x2F;&amp;gt;&amp;lt;path class=&amp;#39;diagram-black black-left&amp;#39; d=&amp;#39;M197 86.75 H127.25 V307.75&amp;#39;&#x2F;&amp;gt;&amp;lt;path class=&amp;#39;diagram-black black-right&amp;#39; d=&amp;#39;M395 86.75 H465 V376&amp;#39;&#x2F;&amp;gt;&amp;lt;text class=&amp;#39;diagram-label diagram-node-label&amp;#39; x=&amp;#39;295.75&amp;#39; y=&amp;#39;101&amp;#39; text-anchor=&amp;#39;middle&amp;#39;&amp;gt;Unlocked&amp;lt;&#x2F;text&amp;gt;&amp;lt;text class=&amp;#39;diagram-label diagram-node-label&amp;#39; x=&amp;#39;120.5&amp;#39; y=&amp;#39;352&amp;#39; text-anchor=&amp;#39;middle&amp;#39;&amp;gt;IP&amp;lt;&#x2F;text&amp;gt;&amp;lt;text class=&amp;#39;diagram-label diagram-node-label&amp;#39; x=&amp;#39;471.75&amp;#39; y=&amp;#39;353&amp;#39; text-anchor=&amp;#39;middle&amp;#39;&amp;gt;Device&amp;lt;&#x2F;text&amp;gt;&amp;lt;text class=&amp;#39;diagram-label diagram-thread-label&amp;#39; x=&amp;#39;295.5&amp;#39; y=&amp;#39;298&amp;#39; text-anchor=&amp;#39;middle&amp;#39;&amp;gt;Thread A&amp;lt;&#x2F;text&amp;gt;&amp;lt;text class=&amp;#39;diagram-label diagram-thread-label&amp;#39; x=&amp;#39;296.25&amp;#39; y=&amp;#39;401&amp;#39; text-anchor=&amp;#39;middle&amp;#39;&amp;gt;Thread B&amp;lt;&#x2F;text&amp;gt;&amp;lt;&#x2F;g&amp;gt;&amp;lt;&#x2F;svg&amp;gt;&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  style canvas fill:transparent,stroke:transparent,stroke-width:0px&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To avoid the risk of deadlocking, we need to make sure that this graph is acyclic. The two acquisition orders above form a cycle, so we need to remove at least one of those red edges.&lt;&#x2F;p&gt;
&lt;p&gt;This might seem like a fairly trivial problem in this tiny example. It&#x27;s pretty obvious from looking at the code that it might deadlock.&lt;&#x2F;p&gt;
&lt;p&gt;But Netstack3 has 77 different mutexes protecting all manner of different state spread across 192,000 lines of code. You can imagine that keeping track of the order in which you&#x27;re supposed to acquire mutexes in that environment would get pretty difficult pretty fast.&lt;&#x2F;p&gt;
&lt;p&gt;And indeed, Netstack2, its predecessor which is written in Go, has historically been plagued by deadlocks.&lt;&#x2F;p&gt;
&lt;p&gt;So the Netstack3 team decided to try to prevent deadlocks statically, at compile time. To do this, they needed a way to encode a lock-order graph in the type system and a way to ensure that code could only acquire locks consistent with that graph.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s see how they did it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;name-every-mutex&quot;&gt;Name every mutex&lt;&#x2F;h3&gt;
&lt;p&gt;The first step is to name each mutex:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    mtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    _marker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PhantomData&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This new &lt;code&gt;Mutex&lt;&#x2F;code&gt; type is identical to the standard-library mutex, except that it carries an extra type parameter used to identify the mutex.&lt;&#x2F;p&gt;
&lt;p&gt;Returning to our example, we define one type per mutex and use those types as names:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Stack&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IpLock&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;DeviceLock&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpLock&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceLock&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These types are never constructed at runtime. We only need them for type-system purposes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;encode-the-lock-order-graph&quot;&gt;Encode the lock-order graph&lt;&#x2F;h3&gt;
&lt;p&gt;Next, we define the &lt;code&gt;LockAfter&lt;&#x2F;code&gt; and &lt;code&gt;LockBefore&lt;&#x2F;code&gt; traits:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; No cycles!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockAfter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;M&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockBefore&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;M&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockAfter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockBefore&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These traits encode the lock-order graph. They&#x27;re &lt;code&gt;unsafe&lt;&#x2F;code&gt; to implement because the user has to promise not to introduce a lock-order graph with cycles. If they do, they violate our safety property.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we define a macro that implements these traits on behalf of a user:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;macro_rules! impl_lock_after&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;A&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ty&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ty)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; SAFETY: The blanket impl will cause any cycles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; to result in a blanket impl conflict, and thus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; won&amp;#39;t compile.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockAfter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for $&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;X&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockBefore&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockAfter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;X&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for $&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;impl_lock_after!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TransportLock&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpLock&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;impl_lock_after!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IpLock&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceLock&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the macro expansion adds a blanket implementation. Don&#x27;t worry about following the full logic here, but the consequence of that blanket implementation is important: if a user invokes the macro in a way that introduces cycles into the lock graph, those blanket implementations will conflict with one another.&lt;&#x2F;p&gt;
&lt;p&gt;Cyclic graphs therefore fail to compile.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;track-the-current-position-in-the-graph&quot;&gt;Track the current position in the graph&lt;&#x2F;h3&gt;
&lt;p&gt;Next, we define the notion of a &lt;em&gt;lock context&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PhantomData&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A &lt;code&gt;LockCtx&lt;&#x2F;code&gt; allows the type system to keep track of where in the lock graph you are at any given point in the source code. It is a zero-sized type, so it has no cost at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Using these building blocks, we can build a deadlock-proof locking API:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; lock&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;L&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;L&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;MutexGuard&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        L&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockBefore&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            LockCtx&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PhantomData&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s walk through the components of this signature one by one.&lt;&#x2F;p&gt;
&lt;p&gt;First, we require an existing &lt;code&gt;LockCtx&lt;&#x2F;code&gt;. Note that we borrow it mutably, which disables the &lt;code&gt;LockCtx&lt;&#x2F;code&gt; for further use until we&#x27;ve unlocked the mutex by dropping the &lt;code&gt;MutexGuard&lt;&#x2F;code&gt;. So long as we&#x27;re holding the mutex, that context is effectively unusable.&lt;&#x2F;p&gt;
&lt;p&gt;Second, we require that the existing &lt;code&gt;LockCtx&lt;&#x2F;code&gt; has a lock ID upstream of our lock ID in the graph. This prevents us from locking a mutex which we&#x27;ve already locked.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;L&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockBefore&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we return a new &lt;code&gt;LockCtx&lt;&#x2F;code&gt; that the caller can use to continue locking mutexes (recall that the original &lt;code&gt;LockCtx&lt;&#x2F;code&gt; is now unusable so long as the current mutex is held). This new &lt;code&gt;LockCtx&lt;&#x2F;code&gt; has our lock ID. So long as the returned &lt;code&gt;MutexGuard&lt;&#x2F;code&gt; exists — in other words, so long as this lock is held — this new &lt;code&gt;LockCtx&lt;&#x2F;code&gt; is the only usable lock context, and it only permits locking mutexes downstream of this one in the lock graph.&lt;&#x2F;p&gt;
&lt;p&gt;One last bit of boilerplate: to represent the root of any lock graph, we introduce the &lt;code&gt;Unlocked&lt;&#x2F;code&gt; type and permit anyone to construct a lock context that starts off unlocked:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Unlocked&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unlocked&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;    pub const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; UNLOCKED&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unlocked&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PhantomData&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;use-the-graph&quot;&gt;Use the graph&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s go back to our example and see how we can use this machinery to prevent deadlocks.&lt;&#x2F;p&gt;
&lt;p&gt;As we showed before, we introduce one type for each mutex and use the macro to encode our graph in the type system as implementations of &lt;code&gt;LockAfter&lt;&#x2F;code&gt; and &lt;code&gt;LockBefore&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Stack&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IpLock&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;DeviceLock&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpLock&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceLock&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;impl_lock_after!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unlocked&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpLock&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;impl_lock_after!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IpLock&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DeviceLock&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember that this code will only compile so long as the graph is free of cycles.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s walk through how we use this graph at runtime. First, we construct a new context that starts in the unlocked state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;UNLOCKED&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we lock our first mutex — the IP mutex. This generates a &lt;code&gt;MutexGuard&lt;&#x2F;code&gt; and a new &lt;code&gt;LockCtx&lt;&#x2F;code&gt; that shadows the old one:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (ip,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we repeat the same process to lock the device mutex:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (device,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting it together:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;UNLOCKED&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (ip,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (device,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now take a look at what happens if we try to violate the lock order. As before, we start in an unlocked state and directly lock the device mutex:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LockCtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;UNLOCKED&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (device,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On its own, that is fine. We haven&#x27;t introduced a cycle yet, so it compiles.&lt;&#x2F;p&gt;
&lt;p&gt;But if, having acquired the device mutex, we now try to acquire the IP mutex, that won&#x27;t compile, because there&#x27;s no path in the graph from the device mutex to the IP mutex:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; (ip,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stack&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;                                ^^^^^^^^ ERROR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How does this fit into our framework?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;definition-2&quot;&gt;Definition&lt;&#x2F;h3&gt;
&lt;p&gt;First, we define the &lt;code&gt;LockAfter&lt;&#x2F;code&gt; and &lt;code&gt;LockBefore&lt;&#x2F;code&gt; traits. We document in prose that they carry a safety property: they always encode an acyclic graph.&lt;&#x2F;p&gt;
&lt;p&gt;Second, we define the &lt;code&gt;Mutex&lt;&#x2F;code&gt; type. We document in prose that it carries a safety property: it is only locked consistent with a predefined lock-order graph.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enforcement-2&quot;&gt;Enforcement&lt;&#x2F;h3&gt;
&lt;p&gt;We make the &lt;code&gt;LockAfter&lt;&#x2F;code&gt; and &lt;code&gt;LockBefore&lt;&#x2F;code&gt; traits &lt;code&gt;unsafe&lt;&#x2F;code&gt; so that a user can only violate our safety property by writing the &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword.&lt;&#x2F;p&gt;
&lt;p&gt;We design &lt;code&gt;impl_lock_after!&lt;&#x2F;code&gt; so that it guarantees that only acyclic graphs can compile.&lt;&#x2F;p&gt;
&lt;p&gt;And we use a &lt;code&gt;LockBefore&lt;&#x2F;code&gt; bound to ensure that the &lt;code&gt;lock&lt;&#x2F;code&gt; method can only be called consistently with the lock-order graph.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;consumption-2&quot;&gt;Consumption&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;lock&lt;&#x2F;code&gt; method uses its &lt;code&gt;LockBefore&lt;&#x2F;code&gt; bound to justify that locking the inner mutex won&#x27;t deadlock.&lt;&#x2F;p&gt;
&lt;p&gt;What I have presented here is a simplified version of what exists in practice. There are actually two subtle ways that I&#x27;m aware of that you can violate deadlock safety using this simplified version. And there&#x27;s an interesting conversation to be had about whether safety properties like these should be literally impossible to circumvent, or whether they only need to be hard enough to circumvent that you could&#x27;t shoot yourself in the foot by accident.&lt;&#x2F;p&gt;
&lt;p&gt;In reality, the lock-ordering library takes the latter approach. I&#x27;m not going to get into that discussion here, and it doesn&#x27;t really affect the point I&#x27;m trying to make.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-results&quot;&gt;The results&lt;&#x2F;h2&gt;
&lt;p&gt;How has this played out for Netstack3?&lt;&#x2F;p&gt;
&lt;p&gt;In the beginning, Netstack3 was entirely single-threaded for simplicity. But over the past few years, the team has been working to thread mutexes and mutex guards through the entire stack. Finally, just a few weeks ago, they had finished that process and were ready to flip the switch — to go from running on one thread to running on multiple threads.&lt;&#x2F;p&gt;
&lt;p&gt;So they changed the default number of threads from one to four:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted z-markup z-deleted&quot;&gt;- Self(NonZeroU8::new(1).unwrap())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted z-markup z-inserted&quot;&gt;+ Self(NonZeroU8::new(4).unwrap())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fxrev.dev&#x2F;1102436&quot;&gt;That was the whole change&lt;&#x2F;a&gt;. It was bug-free on the first try.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;Those are my two examples.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d like to encourage you to try this methodology for yourself, and especially to bring it to new domains and new classes of bugs that nobody in the Rust community has tackled yet.&lt;&#x2F;p&gt;
&lt;p&gt;Let me give you a few pieces of concrete advice to help get you started.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;treat-partial-functions-as-a-code-smell&quot;&gt;Treat partial functions as a code smell&lt;&#x2F;h3&gt;
&lt;p&gt;On a practical note, think of partial functions in your API as a code smell.&lt;&#x2F;p&gt;
&lt;p&gt;Your public functions should never panic, and they usually shouldn&#x27;t return &lt;code&gt;Option&lt;&#x2F;code&gt; or &lt;code&gt;Result&lt;&#x2F;code&gt; unless that is inherent to the behavior you&#x27;re modeling.&lt;&#x2F;p&gt;
&lt;p&gt;Returning an error because an I&#x2F;O operation failed is unavoidable and totally fine. Returning an error because the caller passed an illegal value? That code shouldn&#x27;t have compiled in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;For great primers on this way of thinking, I recommend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lexi-lambda.github.io&#x2F;blog&#x2F;2019&#x2F;11&#x2F;05&#x2F;parse-don-t-validate&#x2F;&quot;&gt;Parse, don&#x27;t validate&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.parsonsmatt.org&#x2F;2017&#x2F;10&#x2F;11&#x2F;type_safety_back_and_forth.html&quot;&gt;Type Safety Back and Forth&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;make-your-apis-exactly-match-the-problem&quot;&gt;Make your APIs exactly match the problem&lt;&#x2F;h3&gt;
&lt;p&gt;Make your APIs exactly match the structure of the problem you&#x27;re modeling.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the error type that Netstack3 returns when it fails to parse an IP packet:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpParseError&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IcmpIpExt&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Parse&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ParseError&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ParameterProblem&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        src_ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Addr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        dst_ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Addr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        code&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ParameterProblemCode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        pointer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ParameterProblemPointer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        must_send_icmp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        header_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;HeaderLen&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        action&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpParseErrorAction&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpParseErrorAction&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    DiscardPacket&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    DiscardPacketSendIcmp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    DiscardPacketSendIcmpNoMulticast&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ParseError&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    NotSupported&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    NotExpected&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Checksum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Format&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This may seem surprisingly convoluted, but it is a faithful representation of the complexity of both the IPv4 and IPv6 protocols. To do anything simpler would cause us problems down the line.&lt;&#x2F;p&gt;
&lt;p&gt;For example, let&#x27;s zoom in on the &lt;em&gt;parameter problem pointer&lt;&#x2F;em&gt; field.&lt;&#x2F;p&gt;
&lt;p&gt;If you receive a malformed packet, you have to respond with your own packet containing an error message. That error message identifies the byte offset of the malformed field that caused parsing to fail. That byte offset is known as the &quot;parameter problem pointer&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Note the generic type here. In IPv4, the field in the error message that stores this pointer is one byte long. In IPv6, it&#x27;s four bytes long. Using generics ensures that we always store the byte offset using the right size of integer.&lt;&#x2F;p&gt;
&lt;p&gt;If instead we uniformly stored the pointer as, for example, a &lt;code&gt;u32&lt;&#x2F;code&gt;, we would have to perform a fallible conversion elsewhere in the codebase. If we had a bug, that conversion would either silently produce incorrect error packets or panic and crash the stack.&lt;&#x2F;p&gt;
&lt;p&gt;By ensuring that our error type faithfully models the behavior of IPv4 and IPv6, we can make that sort of bug impossible.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;expect-diverse-solutions&quot;&gt;Expect diverse solutions&lt;&#x2F;h3&gt;
&lt;p&gt;Don&#x27;t expect the solution to always be the same.&lt;&#x2F;p&gt;
&lt;p&gt;Just because the catchphrase is always that &quot;buggy programs don&#x27;t compile&quot; doesn&#x27;t mean that there&#x27;s a recipe. In my experience, different problems call for wildly different solutions that leverage a hodgepodge of language features.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;simplicity-is-the-art-of-hiding-complexity&quot;&gt;Simplicity is the art of hiding complexity&lt;&#x2F;h3&gt;
&lt;p&gt;Don&#x27;t expect it to always fall out naturally.&lt;&#x2F;p&gt;
&lt;p&gt;One of my favorite quotes is from Rob Pike, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;talks&#x2F;2015&#x2F;simplicity-is-complicated.slide#18&quot;&gt;talking about Go&#x27;s design&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Simplicity is the art of hiding complexity.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Your responsibility is to do the hard work so that your users have a simple mental model of your API and they don&#x27;t have to understand how awful the internals of your library are.&lt;&#x2F;p&gt;
&lt;p&gt;Rust wasn&#x27;t explicitly designed to support this methodology, at least not in its full generality, and you may have to really bend the language to your will.&lt;&#x2F;p&gt;
&lt;p&gt;For example, if you haven&#x27;t seen the trick, it is not at all obvious that it would be possible to prevent graph cycles using the trait system. The internals of the lock-ordering library are kind of ugly as a result, but the mental model that a user needs in order to reason about the API is very simple:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cyclic graphs don&#x27;t compile.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That&#x27;s it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;turtles-all-the-way-down&quot;&gt;Turtles all the way down&lt;&#x2F;h3&gt;
&lt;p&gt;When it comes to your internal APIs, use the same level of discipline and rigor that you would use with a public API.&lt;&#x2F;p&gt;
&lt;p&gt;If a function has safety requirements, make it an &lt;code&gt;unsafe&lt;&#x2F;code&gt; function. If a function can panic, document it clearly.&lt;&#x2F;p&gt;
&lt;p&gt;It may seem obvious in the moment how to call an internal API correctly, but it won&#x27;t be so obvious to the new developer on the team four years and six refactors from now. If you keep up this discipline, then no matter how much time passes, your internal APIs will be just as easy to use correctly as the day you wrote them.&lt;&#x2F;p&gt;
&lt;p&gt;We adhered to this discipline strictly in Netstack3, and the larger the project grew, the more it paid off.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-bit-of-speculation&quot;&gt;A bit of speculation&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#x27;re late in the podcast now, so we can let our hair down a bit and speculate.&lt;&#x2F;p&gt;
&lt;p&gt;– Sean Carroll&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Finally, if you&#x27;ll permit me a bit of speculation, I think this methodology has the potential to fundamentally reshape how we engage in the process of software engineering, and I think that so far we&#x27;ve only scratched the surface of how far we can push it.&lt;&#x2F;p&gt;
&lt;p&gt;One reason is that there are domains where correctness is a much bigger deal than it is for most of us in this room. Rust is only just starting to make inroads into high-assurance domains like automotive, aerospace, medical devices, and so on. Those are domains where bugs are so unacceptable that the pace of development is absolutely glacial.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not suggesting that we&#x27;re going to be able to stop doing code reviews or anything crazy like that. But imagine how much faster we could move if we eliminated entire classes of bugs that we normally have to catch through reviews or testing.&lt;&#x2F;p&gt;
&lt;p&gt;Another reason I think this methodology could be a big deal is that it allows software to scale more effectively.&lt;&#x2F;p&gt;
&lt;p&gt;Software complexity often scales superlinearly as a function of the size of the codebase, and much of that complexity is incidental rather than inherent. Humans only have so much mental capacity. As incidental complexity increases, it crowds out our ability to reason about the inherent complexity that we&#x27;re actually interested in. That puts a natural upper limit on the inherent complexity of the problems we can tackle.&lt;&#x2F;p&gt;
&lt;p&gt;My guess is that this methodology stands to make the biggest difference in large, complex codebases, where small savings in complexity across every module compound on one another.&lt;&#x2F;p&gt;
&lt;p&gt;That has certainly been our experience in Netstack3.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;As I mentioned at the beginning, I wasn&#x27;t able to provide nearly as many examples as I would have liked. I strongly encourage you to check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;joshlf&#x2F;65ccb20e034445a0fc6595f3a270653d&quot;&gt;references&lt;&#x2F;a&gt; and do more reading on your own.&lt;&#x2F;p&gt;
&lt;p&gt;I really believe that, thanks to Rust, we have the opportunity to fundamentally improve the state of software engineering, and I intend to spend the next phase of my career proving it.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you&#x27;ll join me. Thank you.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>I May Have Been Targeted by a Spear Phishing Attack</title>
    <published>2026-06-26T00:00:00+00:00</published>
    <updated>2026-06-26T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/spear-phishing/"/>
    <id>https://joshlf.com/posts/spear-phishing/</id>
    
      
    <category term="Rust"/>
      
    <category term="Security"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/spear-phishing/">&lt;p&gt;Matthew Mastracci &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grack.com&#x2F;blog&#x2F;2026&#x2F;06&#x2F;25&#x2F;dissecting-a-failed-nation-state-attack&#x2F;&quot;&gt;recently published&lt;&#x2F;a&gt; a writeup of an apparent targeted supply-chain attack against Rust maintainers. This was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1ug9pzn&#x2F;anatomy_of_a_failed_nationstate_attack&#x2F;&quot;&gt;posted&lt;&#x2F;a&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;&quot;&gt;r&#x2F;rust&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I was one of the maintainers who received similar outreach. In my case, I assume the target was my maintainer access to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;zerocopy&quot;&gt;zerocopy&lt;&#x2F;a&gt;. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grack.com&#x2F;blog&#x2F;2026&#x2F;06&#x2F;25&#x2F;dissecting-a-failed-nation-state-attack&#x2F;#what-it-drops&quot;&gt;According to Matthew&lt;&#x2F;a&gt;, the payload he received was a remote access trojan (RAT):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The drop is a full remote-access trojan that seems to have been put together by someone who knows what they are doing. It sets up an RSA key locally and uses AES-256-CBC as a session key.&lt;&#x2F;p&gt;
&lt;p&gt;On startup it calls a checkin routine that harvests and exfiltrates a host fingerprint:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;primary IP address (enumerates all non-internal interfaces), plus all IPs&lt;&#x2F;li&gt;
&lt;li&gt;username (&lt;code&gt;os.userInfo().username&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;hostname&lt;&#x2F;li&gt;
&lt;li&gt;OS type + release + platform + architecture&lt;&#x2F;li&gt;
&lt;li&gt;process PID and full &lt;code&gt;process.argv&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Node version&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It generates an RSA-2048 keypair and a random AES-256 session key (aes_psk), then all subsequent traffic is AES-256-CBC encrypted with an HMAC-SHA256 integrity tag.&lt;&#x2F;p&gt;
&lt;p&gt;It supports the following commands:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;env&lt;&#x2F;code&gt; — &lt;code&gt;JSON.stringify(process.env)&lt;&#x2F;code&gt; dumped and sent back.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;upload&lt;&#x2F;code&gt; — reads an arbitrary file path and exfiltrates it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;download&lt;&#x2F;code&gt; — writes attacker-supplied bytes to any writable path.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;spawn&lt;&#x2F;code&gt; — runs an arbitrary process with optional shell expansion.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;cd&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;pwd&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;cp&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;mv&lt;&#x2F;code&gt; — general filesystem primitives.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dns&lt;&#x2F;code&gt; — makes the host resolve arbitrary names through a specified resolver (for DNS tunneling?).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dismantle&lt;&#x2F;code&gt; — self-removal.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here are the emails I received:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;spear-phishing&#x2F;screenshot1.png&quot; alt=&quot;Email screenshot 1&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;spear-phishing&#x2F;screenshot2.png&quot; alt=&quot;Email screenshot 2&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;spear-phishing&#x2F;screenshot3.png&quot; alt=&quot;Email screenshot 3&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;spear-phishing&#x2F;screenshot4.png&quot; alt=&quot;Email screenshot 4&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The approach was professionally plausible: someone claiming to represent a VC firm reached out about (presumably paid) technical diligence&#x2F;consulting. While in my case the conversation petered out before moving beyond email, other targets were eventually directed toward a software project which, as Matthew&#x27;s post describes, contained malicious code.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know who was behind this, and I don&#x27;t have independent evidence for attribution. But it appears to have been a coordinated attempt to compromise the maintainers of widely-used Rust crates. A similar attack – presumably carried out by the same actors – is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;posts&#x2F;piyush-shukla-44b7a11b1_yesterday-i-came-across-one-of-the-most-ugcPost-7422893062072328192-bz7d&#x2F;&quot;&gt;described by&lt;&#x2F;a&gt; Piyush Shukla roughly four months before Matthew&#x27;s post. Piyush was himself the target; he works in the cryptocurrency space, so this may go beyond just Rust.&lt;&#x2F;p&gt;
&lt;p&gt;This post is just to add my data point to the public record: maintainers of high-impact open-source Rust projects are being targeted through ordinary-looking professional outreach.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>The Coming Programming Language Renaissance</title>
    <published>2026-06-08T00:00:00+00:00</published>
    <updated>2026-06-08T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/pl-renaissance/"/>
    <id>https://joshlf.com/posts/pl-renaissance/</id>
    
      
    
    <content type="html" xml:base="https://joshlf.com/posts/pl-renaissance/">&lt;p&gt;For decades, programming language researchers have invented ways to make programs more explicit, more checkable, more constrained, more secure, and more verifiable. Refinement types. Dependent types. Effect systems. Session types. Typestate. Linear types. Contracts. Capabilities. Model checking. Proof assistants. Program synthesis. Typed holes. Semantic editing.&lt;&#x2F;p&gt;
&lt;p&gt;While watered-down versions of some of these have occasionally made it out of the academy (&quot;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Rust_(programming_language)#2006.E2.80.932009:_Early_years&quot;&gt;technology from the past come to save the future from itself&lt;&#x2F;a&gt;&quot;), these are the exceptions that prove the rule. For the most part, what we know how to do &lt;em&gt;in theory&lt;&#x2F;em&gt; makes our industrial practice look like it&#x27;s stuck in the stone age.&lt;&#x2F;p&gt;
&lt;p&gt;Some powerful programming language research directions are hamstrung by fundamental constraints like computability, but my sense is that most of what stops great programming language ideas from escaping the academy are human factors constraints. Human cognition is weird and, in many ways, &lt;em&gt;extremely&lt;&#x2F;em&gt; limited. Empirical work shows, for example, that even apparently superficial language syntax choices can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.vidarholen.net&#x2F;~vidar&#x2F;An_Empirical_Investigation_into_Programming_Language_Syntax.pdf&quot;&gt;materially affect programmer accuracy and learning&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Coding agents, on the other hand, have few of the same limitations. Research already shows that they excel where humans struggle, benefiting from their ability to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2606.01522&quot;&gt;read verbose error messages&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ranjitjhala.github.io&#x2F;static&#x2F;icse25-neurosymbolic-refinement-inference.pdf&quot;&gt;author precise specifications&lt;&#x2F;a&gt;, and tolerate the iteration required to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;abs&#x2F;10.1145&#x2F;3763174&quot;&gt;generate valid proofs of program correctness&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve been here before. In the 1930s and 1940s, between the Great Depression suppressing demand for new technology, wartime secrecy requirements preventing discoveries from being made public,&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-secrecy-1&quot;&gt;&lt;a href=&quot;#fn-secrecy&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and military demand driving increased R&amp;amp;D spending, a huge backlog of research built up. Some economists have suggested that America&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Mh5LY4Mz15o&amp;amp;t=524s&quot;&gt;postwar economic miracle&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-pwem-1&quot;&gt;&lt;a href=&quot;#fn-pwem&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; – which brought us innovations from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.si.edu&#x2F;collections&#x2F;snapshot&#x2F;microwave-oven&quot;&gt;microwave&lt;&#x2F;a&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.britannica.com&#x2F;technology&#x2F;history-of-flight&#x2F;The-jet-age&quot;&gt;commercial aviation&lt;&#x2F;a&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acs.org&#x2F;education&#x2F;whatischemistry&#x2F;landmarks&#x2F;flemingpenicillin.html&quot;&gt;mass-market penicillin&lt;&#x2F;a&gt; – was in part the natural consequence of corporations simply &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;andrewjfieldhouse.com&#x2F;wp-content&#x2F;uploads&#x2F;2024&#x2F;11&#x2F;The_Return_to_Government_R_D_revised_manuscript.pdf&quot;&gt;working through this research backlog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Programming language development in 2026 looks very similar. Decades of theoretical innovation have built up in the academy due to human limitations that are about to be lifted en masse at exactly the time when demand for the &lt;em&gt;production&lt;&#x2F;em&gt; of new programming artifacts is skyrocketing.&lt;&#x2F;p&gt;
&lt;p&gt;Concretely, I predict that agentic programming will lead to a renaissance in programming language design. Language designers, faced with a fundamentally new type of user, suddenly have decades of theoretical research to draw from in designing new, powerful language features uniquely suited to the strengths of coding agents. Whether innovation takes the form of new language features in existing languages, DSLs, entirely new languages, or even a reimagining of what counts as a programming language, change is coming.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-secrecy&quot;&gt;
&lt;p&gt;During WWII, the USPTO placed &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ideas.repec.org&#x2F;a&#x2F;inm&#x2F;ormnsc&#x2F;v69y2023i4p2318-2338.html&quot;&gt;more than 11,000 patent applications&lt;&#x2F;a&gt; under secrecy orders, then rescinded them en masse after the war. &lt;a href=&quot;#fr-secrecy-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-pwem&quot;&gt;
&lt;p&gt;That video is about Japan, but the reference was too good to resist. &lt;a href=&quot;#fr-pwem-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Memory Safety Is a Matter of Life and Death</title>
    <published>2026-06-02T00:00:00+00:00</published>
    <updated>2026-06-02T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/memory-safety-life-and-death/"/>
    <id>https://joshlf.com/posts/memory-safety-life-and-death/</id>
    
      
    
    <content type="html" xml:base="https://joshlf.com/posts/memory-safety-life-and-death/">&lt;p&gt;In 2018, Saudi journalist Jamal Khashoggi&#x27;s fiancée&#x27;s phone was hacked. Later that year, Khashoggi walked into the Saudi Arabian consulate in Istanbul to obtain documents related to his planned marriage, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.boston25news.com&#x2F;news&#x2F;national&#x2F;journalist-jamal-khashoggis-disappearance-a-timeline-of-events&#x2F;854679184&#x2F;&quot;&gt;left two hours later&lt;&#x2F;a&gt; in a body bag.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s easy to forget that the work we do affects real people. It&#x27;s easy to feel, if only unconsciously, that the &lt;em&gt;point&lt;&#x2F;em&gt; of programming is to be mathematically beautiful or fun to use. It&#x27;s easy to forget that buffer overflows aren&#x27;t just bad in the abstract, but that sometimes, they get real people killed.&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s about to get much, &lt;em&gt;much&lt;&#x2F;em&gt; worse.&lt;&#x2F;p&gt;
&lt;p&gt;In my day job, I work on a security team, so I have access to hard data and water cooler talk with colleagues at Google and elsewhere about agentic bug-finding models, which are behind what the security industry has coined the &quot;vulnpocalypse&quot;. For the past few weeks, I&#x27;ve been repeatedly asked the same question: &quot;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;glasswing&quot;&gt;Mythos&lt;&#x2F;a&gt;. Is it really &lt;em&gt;that&lt;&#x2F;em&gt; bad?&quot; In a word: Yes.&lt;&#x2F;p&gt;
&lt;p&gt;The point of this post isn&#x27;t to adjudicate this claim, so in leiu of a serious argument, I&#x27;ll just leave you with this graph &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hacks.mozilla.org&#x2F;2026&#x2F;05&#x2F;behind-the-scenes-hardening-firefox&#x2F;&quot;&gt;courtesy of Firefox&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;firefox-security-bug-fixes-2026.png&quot; alt=&quot;Firefox security bug fixes by month&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Many factors will determine the long-term equillibrium of vulnerability discovery,&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; but that equillibrium will take many years to reach. Regardless of how that plays out in the long term, the medium term impact is clear: memory-unsafe&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; open-source&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; software is not ready for high-quality bug-finding agents to be made widely available. It is expected that broad availability will happen at some point this summer,&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and when it does, few open source programs written in memory-unsafe languages will be safe from catastrophic exploits. Many actors will use these exploits to steal identities, or steal money, or commit other run-of-the-mill cyber crimes. But some will use these exploits to kill people.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; I am not being hyperbolic when I say that when these agents are made available, more people will die.&lt;&#x2F;p&gt;
&lt;p&gt;While memory safe languages are not a panacea, they will prevent the majority of these vulnerabilities (a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;msrc&#x2F;blog&#x2F;2019&#x2F;07&#x2F;a-proactive-approach-to-more-secure-code&quot;&gt;typical estimate&lt;&#x2F;a&gt; is 70%), and they will prevent the highest-impact of these vulnerabilities.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;strong&gt;This makes switching to memory safe languages a moral imperative.&lt;&#x2F;strong&gt; Alternatives such as Carbon are being developed, and other languages with different performance characteristics like Go or Java exist. However, when it comes to memory safe languages which are &lt;em&gt;already in production&lt;&#x2F;em&gt; and which impose &lt;em&gt;no overhead relative to C or C++&lt;&#x2F;em&gt;,&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Rust is the only option. Therefore, it is a moral imperative: Rust must succeed.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I am honored to call many people in the Rust community some of my closest friends. I have heard their stories at conferences, and over drinks, and on Zulip threads and Jitsi meetings. We have come to Rust for many different reasons (although they usually involve some form of nerd sniping). While the community has had its struggles, as any open source community does, it has always been an absolute blast – in our better moments, we have been kind to each other and written amazing software. To paraphrase Scott McNealy, we have &quot;kicked butt, had fun, and changed computing forever.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t see why we can&#x27;t keep having fun with Rust for the rest of our lives. But at the same time, we must acknowledge a hard truth: of the billions of people our software touches, only a tiny fraction know what a pointer is. To these people, it&#x27;s irrelevant whether Rust is beautiful or fun. But for some of these people, if Rust doesn&#x27;t succeed, they will die.&lt;&#x2F;p&gt;
&lt;p&gt;My dad and sister are both doctors, and I&#x27;ve always admired how they show up to work every day and face the weight of real, life-and-death consequences. The connection between their work and the lives of real people is immediate. One contrast that I&#x27;ve seen between their industry and our own is how they measure what is important.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine that your parent had a worrisome lump on an annual physical and went to the radiologist to get it checked out. Imagine that the radiologist could choose a highly-accurate imaging technology, but instead they chose one with a high false-negative rate. You would be furious that this radiologist was jeopardizing your parent&#x27;s life, and it wouldn&#x27;t make you feel any better if the radiologist tried to reassure you that the technology they chose used a cleverer design, or had a better user interface, or made them feel nostalgic for when they were in med school. The radiologist&#x27;s job is to treat your parent, and everything else is secondary.&lt;&#x2F;p&gt;
&lt;p&gt;Whatever the reason we each got into Rust, and whatever keeps us going, we have a new responsibility that most of us never asked for: people are now depending on us for their survival. They depend on Rust being secure. But more importantly, since Rust is already the most secure systems language in existence, they depend on Rust succeeding.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I wrote this post as a celebration that we have built a language so secure that people&#x27;s lives depend on projects choosing it. We should be &lt;em&gt;immensely&lt;&#x2F;em&gt; proud of what we&#x27;ve accomplished.&lt;&#x2F;p&gt;
&lt;p&gt;But I also wrote it as a call to arms. Now more than ever, it is important that Rust succeed. In the coming months and years, we will need to make hard choices. We cannot be all things to all people. We will need to prioritize some use cases over others. We must think of progress and consensus as virtues in and of themselves. We must learn to recognize when having &lt;em&gt;a&lt;&#x2F;em&gt; consensus is more important than having &lt;em&gt;the right&lt;&#x2F;em&gt; consensus, and in these cases, to pick progress over stagnation. Whether it&#x27;s C++ interop, or auditability, or any other un-glamorous feature which will nonetheless increase Rust adoption, we will have to hold our noses, wade into the muck, and get the work done.&lt;&#x2F;p&gt;
&lt;p&gt;I want to keep having fun, and thinking deep thoughts, and writing great code. I don&#x27;t want to give up what has made Rust a joy to participate in.&lt;&#x2F;p&gt;
&lt;p&gt;But I also don&#x27;t want people to die. If that means having a little less fun and being a little more serious, then I believe in our community&#x27;s ability to rise to the occasion.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;The exact chain of events is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Jamal_Khashoggi&quot;&gt;complicated&lt;&#x2F;a&gt;, with the intelligence services of multiple countries targeting multiple people close to Khashoggi for surveillance, both before and after his murder. Publicly-available information is insufficient to prove that Khashoggi would not have been murdered had certain hacking attempts been unsuccessful. However, many other examples, such as the ransomware attack against Synnovis in 2024 and the WannaCry malware in 2017, demonstrate that hacking often leads directly or indirectly to the deaths of innocent people.&lt;&#x2F;p&gt;
&lt;p&gt;I chose to open with the Khashoggi example as it makes the moral obligation that I talk about in the rest of this article very clear. However, if you want to read this article with a less emotional and more analytical mindset, replace &quot;this one person was brutally murdered thanks to a memory safety bug&quot; with &quot;in expectation, many people are injured, killed, or otherwise harmed thanks to memory safety bugs, although it&#x27;s usually difficult to attribute a single incident to a particular bug.&quot; Beyond physical harm from nation state actors, estimates of the economic damage of cyber crime range from $100B to $1T annually. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;If you had asked someone in 1995, &quot;what will be the long-term social consequences of the proliferation of cellular phones,&quot; nobody would have answered, &quot;we will see a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jamanetwork.com&#x2F;journals&#x2F;jamanetworkopen&#x2F;fullarticle&#x2F;2733430&quot;&gt;rapid rise in the suicide rate&lt;&#x2F;a&gt; among teen girls.&quot; Anyone who tells you they know how this will play out is wrong (or lying).&lt;&#x2F;p&gt;
&lt;p&gt;To be less glib, some people have argued that the long-term effect of high-quality bug-finding agents will be to make software &lt;em&gt;more&lt;&#x2F;em&gt; secure, as teams will use them to catch potential vulnerabilities before they are merged. This is a real possibility, but so is the opposite, and in any case it may take a long time reach any equillibrium. The point of this article isn&#x27;t to argue that we can predict any particular outcome, but rather that we have to consider that catastrophic outcomes are sufficiently probable to be worth worrying about and preparing for. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;While memory safe languages are not free from vulnerabilities, they are generally free from &lt;em&gt;memory safety&lt;&#x2F;em&gt; vulnerabilities. Non-memory safety vulnerabilities tend to permit exploits which are significantly less impactful than the exploits permitted by their memory safety-related counterparts. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;red.anthropic.com&#x2F;2026&#x2F;mythos-preview&#x2F;&quot;&gt;have suggested&lt;&#x2F;a&gt; that agents are good enough at binary analysis that even closed-source software won&#x27;t be safe – as long as an agent can inspect the binary, it can find vulnerabilities. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Specifically, it is expected that Mythos itself or equivalently powerful models will become available for public use. In fact, ChatGPT 5.5, which is available to the public, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.aisi.gov.uk&#x2F;blog&#x2F;our-evaluation-of-openais-gpt-5-5-cyber-capabilities&quot;&gt;may already match Mythos in capability&lt;&#x2F;a&gt;. While such models may have guardrails, these usually only pose a serious impediment to casual users, while serious actors are usually able to find ways to bypass them. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;More accurately, they will use these exploits to steal information which will allow them to kill people. &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;security.googleblog.com&#x2F;2022&#x2F;12&#x2F;memory-safe-languages-in-android-13.html&quot;&gt;Per Android&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Memory safety vulnerabilities disproportionately represent our most severe vulnerabilities. In 2022, despite only representing 36% of vulnerabilities in the security bulletin, memory-safety vulnerabilities accounted for 86% of our critical severity security vulnerabilities, our highest rating, and 89% of our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;source.android.com&#x2F;docs&#x2F;security&#x2F;overview&#x2F;updates-resources#local-vs-remote&quot;&gt;remotely exploitable&lt;&#x2F;a&gt; vulnerabilities. Over the past few years, memory safety vulnerabilities have accounted for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;spreadsheets&#x2F;d&#x2F;1lkNJ0uQwbeC1ZTRrxdtuPLCIl7mlUreoKfSIgajnSyY&#x2F;edit#gid=1190662839&quot;&gt;78% of confirmed exploited “in-the-wild”&lt;&#x2F;a&gt; vulnerabilities on Android devices.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
 &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;...which is a non-negotiable for many teams when switching languages. &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
  </entry>
    
  
    
    
  
    
    
  <entry xml:lang="en">
    <title>How to Run When You&#x27;re Not Being Chased</title>
    <published>2026-05-18T00:00:00+00:00</published>
    <updated>2026-05-18T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/how-to-run/"/>
    <id>https://joshlf.com/posts/how-to-run/</id>
    
      
    <category term="Mental Health"/>
      
    <category term="Career"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/how-to-run/">&lt;p&gt;Have you heard this one before?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I obviously don&#x27;t &lt;em&gt;like&lt;&#x2F;em&gt; being anxious, but it&#x27;s how I drive myself. If I (meditated &#x2F; went to therapy &#x2F; got on anti-anxiety meds &#x2F; etc), I would lose my edge.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;ve had multiple close friends use some form of this argument to justify why they avoid working on their mental health: that their demons (anxiety or anything else) fuel their success, and that they couldn&#x27;t succeed without them. Even if we grant that &quot;keeping your edge&quot; is a worthwhile goal, in my experience this argument doesn&#x27;t hold up &lt;em&gt;factually&lt;&#x2F;em&gt;. The reality is instead:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In childhood, your demons &lt;em&gt;did&lt;&#x2F;em&gt; shape your ability to be successful, but that&#x27;s done. As an adult:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;They&#x27;re not helping anymore.&lt;&#x2F;li&gt;
&lt;li&gt;They&#x27;re actively holding you back.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I once heard someone articulate the argument succintly:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Imagine that you had schizophrena, and that you frequently hallucinated being chased by monsters. As a result, you spent a lot of time running away from these monsters. What would happen after you got treatment, stopped hallucinating the monsters, and stopped needing to run? &lt;strong&gt;You&#x27;d still be in great cardio shape.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The problem with the &quot;my demons give me my edge&quot; perspective is that it fails to distinguish between &lt;em&gt;developing&lt;&#x2F;em&gt; skills and &lt;em&gt;using&lt;&#x2F;em&gt; those skills. If, as a child, your demons made you feel like you had no choice but to succeed, then you spent your childhood pushing yourself, becoming comfortable with hard work and stress, and generally cultivating habits, traits, and skills that allow you to succeed as an adult. But now that you &lt;em&gt;are&lt;&#x2F;em&gt; an adult, the development is done. Your success is predicated on your &lt;em&gt;having&lt;&#x2F;em&gt; certain skills, not on the factors that led you to develop those skills in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s more, your demons are likely holding you back by driving you to waste your energy on unimportant things.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The more severe the mental illness is, the more people believe [the false projections of] their mind.&lt;&#x2F;p&gt;
&lt;p&gt;– &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=gOUwoU7WddM&amp;amp;t=846s&quot;&gt;Dr. Alok Kanojia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Mental illness impairs our ability to rationally assess what is required in a given situation. To expand on the hallucination example, while it&#x27;s useful to be in great running shape, it&#x27;s actively &lt;em&gt;harmful&lt;&#x2F;em&gt; to feel driven to run all the time. If you&#x27;re always running, even when it&#x27;s not necessary, then you&#x27;ll always be exhausted. On the occasions when it really &lt;em&gt;is&lt;&#x2F;em&gt; necessary, your energy will already be spent. What you really want is to have the judgment to know when running is justified, and otherwise to conserve your energy. To paraphrase the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Serenity_Prayer&quot;&gt;Serenity Prayer&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Give me the calm to rest when I can, the fitness to run when I must, and the mental health to be able to tell the difference.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So if you find yourself avoiding working on your mental health because you&#x27;re worried you&#x27;ll sabatoge your own success, consider that &lt;em&gt;not&lt;&#x2F;em&gt; working on your mental health may be the real act of sabotage.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  
    
    
  <entry xml:lang="en">
    <title>How to Brush Your Teeth at Work</title>
    <published>2026-04-14T00:00:00+00:00</published>
    <updated>2026-04-14T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/brush-your-teeth/"/>
    <id>https://joshlf.com/posts/brush-your-teeth/</id>
    
      
    <category term="Career"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/brush-your-teeth/">&lt;p&gt;When you were a kid, you had to learn to brush your teeth. It may be easy now, but at one point it was a &lt;em&gt;skill&lt;&#x2F;em&gt;. You would get toothpaste everywhere, and your mom or dad would have to remind you to brush every tooth.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;You also probably &lt;em&gt;hated&lt;&#x2F;em&gt; doing it. You&#x27;d conveniently &quot;forget&quot; unless reminded, and then make excuses for why you hadn&#x27;t done it yet, or didn&#x27;t actually need to do it tonight in particular, or that actually your teeth were better than everybody else&#x27;s teeth and thus brushing was unnecessary and beneath you.&lt;&#x2F;p&gt;
&lt;p&gt;The problem, of course, is that if you don&#x27;t brush your teeth, your teeth will fall out of your head. At first, your parents were responsible for keeping your teeth in your head. Eventually, as you got better at brushing your teeth and got used to it as an inevitable, minor daily annoyance, you stopped thinking about it.&lt;&#x2F;p&gt;
&lt;p&gt;Now, as an adult, imagine if someone told you that brushing their teeth was too much of a hassle to be worth doing – that it would take too much effort to get good at and that, besides, it&#x27;s ridiculous that we &lt;em&gt;need&lt;&#x2F;em&gt; to brush our teeth. Shouldn&#x27;t they just be healthy all on their own? Why haven&#x27;t we evolved that? You would rightfully think that they were shooting themselves in the foot over a very minor inconveience. Surely a few minutes of mindless chore per day is worth the upside, right?&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;This is the pitch that someone gave to me a few years ago, and it changed my relationship with my career.&lt;&#x2F;p&gt;
&lt;p&gt;At the time, I was feeling what is, I think, a very common feeling: That pointless bureaucracy was making my job a slog, that I was being held back from doing good, interesting work, being asked to make it &lt;em&gt;worse&lt;&#x2F;em&gt; in order to make it legible to a bureaucracy that didn&#x27;t understand what I was doing, didn&#x27;t understand why the way I was doing it was actually &lt;em&gt;better&lt;&#x2F;em&gt;, didn&#x27;t value quality, didn&#x27;t reward the right behaviors, and generally made us all do paperwork that few people would ever read and that would have no meaningful effect on what we actually &lt;em&gt;produced&lt;&#x2F;em&gt;. It all felt so pointless and unfair. Why can&#x27;t we just let people do good work and get on with their lives?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;As an aside, there are actually good reasons for all of this that tend to be harder to appreciate when you&#x27;re earlier in your career. A mentor once told me: &quot;Organizational dysfunction is never completely avoidable. Sure, it might be possible to do things better, but it&#x27;s always downstream of a genuinely hard coordination problem. The fact that all these different people and groups, with their competing and misaligned interests, can collaborate &lt;em&gt;at all&lt;&#x2F;em&gt; is a miracle of game theory. The fact that it isn&#x27;t &lt;em&gt;perfect&lt;&#x2F;em&gt; should be the least surprising thing in the world.&quot; If this is interesting to you, read &lt;em&gt;The Evolution of Cooperation&lt;&#x2F;em&gt; by Robert Axelrod. It will change how you think about human organizations.&lt;&#x2F;p&gt;
&lt;p&gt;But let&#x27;s ignore that and assume, for the sake of argument, that bureaucracy really does exist for no good reason at all.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;While this feeling is nearly universal at some point in a career, consider the analogy to brushing your teeth. No matter how stilly it may feel, feeling that it&#x27;s silly isn&#x27;t going to magically make us evolve past the need to brush our teeth. You have two options: You can either do what most of us do – accept a very minor inconvenience and get the benefits of having teeth – or you can avoid a very minor inconvenience, but at the cost of feeling constantly angry at an unfair world &lt;em&gt;and&lt;&#x2F;em&gt; not having teeth.&lt;&#x2F;p&gt;
&lt;p&gt;Think of the bureaucratic bullshit as teeth-brushing. The child perspective entails constantly dreading the impending request to brush, clumsily brushing and getting toothpaste all over your face, and having poor dental health from all of the times you managed to avoid doing it. Imagine, instead, if you got &lt;em&gt;good&lt;&#x2F;em&gt; at navigating the bureaucracy. It would take some up-front investment to develop the skill, but once you did, you could put it all on auto-pilot. Just like brushing your teeth, as you got good at it, it would take less mental effort. It would feel less like a big, looming obligation and more like just another small cost of doing business that you get out of the way so you can move on to the interesting work you really care about doing.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond the mental peace, you would also have more control over your career. As you learned how to speak bureaucrat-ese, you would be more effective at demonstrating – in a language that your manager&#x27;s manager&#x27;s manager can understand – that your work is important and should continue to be funded. You would get to pick more interesting projects because you would know how to convince your leadership that they were worth investing in. You would get less oversight and micromanagement because you would be trusted to use your judgment about what to work on.&lt;&#x2F;p&gt;
&lt;p&gt;The next time you encounter somebody with a really cool job and think, &quot;fuck, what did they do to get a job that cool,&quot; consider how good they are at brushing their teeth. Maybe a lot of what separates you from them is just a few minutes per day and some toothpaste.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Force Your Macro&#x27;s Callers to Write Unsafe</title>
    <published>2025-04-05T00:00:00+00:00</published>
    <updated>2025-04-05T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/unsafe-macros/"/>
    <id>https://joshlf.com/posts/unsafe-macros/</id>
    
      
    <category term="Rust"/>
      
    <category term="Unsafe"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/unsafe-macros/">&lt;p&gt;Imagine you&#x27;re writing this macro:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; Types that can be frobnicated.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; It must be sound to frobnicate `Self`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;unsafe trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Frobnicatable&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; Implements `Frobnicatable` for `$t`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; `$t` must satisfy the safety invariant of `Frobnicatable`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;macro_rules! unsafe_impl_frobnicatable&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ty)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; SAFETY: The caller has promised that `$t` satisfies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; the safety invariant of `Frobnicatable`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Frobnicatable&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;t {}  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;&lt;em&gt;Of course, you&#x27;d never actually write a macro to emit code this simple, but
it&#x27;s a meant as a stand-in for macros that emit more complex code.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A caller might write this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; SAFETY: It is sound to frobnicate `Foo`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unsafe_impl_frobnicatable!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But imagine that your caller wants to practice good safety hygeine, and they use
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rust-clippy&#x2F;master&#x2F;index.html#undocumented_unsafe_blocks&quot;&gt;&lt;code&gt;#![deny(clippy::undocumented_unsafe_blocks)]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Because Clippy doesn&#x27;t realize that the macro call requires a safety comment, it
won&#x27;t complain if your caller forgets their safety comment:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#![deny(clippy&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;undocumented_unsafe_blocks)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; Clippy: 🙈&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unsafe_impl_frobnicatable!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead, you should write your macro so that it &lt;em&gt;invokes&lt;&#x2F;em&gt; unsafe code. This also
means that we can drop the &lt;code&gt;unsafe_&lt;&#x2F;code&gt; prefix from the macro&#x27;s name – it was just
there to make it less likely for your callers to miss the safety requirement,
but that&#x27;s no longer a concern. &lt;em&gt;Also, make sure to have the macro&#x27;s right-hand
side contain a block – ie, &lt;code&gt;{{ ... }}&lt;&#x2F;code&gt; – see the appendix for an explanation of
why this is important.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; Implements `Frobnicatable` for `$t`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; `$t` must satisfy the safety invariant of `Frobnicatable`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;macro_rules! impl_frobnicatable&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ty)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; Force caller to wrap in an `unsafe { ... }` block.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        $crate::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;__unsafe&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; SAFETY: The caller has promised that `$t` satisfies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; the safety invariant of `Frobnicatable`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Frobnicatable&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;t {}  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[doc(hidden)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;pub const unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; __unsafe&lt;&#x2F;span&gt;&lt;span&gt;() {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, even when Clippy isn&#x27;t used, Rust will force your caller to put the macro
invocation in an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block. In other words, this will no longer compile:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; SAFETY: It is sound to frobnicate `Foo`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;impl_frobnicatable!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To fix this, your caller must wrap the invocation in an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block, for
example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; SAFETY: It is sound to frobnicate `Foo`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; = unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; impl_frobnicatable!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now Clippy &lt;em&gt;will&lt;&#x2F;em&gt; catch a missing safety comment since your caller is using
a normal &lt;code&gt;unsafe&lt;&#x2F;code&gt; block.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appendix-macro-expansion&quot;&gt;Appendix: Macro expansion&lt;&#x2F;h2&gt;
&lt;p&gt;Note one subtlety: You&#x27;re going to want to have your macro emit a block (ie, use
&lt;code&gt;(...) =&amp;gt; {{ ... }}&lt;&#x2F;code&gt; rather than &lt;code&gt;(...) =&amp;gt; { ... }&lt;&#x2F;code&gt;). You&#x27;re now requiring your
callers to call your macro in expression or statement position (ie, inside of a
block) rather than in item position (ie, at the top-level, outside of a block).
Thus, it has to play nicely with code before and after it in the same block.
Expanding to a self-contained block is a good way of ensuring that this will
happen.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Introducing Mundane, a New Cryptography Library for Rust</title>
    <published>2018-11-06T00:00:00+00:00</published>
    <updated>2018-11-06T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/introducing-mundane/"/>
    <id>https://joshlf.com/posts/introducing-mundane/</id>
    
      
    <category term="Rust"/>
      
    <category term="Cryptography"/>
      
    <category term="Mundane"/>
      
    <category term="BoringSSL"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/introducing-mundane/">&lt;p&gt;Mundane, meet the world. The world, meet Mundane.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;rustdoc&#x2F;mundane&quot;&gt;Mundane&lt;&#x2F;a&gt; is a cryptography library written in Rust and backed
by BoringSSL. It aims to be difficult to misuse, ergonomic, and performant (in
that order). It was originally created to serve the cryptography needs of
Fuchsia, but we&#x27;ve decided to split it off as a general-purpose crate.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;why-mundane&quot;&gt;Why Mundane?&lt;&#x2F;h2&gt;
&lt;p&gt;Mundane&#x27;s raison d&#x27;être is to provide an API which is difficult to misuse.
Experience shows that one of the most common failure modes of cryptography is
incorrect implementation, and often, that failure occurs at the boundary between
an application and a cryptography library.&lt;&#x2F;p&gt;
&lt;p&gt;Given this experience, Mundane takes the approach of giving the programmer the
fewest degrees of freedom possible. Doing the right thing should be easy and
feel natural. Doing the wrong thing should feel difficult and ideally be
entirely impossible.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is the perfect language for a library with this design philosophy. Its
expressive and strict type system allows us to ensure that, across a wide array
of correctness properties, an incorrect program will not compile.&lt;&#x2F;p&gt;
&lt;p&gt;Consider, for example, the humble signature. A signature consists of two
components: a hash of some input data, and a digital signature of that hash.
Mundane&#x27;s &lt;code&gt;Signature&lt;&#x2F;code&gt; trait looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; A cryptographic signature generated by a private key.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Signature&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Sealed&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Sized&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; The private key type used to generate this signature.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PrivateKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PrivateKey&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; Sign a message.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; The input to this function is always a message, never a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; digest. If a signature scheme calls for hashing a message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; and signing the hash digest, `sign` is responsible for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; both hashing and signing.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sign&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PrivateKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;, message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; Verify a signature.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; The input to this function is always a message, never a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; digest. If a signature scheme calls for hashing a message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; and signing the hash digest, `verify` is responsible for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; both hashing and verifying the digest.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; verify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;, key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PrivateKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PrivateKey&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Public&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Right away, we see an example of a mistake which is impossible with Mundane&#x27;s
API: It&#x27;s impossible to incorrectly combine hashing and signing because they&#x27;re
not exposed as separate operations. Instead, both on the signing path and the
verification path, hashing is handled by the API automatically.&lt;&#x2F;p&gt;
&lt;p&gt;This allows us to unlock more powerful and subtle correctness properties. For
example, since we are responsible for hashing, not only can we ensure that
hashing is done properly, we can also ensure that a secure hash function is
used. Consider, for example, the &lt;code&gt;EcdsaSignature&lt;&#x2F;code&gt;, which implements &lt;code&gt;Signature&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F; A DER-encoded ECDSA signature.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; EcdsaSignature&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;C&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PCurve&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; H&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Hasher&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; EcdsaHash&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The ECDSA signature algorithm can operate over any elliptic curve (the &lt;code&gt;C&lt;&#x2F;code&gt; type
parameter) and any hash function (the &lt;code&gt;H&lt;&#x2F;code&gt; type parameter). If we look closely,
we see that &lt;code&gt;H&lt;&#x2F;code&gt; is not just a &lt;code&gt;Hasher&lt;&#x2F;code&gt; (the trait implemented by hash
functions), but is, in addition, an &lt;code&gt;EcdsaHash&amp;lt;C&amp;gt;&lt;&#x2F;code&gt;. This trait is only
implemented for valid hash&#x2F;curve pairs. Some hashes are large enough that, in
order to sign them using ECDSA, they would need to be truncated. For example,
using a SHA-512 hash with ECDSA over a P-256 curve would require truncating the
hash before signing, reducing the security of the hash.&lt;&#x2F;p&gt;
&lt;p&gt;Thus, we only implement &lt;code&gt;EcdsaHash&lt;&#x2F;code&gt; for hash&#x2F;curve pairs where no truncation is
necessary. Hash&#x2F;curve pairs which require truncation aren&#x27;t supported, and code
which tries to use them won&#x27;t compile.&lt;&#x2F;p&gt;
&lt;p&gt;For more examples, see the &lt;a href=&quot;&#x2F;rustdoc&#x2F;mundane&quot;&gt;documentation&lt;&#x2F;a&gt;. For an in-depth
discussion of our design philosophy, see the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;mundane&#x2F;blob&#x2F;master&#x2F;DESIGN.md&quot;&gt;design
doc&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;&#x2F;h3&gt;
&lt;p&gt;Of course, there&#x27;s more to cryptography than the API. Mundane is based on the
well-vetted and actively-developed BoringSSL. Mundane does not provide any
implementations itself, and does not currently have any plans to do so in the
future.&lt;&#x2F;p&gt;
&lt;p&gt;A common problem with relying on native libraries from Rust crates is
compatibility - while Rust and Cargo are able to compile multiple crate versions
into a single binary, C is not so flexible. In order to avoid this problem,
Mundane vendors a copy of the BoringSSL source, which is shipped along with the
crate on crates.io. It uses symbol prefixing to ensure that the version of
BoringSSL compiled for a particular version of Mundane will not conflict with
either a) the version of BoringSSL compiled for a different version of Mundane
or, b) any version of BoringSSL compiled for any other Rust crate. Because the
source is shipped with Mundane, users do not need to have BoringSSL installed
when building.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The approach we use to prefix BoringSSL&#x27;s symbols is complex, and makes
compilations take longer than we&#x27;d like. If you&#x27;re interested in helping improve
the situation, please get in touch!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-not-other-cryptography-crate&quot;&gt;Why not &amp;lt;other cryptography crate&amp;gt;?&lt;&#x2F;h2&gt;
&lt;p&gt;There are a host of fantastic cryptography crates in Rust, each with its own
focus and design tradeoffs. Mundane has its focus - to be misuse-resistant at
all costs - and it makes design tradeoffs with that focus in mind. If that&#x27;s not
what you&#x27;re looking for, then one of the other cryptography crates might be a
better fit for your use case.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, as the primary Rust cryptography crate used by the Fuchsia OS,
Mundane has a very high bar for security and active maintenance. While Rust is
our ideal language for almost everything, it still has some shortcomings when it
comes to writing cryptography code, such as the lack of guaranteed constant-time
operations. Moreover, to be blunt, we don&#x27;t trust ourselves to implement
cryptography correctly. That&#x27;s why we rely exclusively on BoringSSL, which is
developed full-time by a team of professional cryptographers, and which provides
strong guarantees about fixing vulnerabilities quickly if they arise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-can-i-help&quot;&gt;How can I help?&lt;&#x2F;h2&gt;
&lt;p&gt;Use Mundane! Use it for high-level applications and low level applications. Use
it in all different environments. The more users we have, the more feedback
we&#x27;ll get, and the better Mundane will be. Tell us what you like, and what you
don&#x27;t. Tell us what features you want to see in the future. Submit
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;mundane&#x2F;issues&quot;&gt;issues&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Rust Has Higher Kinded Types Already... Sort Of</title>
    <published>2018-10-18T00:00:00+00:00</published>
    <updated>2018-10-18T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/rust-higher-kinded-types-already/"/>
    <id>https://joshlf.com/posts/rust-higher-kinded-types-already/</id>
    
      
    <category term="Rust"/>
      
    <category term="Types"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/rust-higher-kinded-types-already/">&lt;h2 id=&quot;refresher&quot;&gt;Refresher&lt;&#x2F;h2&gt;
&lt;p&gt;First, a very quick refresher.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust, a type which takes type parameters (&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;HashMap&amp;lt;K, V&amp;gt;&lt;&#x2F;code&gt;,
etc) is only a valid type when all type parameters are specified. In other
words, &lt;code&gt;Rc&lt;&#x2F;code&gt;, &lt;code&gt;Vec&lt;&#x2F;code&gt;, and &lt;code&gt;HashMap&amp;lt;K&amp;gt;&lt;&#x2F;code&gt; are not types. You can&#x27;t have a variable of
type &lt;code&gt;Rc&lt;&#x2F;code&gt;. You can&#x27;t pass &lt;code&gt;Rc&lt;&#x2F;code&gt; as a parameter to other types.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;The ability to have such things be actual types is a feature called &lt;em&gt;higher
kinded types&lt;&#x2F;em&gt; (HKT). It&#x27;s primarily useful when combined with traits which also
take type parameters. Consider, for example, a hypothetical trait to abstract
over different kinds of reference-counted pointers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Deref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Target&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can easily implement this for &lt;code&gt;Rc&lt;&#x2F;code&gt; and &lt;code&gt;Arc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, with HKTs, &lt;code&gt;RcPtr&lt;&#x2F;code&gt; (as opposed to &lt;code&gt;RcPtr&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;) would be a valid trait,
and &lt;code&gt;Rc&lt;&#x2F;code&gt; and &lt;code&gt;Arc&lt;&#x2F;code&gt; would implement it (as opposed to &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;This would allow you to do things like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; TreeNode&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; P&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TreeNode&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TreeNode&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a tree data structure where the caller gets to decide whether it&#x27;s
thread-safe or not. There are many applications which would benefit greatly from
allowing the caller to specify some property such as thread safety, caching
behavior, etc - all things which require HKTs in order to leave type parameters
unbound until later than is allowed in normal Rust today (I say &quot;normal&quot;
because, well, read the next section).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hkts-in-rust-today&quot;&gt;HKTs in Rust Today&lt;&#x2F;h2&gt;
&lt;p&gt;One way to view the limitation that prevents us from writing this code is that,
a) when declaring a trait bound, all type parameters must be bound (i.e., &lt;code&gt;P: RcPtr&lt;&#x2F;code&gt; is not a valid trait bound since &lt;code&gt;RcPtr&lt;&#x2F;code&gt; takes a type parameter) and, b)
when declaring a type, all type parameters must be bound (i.e., &lt;code&gt;Rc&lt;&#x2F;code&gt; and &lt;code&gt;Arc&lt;&#x2F;code&gt;
aren&#x27;t types; &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; are).&lt;&#x2F;p&gt;
&lt;p&gt;However, it&#x27;s not quite true that there&#x27;s no way to define a trait which allows
some type parameters to remain unbound, or that there&#x27;s no way to implement
those traits with types which also leave some type parameters unbound. Consider,
for example, the following function from the standard library&#x27;s &lt;code&gt;Iterator&lt;&#x2F;code&gt;
trait:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Iterator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Sum&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even once a type has implemented the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait, the &lt;code&gt;S&lt;&#x2F;code&gt; type parameter on
&lt;code&gt;sum&lt;&#x2F;code&gt; is still unbound - it&#x27;s only bound once the method is called. This implies
a general pattern - if you want to allow specifying a trait bound while leaving
type parameters unbound, just move them into the methods on that trait. Let&#x27;s
give it a try:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; deref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If this trait gives you an uneasy feeling, you&#x27;ve got the right intuition.
Normally, with a trait with a type parameter like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; deref&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You declare variables like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; = ...&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, whenever you operate on &lt;code&gt;foo&lt;&#x2F;code&gt;, the compiler guarantees that the correct
type &lt;code&gt;T&lt;&#x2F;code&gt; is used. This is important, or else you&#x27;d be able to operate on the
same variable as different types at different points in the program:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;quot;hello there&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In other words, the fact that Rust tracks the type of variables is what allows
us to have memory safety! So if the type parameter to &lt;code&gt;RcPtr&lt;&#x2F;code&gt; is moved from the
trait itself into each of the methods, then you could do something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; = ...&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;, foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;deref&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In other words, you could violate memory safety. No bueno. I guess we&#x27;re out of
luck...&lt;&#x2F;p&gt;
&lt;p&gt;Although... There is a giant, hairy, awful, scary escape hatch in the language,
so what if we just...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;unsafe trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; deref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s better :)&lt;&#x2F;p&gt;
&lt;p&gt;Of course, using &lt;code&gt;unsafe&lt;&#x2F;code&gt; means that you&#x27;re opting into manually verifying
certain properties. So what properties does the programmer pinky-swear to uphold
here? Essentially, it becomes the programmer&#x27;s responsibility to track the types
of variables and only ever access them consistently. In other words, for a given
instance of a variable, it must only ever be accessed with the same &lt;code&gt;T&lt;&#x2F;code&gt;
parameter.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, Rust is pretty good at encapsulation, so we can just encapsulate this
in a safe type that uses unsafe under the hood, and guarantees to always use the
same &lt;code&gt;T&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcWrapper&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    rc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; R&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    _marker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PhantomData&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcWrapper&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        RcWrapper&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            rc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;&amp;gt;(t),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            _marker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PhantomData&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Deref&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcWrapper&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Target&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; deref&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;deref&lt;&#x2F;span&gt;&lt;span&gt;() }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Given an &lt;code&gt;R: RcPtr&lt;&#x2F;code&gt; and a &lt;code&gt;T&lt;&#x2F;code&gt;, instead of writing &lt;code&gt;R&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; as we would if Rust
supported HKT natively, we write &lt;code&gt;RcWrapper&amp;lt;R, T&amp;gt;&lt;&#x2F;code&gt;. We can then treat the
&lt;code&gt;RcWrapper&amp;lt;R, T&amp;gt;&lt;&#x2F;code&gt; just as we would &lt;code&gt;R&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; if we had native HKT - we can pass it
around, call methods on it, clone it, etc.&lt;&#x2F;p&gt;
&lt;p&gt;OK, so we can define the trait, and we can even make it safe to use. But how on
earth could we implement the trait? What would such an implementation look like?&lt;&#x2F;p&gt;
&lt;p&gt;Awful, that&#x27;s what. While one of the benefits of giving variables types is that
you can guarantee that you always operate on them as the proper type, another
benefit is that you always know what size they are. What size is something whose
type isn&#x27;t known until you call methods on it? God only knows...&lt;&#x2F;p&gt;
&lt;p&gt;And when only God knows something, you&#x27;ve got no choice but to figure it out at
runtime, and stick it on the heap.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SingleThreadedRc&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Actually *mut Rc&amp;lt;T&amp;gt;, but we don&amp;#39;t know&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; what T is until runtime...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span&gt; (),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SingleThreadedRc&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Dear SingleThreadedRc, I pinky-swear that&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; you&amp;#39;re actually holding a pointer to an Rc&amp;lt;T&amp;gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; I swear on my mother&amp;#39;s grave.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;inner &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;as *const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RcPtr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SingleThreadedRc&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; Get access to the Rc&amp;lt;T&amp;gt; we knew we had &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F; inside of us deep down all along...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; new_inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; new_inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(new_inner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        SingleThreadedRc&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;into_raw&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(new_inner)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span&gt; (),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; deref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;deref&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Does anybody have any Purell?&lt;&#x2F;p&gt;
&lt;p&gt;But it works. You can see a full example including usage
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2015&amp;amp;gist=d280c71819f6d698e05ab3ec448f2394&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;To recap, here&#x27;s the general pattern. You would like a trait, &lt;code&gt;MyTrait&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;, to
be higher-kinded, but we don&#x27;t support that in Rust right now. Instead, you
create a trait, &lt;code&gt;MyTrait&lt;&#x2F;code&gt;, which takes no type parameters, but each of its
methods take a type parameter, &lt;code&gt;T&lt;&#x2F;code&gt;. Then, if you have an &lt;code&gt;M: MyTrait&lt;&#x2F;code&gt;, instead
of doing &lt;code&gt;M&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; as you normally would, you create a concrete wrapper type,
&lt;code&gt;MyTraitWrapper&amp;lt;M: MyTrait, T&amp;gt;&lt;&#x2F;code&gt;. &lt;code&gt;M&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; is then written as &lt;code&gt;MyTraitWrapper&amp;lt;M, T&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, the code presented here is far from pretty or optimal. One obvious
drawback is the heap allocation. If you could guarantee an upper bound on the
size of the internal type (e.g., if you knew an upper bound on the size of
&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; for all &lt;code&gt;T&lt;&#x2F;code&gt;), you could stack- instead of heap-allocate.&lt;&#x2F;p&gt;
&lt;p&gt;This also doesn&#x27;t cover everything you might want HKT for. For example, how do
you emulate the following trait, where you&#x27;d like to be able to do &lt;code&gt;M: MyTrait&lt;&#x2F;code&gt;
and then, later, &lt;code&gt;M::&amp;lt;T&amp;gt;::MyType&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MyTrait&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MyType&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m pretty sure it&#x27;s possible, but I haven&#x27;t actually gotten it working in code
yet. In the interest of keeping this post short (and also reclaiming some of my
free time), I&#x27;ve decided to leave it an exercise to readers to either get it
working, or argue that it can&#x27;t be done (and thus that the approach I&#x27;ve
proposed here falls short of full HKT).&lt;&#x2F;p&gt;
&lt;p&gt;Finally, in fairness, calling this &quot;HKT&quot; is a bit of a stretch. It&#x27;s not a
general-purpose mechanism - you have to manually implement it for every trait
and every type - and it doesn&#x27;t provide the same soundness guarantees that a
language feature would. But, for any given application that needs a particular
trait to be HKT-ified, it gets the job done.&lt;&#x2F;p&gt;
&lt;p&gt;Rust has HKT right now, but only the sinners can use it.&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: In Review</title>
    <published>2016-09-18T00:00:00+00:00</published>
    <updated>2016-09-18T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-in-review/"/>
    <id>https://joshlf.com/posts/soylent-in-review/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-in-review/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Just over two years ago, I started what I thought was going to be, as the note above suggests, a month-long experiment with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.soylent.com&quot;&gt;Soylent&lt;&#x2F;a&gt; (if you don&#x27;t know what Soylent is, read the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt;). At the time, I was considering Soylent as a potential full or partial replacement for normal food, but since I was about to head into a school year with a full meal plan, I wasn&#x27;t going to be able to start right away. So I wanted to try it out for a month to see if it was something I&#x27;d want to do full-time after graduation, and I decided to write this blog series on it - one post per day - to track my progress and let others benefit from my experience.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Not only did I not end up switching to Soylent, I didn&#x27;t even finish the blog series (or, for that matter, the experiment itself). And for the past two years, I&#x27;ve continually putting off writing a final post. Better late than never, I guess?&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I&#x27;m going to explain my main takeaways from the experiment, and a number of tips, tricks, and insights that I learned along the way.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE (09&#x2F;18&#x2F;2016): I should note that the version of Soylent I used for this experiment was 1.0. Some results may vary with other versions.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;you-need-to-need-it&quot;&gt;You Need to Need It&lt;&#x2F;h2&gt;
&lt;p&gt;By far the most important lesson that I learned is that Soylent would never work for me unless I need it to. As I described in the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt;, my reason for considering Soylent was convenience - I&#x27;m lazy when it comes to shopping, cooking, and cleaning, and Soylent reduces the burden of all of these. But the timing of the experiment meant that I never needed the convenience. For the first two weeks of the experiment, I was on summer break, and I had all the time in the world. Cooking was, if anything, a way to fill the time. After that, I was at school, and on a full meal plan. Instead of shopping, cooking, and cleaning, I simply walked into a dining hall, ate already-prepared food, and left my plates to be cleaned by somebody else.&lt;&#x2F;p&gt;
&lt;p&gt;For me, Soylent would only work if the alternative was time-consuming or annoying. To be fair, though, I never got to try, so I can only speculate. Maybe even then it wouldn&#x27;t be enough.&lt;&#x2F;p&gt;
&lt;p&gt;But that begs the question - why didn&#x27;t I enjoy Soylent in its own right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;soylent-is-medicine&quot;&gt;Soylent is Medicine&lt;&#x2F;h2&gt;
&lt;p&gt;After you get used to it, Soylent doesn&#x27;t taste actively bad, but it certainly isn&#x27;t appealing in its own right either. I found myself craving real food not because I was hungry - Soylent certainly made me full - but for the taste and the texture. As I described in my &lt;a href=&quot;&#x2F;posts&#x2F;soylent-day-3&#x2F;&quot;&gt;third post&lt;&#x2F;a&gt;, &quot;I still feel full and satisfied after I drink it, but I have to will myself to drink it knowing that that will be the outcome; I don&#x27;t find myself actively wanting Soylent itself.&quot; In short, you have to treat it like medicine - you eat it because you need to, not because you want to.&lt;&#x2F;p&gt;
&lt;p&gt;Again, you need to need it. If it&#x27;s your only option, or if it has upsides that normal food doesn&#x27;t, then it&#x27;s worth it. I also know that a lot of people only use Soylent for one meal in the day - for example, a quick breakfast if they&#x27;re rushing to get to work in the morning. It makes sense to me that that might work better since you can still enjoy lunch and dinner, but I haven&#x27;t tried it myself, so I can&#x27;t say for sure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tips-tricks-and-insights&quot;&gt;Tips, Tricks, and Insights&lt;&#x2F;h2&gt;
&lt;p&gt;Even though I didn&#x27;t see the experiment through to its conclusion, I did eat it for more than two weeks, and picked a few tips, tricks, and insights along the way.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The taste of Soylent is mildly sweet, and it was a bit off-putting to me at first. The texture is very thick, and I was not used to drinking liquid that dense. It takes a few days to become fully comfortable with drinking it, so be patient.&lt;&#x2F;li&gt;
&lt;li&gt;Drink &lt;em&gt;slowly&lt;&#x2F;em&gt;. I can&#x27;t emphasize this enough. Each glass of Soylent has the caloric content of a full meal. Imagine how full you would feel if you scarfed down a cheeseburger in thirty seconds. Soylent may be a liquid, but if you drink it quickly, you will feel just as full. I made this mistake the first day, and I felt queasy afterwards.&lt;&#x2F;li&gt;
&lt;li&gt;Not only should you drink slowly when sitting down to a meal, but it may be a good idea to sip continuously throughout the day instead of treating each drink as a single meal. I found myself naturally falling into this rythm, and I think the reason is that, being a liquid, Soylent doesn&#x27;t have to be broken down by stomach acids before its nutrients get absorbed into the blood stream. Thus, in order to get the continual feeling of having energy that you get from eating a meal of solid food, just drink small quantities of Soylent continuously.&lt;&#x2F;li&gt;
&lt;li&gt;If you use Soylent for a large part of your diet, and you adopt the approach of drinking small amounts continuously, you may find that you become accustomed to eating small quantities, and that eating a large quantity of food (such as at a restaurant) makes you feel much more full than it normally would.&lt;&#x2F;li&gt;
&lt;li&gt;A common problem that people report when first trying Soylent is flatulence. &quot;Something something gut biome,&quot; I guess; I&#x27;m not a biologist. But it&#x27;s something people experience. I never had it that badly, but one thing I can say is that drinking Soylent quickly makes it worse - again, always drink slowly.&lt;&#x2F;li&gt;
&lt;li&gt;Always drink cool or cold Soylent, and never water it down. To this day, my friends cite the most entertaining post in this series as the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-day-15&#x2F;&quot;&gt;day 15 post&lt;&#x2F;a&gt; in which I describe the horror of drinking warm, watered-down Soylent. &quot;For the love of all that is good and holy, do not water down your Soylent... I don&#x27;t know what it is about watered down or warm Soylent, but just... just don&#x27;t. Dear god, just don&#x27;t.&quot; I felt really queasy - on the verge of throwing up - for the better part of the morning. However, I had cold, not-watered-down Soylent for lunch, and it made my stomach feel much better, which confirmed that the temperature and dilution were the problem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Well, that&#x27;s all I&#x27;ve got! It feels like a relief to finally get this thing written - I&#x27;ve seriously been putting it off for two years. Hopefully this dinky blog series on a dinky personal website will find someone in the future with questions, and give them some answers. It will be my little piece of &quot;Wisdom of the Ancients.&quot;&lt;&#x2F;p&gt;
&lt;img alt=&quot;Wisdom of the Ancients&quot; src=&quot;http:&#x2F;&#x2F;imgs.xkcd.com&#x2F;comics&#x2F;wisdom_of_the_ancients.png&quot; style=&quot;margin:0px auto;display:block&quot;&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;i&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;979&#x2F;&quot;&gt;Wisdom of the Ancients&lt;&#x2F;a&gt;&lt;&#x2F;i&gt;, xkcd&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 17</title>
    <published>2014-08-28T00:00:00+00:00</published>
    <updated>2014-08-28T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-17/"/>
    <id>https://joshlf.com/posts/soylent-day-17/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-17/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing noteworthy to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 16</title>
    <published>2014-08-27T00:00:00+00:00</published>
    <updated>2014-08-27T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-16/"/>
    <id>https://joshlf.com/posts/soylent-day-16/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-16/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing noteworthy to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 15</title>
    <published>2014-08-26T00:00:00+00:00</published>
    <updated>2014-08-26T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-15/"/>
    <id>https://joshlf.com/posts/soylent-day-15/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-15/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For the love of all that is good and holy, do not water down your Soylent. This morning, not having a fridge to store a full pitcher in, I decided to make one serving for breakfast. I thought that I could get away with fitting one and a half servings in my water bottle, so I put one and a half serving&#x27;s worth of water in. Then I realized that it wasn&#x27;t going to fit, so I only put in one serving of Soylent. Oh, and since I didn&#x27;t have a fridge, it was room temperature (another big no-no). I forced myself to drink the warm, diluted substance because I needed to eat, but each sip made me feel like I was going to puke. I don&#x27;t know what it is about watered down or warm Soylent, but just... just don&#x27;t. Dear god, just don&#x27;t.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;&#x2F;strong&gt; I spoke too soon! After initially posting this article, I had some Soylent that had been sitting in the fridge all day. It was actually a huge relief. The taste of the watered down Soylent had been in my mouth all day, and the cold Soylent was like cool sweet relief. Not only was it refreshing, but it actually washed away the taste of the watered down Soylent from earlier. Soylent to the rescue, I guess?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;I still don&#x27;t have access to a scale in my dorm, and I forgot to take my heart rate (that one&#x27;s on me).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 14</title>
    <published>2014-08-25T00:00:00+00:00</published>
    <updated>2014-08-25T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-14/"/>
    <id>https://joshlf.com/posts/soylent-day-14/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-14/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yesterday was my last day in Boston for the summer before heading to Providence. Being me, I decided to make the trip by bike, and, also being me, decided to bump said trip up to 2:00 am last night on a whim.&lt;&#x2F;p&gt;
&lt;p&gt;Besides preening my adventurer&#x27;s feathers, I mention this because I had to finish all of the Soylent that I had before I left, or else throw it away (I took the pitcher with me, and I didn&#x27;t want to have a half-full pitcher of Soylent sloshing around on the back of my bike). Naturally, I picked the first option.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;There was a lot of Soylent left - about two very full glasses&#x27; worth. Having made the decision to bump up the trip about 30 minutes before I was going to leave, I had 30 minutes to drink it all. So I chugged.&lt;&#x2F;p&gt;
&lt;p&gt;I expected to feel over-full and maybe in a small amount of pain. But that&#x27;s not exactly what happened. I felt pretty full, but not so much that it bothered me. Instead, I think largely from drinking the Soylent so quickly and giving my esophagus a workout, I got a heartburn-like pain near the bottom of my sternum that lasted all through the night and even persists faintly now at 9:00 pm the next day.&lt;&#x2F;p&gt;
&lt;p&gt;The moral of the story: Drink. Soylent. Slowly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t have access to a scale in my dorm, so I was unable to weigh myself. I may buy a cheap one so I can keep taking weight measurements. I also didn&#x27;t want to take my heart rate after a night of biking and no sleep since that would kind of be like slapping statistical significance in the face.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 13</title>
    <published>2014-08-24T00:00:00+00:00</published>
    <updated>2014-08-24T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-13/"/>
    <id>https://joshlf.com/posts/soylent-day-13/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-13/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing noteworthy to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 164 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 12</title>
    <published>2014-08-23T00:00:00+00:00</published>
    <updated>2014-08-23T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-12/"/>
    <id>https://joshlf.com/posts/soylent-day-12/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-12/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing noteworthy to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 165 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: 64 bpm&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 11</title>
    <published>2014-08-22T00:00:00+00:00</published>
    <updated>2014-08-22T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-11/"/>
    <id>https://joshlf.com/posts/soylent-day-11/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-11/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing new to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;I wasn&#x27;t at home last night, so I couldn&#x27;t weigh myself in the morning (no scale available), and I forgot to take my heart rate (that one&#x27;s on me).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 10</title>
    <published>2014-08-21T00:00:00+00:00</published>
    <updated>2014-08-21T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-10/"/>
    <id>https://joshlf.com/posts/soylent-day-10/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-10/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today I went out to dinner and ate a fairly large amount, and I was less full than I had been in previous days. I think my straying from a pure-Soylent diet the past few days has gotten me more accustomed to large quantities of food in bursts as opposed to small quantities repeatedly.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve decided that, given the fact that my physical health hasn&#x27;t fluctuated at all (it&#x27;s just been listed as &quot;good&quot; on all but one of the days), I&#x27;m going to remove it from the list of vitals. If any noteworthy changes happen, I&#x27;ll note them, but otherwise I won&#x27;t mention it.&lt;&#x2F;p&gt;
&lt;p&gt;Also, I pulled an all-nighter last night, and so I couldn&#x27;t take my heart rate just after waking up, and I omitted it today.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 164 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 9</title>
    <published>2014-08-20T00:00:00+00:00</published>
    <updated>2014-08-20T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-9/"/>
    <id>https://joshlf.com/posts/soylent-day-9/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-9/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today, I went out to dinner &lt;em&gt;and&lt;&#x2F;em&gt; desert, I didn&#x27;t fill up as much as I expected. I have a suspicion that this may just be because of the increased amount of normal food I&#x27;ve had over the past few days (with going out to dinner on Sunday and snacks the past few days). I just had a glass of Soylent as I sit here writing this (at 3:00am, so it&#x27;s been a while since I ate), and I was actually hungry before I had it. Really the take-home here is that this stuff makes for good blog posts but really shitty empirical science. Hooray for small sample sizes!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 162 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: 72 bpm&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 8</title>
    <published>2014-08-19T00:00:00+00:00</published>
    <updated>2014-08-19T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-8/"/>
    <id>https://joshlf.com/posts/soylent-day-8/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-8/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today, I had a turkey sandwich with two slices of sharp cheddar cheese on a relatively empty stomach, and now I&#x27;m very full. Normally this would not be the case - I&#x27;d be satisfied at best. I&#x27;m getting the sense that I&#x27;m really getting used to eating a bit at a time, and I&#x27;m getting used to it pretty quickly (after all, it&#x27;s barely been a week).&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 168 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: 62 bpm&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 7</title>
    <published>2014-08-18T00:00:00+00:00</published>
    <updated>2014-08-18T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-7/"/>
    <id>https://joshlf.com/posts/soylent-day-7/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-7/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing noteworthy to report today.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;I forgot to take my vitals this morning... sorry.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: N&#x2F;A&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: N&#x2F;A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 6</title>
    <published>2014-08-17T00:00:00+00:00</published>
    <updated>2014-08-17T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-6/"/>
    <id>https://joshlf.com/posts/soylent-day-6/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-6/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today, I went out to dinner with a friend and had a restaurant-sized cheeseburger. I normally have a bottomless pit of a stomach, but this filled me up to the point of being uncomfortable. My hypothesis is that I&#x27;ve gotten used to not eating a large amount at a time. Because Soylent is a liquid, it is absorbed immediately, and thus must be consumed bit by bit during the day. Thus, over the course of the past few days, my stomach has never been particularly full. I guess I&#x27;ve gotten used to it.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;I also didn&#x27;t even finish the leftover Soylent from last night (there was about a fifth of a day&#x27;s worth), let alone make a new pitcher. I&#x27;ll be curious to see if I wake up very hungry tomorrow (or have more after posting this article and before going to bed).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 162 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: 80 bpm&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 5</title>
    <published>2014-08-16T00:00:00+00:00</published>
    <updated>2014-08-16T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-5/"/>
    <id>https://joshlf.com/posts/soylent-day-5/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-5/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing particularly noteworthy from today. However, it&#x27;s been four full days now, and I haven&#x27;t had nearly the amount of crime-against-humanity farting that many others have reported. I&#x27;ve had a little, but it&#x27;s been pretty infrequent (a few farts a day) and not particularly smelly. I expect that it&#x27;s been some combination of following the advice I wrote about on &lt;a href=&quot;&#x2F;posts&#x2F;soylent-day-2&#x2F;&quot;&gt;day two&lt;&#x2F;a&gt; (not chugging the Soylent) and my body&#x27;s unique sensitivity (or lack thereof) to the ingredients in Soylent. There&#x27;s no obvious single answer; I guess the most I can say is that I got lucky.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;A friend suggested that I add heart rate to my daily objective vital tally since it&#x27;s trivial to take yourself and doesn&#x27;t fluctuate too much.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 161 lbs&lt;&#x2F;li&gt;
&lt;li&gt;Heart rate: 74 bpm&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 4</title>
    <published>2014-08-15T00:00:00+00:00</published>
    <updated>2014-08-15T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-4/"/>
    <id>https://joshlf.com/posts/soylent-day-4/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-4/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Soylent itself has been getting steadily more palatable. Though I&#x27;m making the same mixture each day, it seems thinner to me now than it did at the start, and more enjoyable. I&#x27;m still not to the point where I&#x27;ll want it if I&#x27;m hungry (though I&#x27;ll convince myself to eat it in that case), but it&#x27;s better than it was.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 164 lbs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good, but I pulled an all-nighter last night, so any subjective data from today is untrustworthy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 3</title>
    <published>2014-08-14T00:00:00+00:00</published>
    <updated>2014-08-14T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-3/"/>
    <id>https://joshlf.com/posts/soylent-day-3/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-3/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today I made another observation about eating quickly. Don&#x27;t. Just don&#x27;t. I tried sipping more slowly like I wrote about in &lt;a href=&quot;&#x2F;posts&#x2F;soylent-day-2&#x2F;&quot;&gt;yesterday&#x27;s post&lt;&#x2F;a&gt;, but I guess I didn&#x27;t slow down enough because now I feel almost uncomfortably full. In retrospect this shouldn&#x27;t be surprising. Imagine eating a plate of spaghetti in a minute. Of course you&#x27;re going to be full.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;I&#x27;ve also noticed that a full pitcher seems like too much for a day. I&#x27;ll admit that I&#x27;ve been snacking on normal food a bit, so maybe that&#x27;s been making up for some of my calorie count, but I finished the pitcher I made for dinner two nights ago for breakfast this morning (that is, it lasted me almost two days). I haven&#x27;t been very active these past two days, so maybe I&#x27;m just not burning much energy on a daily basis.&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, I&#x27;ve found myself being actively hungry for something &lt;em&gt;other&lt;&#x2F;em&gt; than Soylent. As in, the idea of eating tasty food really appeals to me. I&#x27;m not sure if it&#x27;s because the bland taste is, well, bland, or because I&#x27;m missing some key nutrients (or at least nutrients that aren&#x27;t necessary but I had a habbit of getting a lot of before). I still feel full and satisfied after I drink it, but I have to will myself to drink it knowing that that will be the outcome; I don&#x27;t find myself actively wanting Soylent itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 162 lbs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Good.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: Day 2</title>
    <published>2014-08-13T00:00:00+00:00</published>
    <updated>2014-08-13T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-day-2/"/>
    <id>https://joshlf.com/posts/soylent-day-2/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-day-2/">&lt;p&gt;&lt;em&gt;[This post is part of a series on my month-long experiment with Soylent. See the &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;original post&lt;&#x2F;a&gt; for an introduction.]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In my &lt;a href=&quot;&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;&quot;&gt;previous post&lt;&#x2F;a&gt;, I mentioned that I had found drinking Soylent to be unpleasant, and that it gave me a queasy feeling in my stomach. I now think that that had mostly to do with the large quantity of candy I had eaten just beforehand because, when I had my first Soylent today (even without the strawberries that I blended in yesterday to make it palatable), I didn&#x27;t find it nearly as unpleasant. Since I was more hungry, the sweetness was more enjoyable.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Besides the sweetness, I had made another mistake. I found a post online by a guy discussing the flatulence issue. He said that he hadn&#x27;t had it so bad, but his wife had. He figured out that it was because she was drinking it quickly like she might a normal beverage, and they found that when she stopped drinking so quickly, and instead sipped it slowly like one might eat a normal meal, the issue subsided. I haven&#x27;t yet had any issues with gas, but his point about drinking quickly was nonetheless relevant: I had drunk my Soylent quickly, and that probably contributed to my feeling queasy - it was like eating a big hamburger in under a minute. Today, I tried more slowly, and found that it helped.&lt;&#x2F;p&gt;
&lt;p&gt;Also, I should note one thing that I forgot to mention in the original post: I&#x27;m going to set a rule for myself that I can eat less than a day&#x27;s serving of Soylent if I want to (though not by supplementing it with other food), but I won&#x27;t ever eat more than a day&#x27;s serving. If I end up getting really hungry this way, I may stop after a week or so, but I want to try it for at least some amount of time to see how it feels.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vitals&quot;&gt;Vitals&lt;&#x2F;h2&gt;
&lt;p&gt;Today is the first day I&#x27;m taking any vitals. I probably should have started yesterday - oh well. I don&#x27;t have much equipment, so for the time being I&#x27;m just going to take my weight, and also record some subjective stuff like how healthy I feel (not mood, but physical health).&lt;&#x2F;p&gt;
&lt;p&gt;Also, I should note that weight fluctuates a lot day-to-day based on things like how late you ate the night before and how early you weigh yourself and so on. For that reason, I&#x27;d advise you not to read too much into the minor fluctuations, but pay attention rather to the overall trends. I&#x27;ll try to write about these trends in any multi-day summaries that I write.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;objective-vitals&quot;&gt;Objective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Weight: 166 lbs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;subjective-vitals&quot;&gt;Subjective Vitals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical health: Decent. I&#x27;ve got a bit of a headache, but I didn&#x27;t sleep a full night, so that&#x27;s probably why.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Soylent: The Blog Series</title>
    <published>2014-08-12T00:00:00+00:00</published>
    <updated>2014-08-12T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/soylent-the-blog-series/"/>
    <id>https://joshlf.com/posts/soylent-the-blog-series/</id>
    
      
    <category term="Soylent"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/soylent-the-blog-series/">&lt;p&gt;For the next month, I will not be eating normal food, but will instead be subsisting almost exclusively off of &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.soylent.me&#x2F;&quot;&gt;Soylent&lt;&#x2F;a&gt;. Soylent is a a powder which contains all of the nutrients that a human body needs to be healthy (at least, as far as modern science knows). When mixed with water, it yields a bland, brownish liquid that you drink.&lt;&#x2F;p&gt;
&lt;p&gt;What exactly do we call this concoction? The side of the box it was shipped in bears the tagline &quot;powdered food.&quot; Some have referred to it as a &quot;food alternative,&quot; or have suggested that they are eating Soylent instead of food. Most importantly, there&#x27;s no shortage of articles and blog posts discussing the various philosophical aspects of Soylent - is it food? Will people want to eat it? Isn&#x27;t food meant to be social? I have thoughts on these questions, but that&#x27;s not the point of this blog series. I may write a post on the subject, but for the most part this series is about my personal experience with Soylent, and the practicalities of using it as a replacement for a traditional diet.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;the-blog-series&quot;&gt;The Blog Series&lt;&#x2F;h2&gt;
&lt;p&gt;As I mentioned, this blog series is focused primarily on my experience with Soylent and the practicalities of using it as a replacement for a traditional diet. I&#x27;m going to use it as a sort of scientific log book or journal, documenting how the Soylent tastes, how it&#x27;s making me feel, whether I&#x27;ve stripped the paint off of any of my walls with my farts [&lt;a href=&quot;https:&#x2F;&#x2F;joshlf.com&#x2F;posts&#x2F;soylent-the-blog-series&#x2F;#1&quot;&gt;1&lt;&#x2F;a&gt;], and so on. I hope to post once a day. I expect that most posts will be fairly brief, and not much will change day-to-day (&quot;Still haven&#x27;t died; my housemates still hate my intestines.&quot;). From time to time I may do a review post noting trends that I&#x27;ve seen over the past x amount of time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-why&quot;&gt;The Why&lt;&#x2F;h2&gt;
&lt;p&gt;A reasonable question to ask is why - why am eating Soylent for a month? That&#x27;s easy - I&#x27;m doing it to see how it affects me so that in the future I&#x27;ll know if it&#x27;s a viable option (I&#x27;m on meal plan at college this year, so I won&#x27;t be using Soylent long-term for at least another nine months). The harder question is - why would I want to do it long term?&lt;&#x2F;p&gt;
&lt;p&gt;I have two main reasons. First, it&#x27;s easy. I&#x27;m really not a fan of the chores of life - the stuff that you do so you can keep living the parts of life that you look forward to. While I don&#x27;t consider eating to be a chore, it&#x27;s a different story for cooking, cleaning, and shopping for food. When my life is relaxed and not too busy, this isn&#x27;t such a big deal, but when it does get busy, time spent on those chores is time that I invariably don&#x27;t spend on more enjoyable activities.&lt;&#x2F;p&gt;
&lt;p&gt;Second, it&#x27;s healthy. I&#x27;m something of a garbage truck when it comes to food - I basically just eat whatever tastes good. This is fun while I&#x27;m young, but it&#x27;s clearly going to come back to bite me later in life. And, yes, eating a normal healthy diet is obviously an option, but I know myself, and I know that planning, executing, and, most importantly, paying for a healthy diet isn&#x27;t something I&#x27;m realistically going to do. Soylent is (as far as we know) very healthy, and it&#x27;s cheap and requires no effort or planning.&lt;&#x2F;p&gt;
&lt;p&gt;Now, there&#x27;s more to it than just that, but those are my primary reasons - the rest is just minutiae. Hopefully this little primer on my thinking will give context to this blog series and my opinions on and reactions to different aspects of Soylent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-what&quot;&gt;The What&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;So you&#x27;re really eating nothing but Soylent for a month?&quot; Well, no. Not exactly. What I want to do is test the efficacy of living off of it exclusively. But I don&#x27;t think that occasionally eating normal food is going to mean that my results suddenly are wildly inaccurate. I&#x27;m not trying to get precise numerical results - I&#x27;m just trying to get a general sense of how an all-Soylent diet affects me. In light of this caveat, I&#x27;m going to allow myself a few exceptions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An occasional snack or desert (so long as it doesn&#x27;t constitute a meaningful portion of my daily intake)&lt;&#x2F;li&gt;
&lt;li&gt;Social eating (going out to dinner with friends and whatnot). I&#x27;ll try to have Soylent in social situations whenever possible, but I&#x27;m obviously not going to bring a water bottle of Soylent to a restaurant.&lt;&#x2F;li&gt;
&lt;li&gt;Additives to make the Soylent itself taste better (so long as they don&#x27;t constitute a meaningful portion of my daily intake)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nonetheless, I&#x27;m going to try to stick as closely as possible to the spirit of going &quot;all Soylent.&quot; I may adjust how &lt;em&gt;much&lt;&#x2F;em&gt; Soylent I eat (for example, if I&#x27;m not getting enough calories each day), but in general, I won&#x27;t introduce non-Soylent food as a significant part of my diet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-unboxing&quot;&gt;The Unboxing&lt;&#x2F;h2&gt;
&lt;p&gt;When you order Soylent, the first thing that you get is not the Soylent itself, but a &quot;starter kit.&quot; It includes a pitcher for mixing and storing the Soylent, and a measuring cup which holds one half serving&#x27;s amount of Soylent powder.&lt;&#x2F;p&gt;
&lt;p&gt;Then comes the real behemoth - the Soylent itself. I ordered a month&#x27;s supply of Soylent, so it came in a box big enough to uncomfortably smuggle a human. Inside the box were four smaller boxes, each containing a week&#x27;s supply of Soylent and a small instruction booklet.&lt;&#x2F;p&gt;
&lt;p&gt;The booklet is labeled &quot;Soylent 1.0 Release Notes,&quot; a clear nod to Soylent&#x27;s open source ethos.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_box_9042216c5172726a78d731fdd20b2334.jpg&quot; alt=&quot;A large unopened Soylent shipping box&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_box_open_4d7cf27b60a8a038293724786e377461.jpg&quot; alt=&quot;An open Soylent shipping box with smaller boxes inside&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_week_3ff8e7b2bcfd6854f8e0a823e409f64b.jpg&quot; alt=&quot;A weekly Soylent box with an instruction booklet&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Soylent itself comes in seven packages - one per day - and seven small bottles of oil blend. A few of the ingredients in Soylent are sourced from animal products, and in an effort to remain vegan-friendly, these are packaged separately in the oil blend. Soylent&#x27;s makers claim they hope to eventually find vegan alternatives so that they can sell Soylent as the powder alone.&lt;&#x2F;p&gt;
&lt;p&gt;The pouches themselves are, like everything in the box and the box itself, styled minimalistically - plain black text on a white background. They bear only the logo and nutrition facts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_pouch_and_pitcher_42768f76f6ee934476d12946147eff45.jpg&quot; alt=&quot;A Soylent pouch next to the included pitcher and oil bottle&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The powder is beige and quite dense. If you drop the pouch on the counter, the powder settles with a single muted thud. It gives off a pungent, sickly sweet smell (I had just eaten five servings of Twizzlers as a last hurrah, so that probably lowered my tolerance).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_powder_c8cbc60bd10c31fc0122948c1078ecfa.jpg&quot; alt=&quot;Soylent powder inside an opened pouch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-preparation&quot;&gt;The Preparation&lt;&#x2F;h2&gt;
&lt;p&gt;Once Soylent has been mixed with water, it has a recommended fridge lifetime of 48 hours. The instruction booklet suggests ways to make single servings if you aren&#x27;t going to eat a full day&#x27;s worth within that time. However, I&#x27;m going all in on this, so it&#x27;s not a problem.&lt;&#x2F;p&gt;
&lt;p&gt;The pitcher that is included in the starter kit holds one day&#x27;s worth of Soylent - one pouch and one vial of oil blend mixed into the proper amount of water. This means that it conveniently serves as a measuring device - just dump the powder and the oil in and then fill the rest up with water.&lt;&#x2F;p&gt;
&lt;p&gt;The instruction booklet recommends a slightly more nuanced procedure. First, dump the powder into the pitcher. Then fill most of the way up with water. Shake vigorously for 30 seconds. Then add the oil blend and fill the remaining space with water. Shake vigorously again for 30 seconds.&lt;&#x2F;p&gt;
&lt;p&gt;When I first added the water to the pitcher of powder, it looked as though the powder was somehow resistant to mixing with the water. However, probably due to the fine grain of the powder, after 30 seconds of vigorous shaking, the mixture was completely mixed. The whole thing was pretty heavy, and after adding the oil blend and shaking for another 30 seconds, my arms were pretty tired.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_powder_in_pitcher_bc2515efda92d5013cd6c13db72bbb28.jpg&quot; alt=&quot;Soylent powder poured into the pitcher&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;content&#x2F;soylent_and_oil_cd6783046d4b50f033d559108e697ebd.jpg&quot; alt=&quot;Soylent powder and oil blend in the pitcher&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-consumption&quot;&gt;The Consumption&lt;&#x2F;h2&gt;
&lt;p&gt;The resultant liquid has the same sickly sweet smell as the powder, and I was afraid that drinking it would be quite unpleasant. However, it didn&#x27;t taste nearly as bad as it smelled. I&#x27;d heard reports that it had a grainy texture, but I didn&#x27;t find that to be an accurate description. I could certainly tell that it had been mixed from a powder, but the powder was fine enough that I couldn&#x27;t make out the individual grains. Instead, it had a smooth but heavy texture somewhat like a well-blended milkshake made from dense ice cream.&lt;&#x2F;p&gt;
&lt;p&gt;However, there was something off-putting about it. I couldn&#x27;t place my finger on what it was, but I found that drinking it gave me a sensation like what I was drinking tasted actively bad, though it didn&#x27;t actually taste that way. In order to make it more palatable, I blended in four frozen strawberries with a glass (about one serving, or one third of a full day&#x27;s worth). This helped, but I still found it off-putting. When I drank water shortly after drinking the Soylent, I got a mild queasy feeling in my stomach.&lt;&#x2F;p&gt;
&lt;p&gt;I have a few hypotheses here. First, maybe it just takes some getting used to. Second, maybe I shouldn&#x27;t have eaten it on a full stomach (remember those Twizzlers?). Or maybe it&#x27;s something else. I&#x27;m going to look around online tonight and see what other people say about it. I&#x27;m sure there&#x27;s no shortage of advice online about what to expect and how to make Soylent more palatable. I&#x27;ll write about what I find in tomorrow&#x27;s post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;That wraps up this first post. I expect that future posts will be much shorter. Please comment or &lt;a href=&quot;mailto:hello@joshlf.com&quot;&gt;write&lt;&#x2F;a&gt; with questions, thoughts, or suggestions!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a id=&quot;1&quot;&gt;&lt;&#x2F;a&gt;[1] Many users have reported having pretty bad gas while their digestive tracts adjust; it usually goes away pretty quickly (a few days to a week).&lt;&#x2F;p&gt;
</content>
  </entry>
    
  
    
    
  <entry xml:lang="en">
    <title>Boston Go Meetup</title>
    <published>2014-03-08T00:00:00+00:00</published>
    <updated>2014-03-08T00:00:00+00:00</updated>
    
    <author>
      <name>Josh Liebow-Feeser</name>
    </author>
    
    <link rel="alternate" type="text/html" href="https://joshlf.com/posts/boston-go-meetup/"/>
    <id>https://joshlf.com/posts/boston-go-meetup/</id>
    
      
    <category term="Go"/>
      
    <category term="Reflection"/>
      
    
    <content type="html" xml:base="https://joshlf.com/posts/boston-go-meetup/">&lt;p&gt;Yesterday (Thursday, March 7th, 2014), I gave a talk on reflection in Go at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;plus.google.com&#x2F;u&#x2F;0&#x2F;communities&#x2F;103337146295481792015&quot;&gt;Boston Go Meetup&lt;&#x2F;a&gt;. It was a blast, and there were a bunch of great people there (and other great talks). Here are the &lt;a href=&quot;&#x2F;files&#x2F;talks&#x2F;Reflection.pdf&quot;&gt;slides from that talk&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;</content>
  </entry>
    
  
    
    
  
    
    
  
    
    
  
</feed>
