This commit is contained in:
Nilstrieb 2022-07-22 14:19:24 +00:00
parent df08ff65e1
commit be75277094
5 changed files with 11 additions and 11 deletions

View file

@ -1,6 +1,6 @@
<!doctype html><html lang=en><head><title>Box Is a Unique Type :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="About better aliasing semantics for `Box`"><meta name=keywords content="box,noalias"><meta name=robots content="noodp"><link rel=canonical href=/posts/box-is-a-unique-type/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="article"><meta property="og:title" content="Box Is a Unique Type"><meta property="og:description" content="About better aliasing semantics for `Box`"><meta property="og:url" content="/posts/box-is-a-unique-type/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><meta property="article:published_time" content="2022-07-22 00:00:00 +0000 UTC"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=post><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-22</span>
<span class=post-author>:: Nilstrieb</span>
<span class=post-reading-time>:: 10 min read (2080 words)</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
<span class=post-reading-time>:: 10 min read (2081 words)</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content><div><p>We have all used <code>Box&lt;T></code> before in our Rust code. It&rsquo;s a glorious type, with great ergonomics
and flexibitility. We can use it to put our values on the heap, but it can do even more
than that!</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>Fields</span> {
@ -43,14 +43,14 @@ well here. But what allows it to make this optimization? Taking a look at the ge
reveals the solution: (severely shortened to only show the relevant parts)</p><pre tabindex=0><code class=language-llvmir data-lang=llvmir>define void @takes_box_and_ptr_to_it(i8* noalias %0, i8* %ptr) {
</code></pre><p>See the little attribute on the first parameter called <code>noalias</code>? That&rsquo;s what&rsquo;s doing the magic here.
<code>noalias</code> is an LLVM attribute on pointers that allows for various optimizations. If there are two pointers,
and at least one of them is <code>noalias</code>, there are some restrictions around the two:</p><ul><li>If one of them writes, they must not point to the same value (alias each other)</li><li>If neither of them writes, they can alias just fine.
and at least one of them is <code>noalias</code>, there are some restrictions around the two. Approximately:</p><ul><li>If one of them writes, they must not point to the same value (alias each other)</li><li>If neither of them writes, they can alias just fine.
Therefore, we also apply <code>noalias</code> to <code>&mut T</code> and <code>&T</code> (if it doesn&rsquo;t contain interior mutability through
<code>UnsafeCell&lt;T></code>, since they uphold these rules.</li></ul><p>This might sound familiar to you if you&rsquo;re a viewer of <a href=https://twitter.com/jonhoo>Jon Gjengset</a>&rsquo;s content (which I can highly recommend). Jon has made an entire video about this before, since his crate <code>left-right</code>
was affected by this (<a href=https://youtu.be/EY7Wi9fV5bk)>https://youtu.be/EY7Wi9fV5bk)</a>.</p><p>If you&rsquo;re looking for <em>any</em> hint that using box emits <code>noalias</code>, you have to look no further than the documentation
for <a href=https://doc.rust-lang.org/nightly/std/boxed/index.html#considerations-for-unsafe-code><code>std::boxed</code></a>. Well, the nightly or beta docs, because I only added this section very recently. For years, this behaviour was not really documented, and you had to
belong to the arcane circles of the select few who were aware of it. So lots of code was written thinking that box was &ldquo;just an
RAII pointer&rdquo; (a pointer that allocates the value in the constructor, and deallocates it in the destructor on drop) for all
pointers are concerned.</p><h1 id=stacked-borrows-and-miri>Stacked Borrows and Miri<a href=#stacked-borrows-and-miri class=hanchor arialabel=Anchor>&#8983;</a></h1><p><a href=https://github.com/rust-lang/miri>Miri</a> is an interpreter for Rust code with the goal of finding undefinde behaviour.
pointers are concerned.</p><h1 id=stacked-borrows-and-miri>Stacked Borrows and Miri<a href=#stacked-borrows-and-miri class=hanchor arialabel=Anchor>&#8983;</a></h1><p><a href=https://github.com/rust-lang/miri>Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour.
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.</p><p>I cannot recommend Miri highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions

View file

@ -51,7 +51,7 @@ reveals the solution: (severely shortened to only show the relevant parts)&lt;/p
&lt;pre tabindex="0">&lt;code class="language-llvmir" data-lang="llvmir">define void @takes_box_and_ptr_to_it(i8* noalias %0, i8* %ptr) {
&lt;/code>&lt;/pre>&lt;p>See the little attribute on the first parameter called &lt;code>noalias&lt;/code>? That&amp;rsquo;s what&amp;rsquo;s doing the magic here.
&lt;code>noalias&lt;/code> is an LLVM attribute on pointers that allows for various optimizations. If there are two pointers,
and at least one of them is &lt;code>noalias&lt;/code>, there are some restrictions around the two:&lt;/p>
and at least one of them is &lt;code>noalias&lt;/code>, there are some restrictions around the two. Approximately:&lt;/p>
&lt;ul>
&lt;li>If one of them writes, they must not point to the same value (alias each other)&lt;/li>
&lt;li>If neither of them writes, they can alias just fine.
@ -66,7 +66,7 @@ belong to the arcane circles of the select few who were aware of it. So lots of
RAII pointer&amp;rdquo; (a pointer that allocates the value in the constructor, and deallocates it in the destructor on drop) for all
pointers are concerned.&lt;/p>
&lt;h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri&lt;/h1>
&lt;p>&lt;a href="https://github.com/rust-lang/miri">Miri&lt;/a> is an interpreter for Rust code with the goal of finding undefinde behaviour.
&lt;p>&lt;a href="https://github.com/rust-lang/miri">Miri&lt;/a> is an interpreter for Rust code with the goal of finding undefined behaviour.
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
&lt;em>anything&lt;/em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.&lt;/p>