We have all used Box<T> before in our Rust code. It’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!

struct Fields {
@@ -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)

define void @takes_box_and_ptr_to_it(i8* noalias %0, i8* %ptr) {
 

See the little attribute on the first parameter called noalias? That’s what’s doing the magic here. noalias is an LLVM attribute on pointers that allows for various optimizations. If there are two pointers, -and at least one of them is noalias, there are some restrictions around the two:

  • If one of them writes, they must not point to the same value (alias each other)
  • If neither of them writes, they can alias just fine. +and at least one of them is noalias, there are some restrictions around the two. Approximately:

    • If one of them writes, they must not point to the same value (alias each other)
    • If neither of them writes, they can alias just fine. Therefore, we also apply noalias to &mut T and &T (if it doesn’t contain interior mutability through UnsafeCell<T>, since they uphold these rules.

    This might sound familiar to you if you’re a viewer of Jon Gjengset’s content (which I can highly recommend). Jon has made an entire video about this before, since his crate left-right was affected by this (https://youtu.be/EY7Wi9fV5bk).

    If you’re looking for any hint that using box emits noalias, you have to look no further than the documentation for std::boxed. 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 “just an RAII pointer” (a pointer that allocates the value in the constructor, and deallocates it in the destructor on drop) for all -pointers are concerned.

    Stacked Borrows and Miri

    Miri is an interpreter for Rust code with the goal of finding undefinde behaviour. +pointers are concerned.

    Stacked Borrows and Miri

    Miri 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, anything 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.

    I cannot recommend Miri highly enough for all unsafe code you’re writing (sadly support for some IO functions diff --git a/posts/index.xml b/posts/index.xml index 50a90de..1b9c984 100644 --- a/posts/index.xml +++ b/posts/index.xml @@ -51,7 +51,7 @@ 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> +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. @@ -66,7 +66,7 @@ belong to the arcane circles of the select few who were aware of it. So lots of 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</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. +<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> diff --git a/tags/rust/index.xml b/tags/rust/index.xml index f104886..316b3be 100644 --- a/tags/rust/index.xml +++ b/tags/rust/index.xml @@ -51,7 +51,7 @@ 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> +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. @@ -66,7 +66,7 @@ belong to the arcane circles of the select few who were aware of it. So lots of 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</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. +<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> diff --git a/tags/unsafe-code/index.xml b/tags/unsafe-code/index.xml index 7c1afa2..10caa16 100644 --- a/tags/unsafe-code/index.xml +++ b/tags/unsafe-code/index.xml @@ -51,7 +51,7 @@ 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> +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. @@ -66,7 +66,7 @@ belong to the arcane circles of the select few who were aware of it. So lots of 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</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. +<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>