mirror of
https://github.com/Noratrieb/blog.git
synced 2026-01-14 20:35:02 +01:00
deploy: 8ed5d72bc9
This commit is contained in:
parent
3a526b579c
commit
4d6197c1aa
5 changed files with 132 additions and 92 deletions
46
index.xml
46
index.xml
|
|
@ -56,8 +56,9 @@ and at least one of them is <code>noalias</code>, there are some restricti
|
||||||
<li>If one of them writes, they must not point to the same value (alias each other)</li>
|
<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.
|
<li>If neither of them writes, they can alias just fine.
|
||||||
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
||||||
<code>UnsafeCell&lt;T&gt;</code>, since they uphold these rules.</li>
|
<code>UnsafeCell&lt;T&gt;</code>), since they uphold these rules.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>For more info on <code>noalias</code>, see <a href="https://llvm.org/docs/LangRef.html#parameter-attributes">LLVMs LangRef</a>.</p>
|
||||||
<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>
|
<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>
|
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
|
<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
|
||||||
|
|
@ -66,13 +67,13 @@ 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
|
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>
|
pointers are concerned.</p>
|
||||||
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
||||||
<p>TODO: introduce UB by explaining how it allows optimizations like the one above, don&rsquo;t talk in standardese</p>
|
<p>So, LLVM was completely correct in optimizing our code to make the assert fail. But what exactly gave it permission to do so?
|
||||||
<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). Undefined behaviour is at the root of many modern compiler optimizations. But what is undefined behaviour?
|
||||||
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
|
UB represents a contract between the program and the compiler. The compiler assumes that UB will not happen, and can therefore optimize based
|
||||||
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
|
on these assumptions. Examples of UB also include use-after-free, out of bounds reads or data races. If UB is executed, <em>anything</em> can happen,
|
||||||
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.</p>
|
including segmentation faults, silent memory corruption, leakage of private keys or exactly what you intended to happen.</p>
|
||||||
<p>I cannot recommend Miri highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions
|
<p><a href="https://github.com/rust-lang/miri">Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour in Rust. I cannot recommend Miri
|
||||||
and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
||||||
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
||||||
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
||||||
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
|
|
@ -137,29 +138,36 @@ other box-exclusive features it offers. Even worse is <code>string_cache</
|
||||||
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
||||||
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
||||||
user code ever having access to it.</p>
|
user code ever having access to it.</p>
|
||||||
<p>There are also several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
<p>There are several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
||||||
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
||||||
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
||||||
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
||||||
|
<p>But there are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
||||||
|
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.
|
||||||
|
So if box stayed unique, people could also just pick up that crate as a dependency and use the aliasable box from there instead of
|
||||||
|
having to write their own. Interestingly, this crate also provides a <code>Vec&lt;T&gt;</code>, even though <code>Vec&lt;T&gt;</code> can currently be aliased in practice and
|
||||||
|
in the current version of stacked borrows. just fine, although it&rsquo;s also not clear whether we want to keep it like this, but I
|
||||||
|
don&rsquo;t think this can reasonable be changed.</p>
|
||||||
<h1 id="noalias-noslow">noalias, noslow</h1>
|
<h1 id="noalias-noslow">noalias, noslow</h1>
|
||||||
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
||||||
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
||||||
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
||||||
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
||||||
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
||||||
<p>I have not yet benchmarked ecosystem crates without box noalias and don&rsquo;t have the capacity to do so right now, so I would be very
|
<p>I have also benchmarked a few crates from the ecosystem with and without noalias on box, and the <a href="https://gist.github.com/Nilstrieb/9a0751fb9fd1044a30ab55cef9a7d335">results</a>
|
||||||
grateful if anyone wanted to pick that up and report the results.</p>
|
were inconclusive. (At the time of writing, only regex-syntax, tokio, and syn have been benchmarked.) regex-syntax showed no changes. Tokio showed a few improvements without noalias
|
||||||
<p>There are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
which is very weird, so maybe the benchmarks aren&rsquo;t really good or something else was going on. And syn tended towards minor regressions without noalias, but the benchmarks had high
|
||||||
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.</p>
|
jitter so no real conclusion can be reached from this either, at least in my eyes, but I don&rsquo;t have a lot of experience with benchmarks. Therefore, I would love for more people
|
||||||
|
to benchmark more crates, especially if you have more experience with benchmarks.</p>
|
||||||
<h1 id="a-way-forward">a way forward</h1>
|
<h1 id="a-way-forward">a way forward</h1>
|
||||||
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions in ecosystem crates,
|
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions, they are not significant enough
|
||||||
the overall tradeoff goes against the current box behaviour. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely
|
to justify boxes uniqueness. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it
|
||||||
remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it just like a <code>*const T</code> for the purposes of aliasing. This will make it more
|
just like a <code>*const T</code> for the purposes of aliasing. This will make it more predictable for unsafe code, and is a step forward towards less magic from <code>Box&lt;T&gt;</code>.</p>
|
||||||
predictable for unsafe code, and comes at none or only a minor performance cost.</p>
|
<p>But the performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
||||||
<p>But this performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
|
||||||
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
||||||
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
||||||
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
||||||
inside the standard library would have to be removed.</p>
|
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
|
||||||
|
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p>
|
||||||
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
||||||
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
||||||
|
|
@ -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>
|
<!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-author>:: Nilstrieb</span>
|
||||||
<span class=post-reading-time>:: 10 min read (2110 words)</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>
|
<span class=post-reading-time>:: 12 min read (2351 words)</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>
|
||||||
#<a href=/tags/unsafe-code/>unsafe code</a> </span><div class=post-content><div><p>We have all used <code>Box<T></code> before in our Rust code. It’s a glorious type, with great ergonomics
|
#<a href=/tags/unsafe-code/>unsafe code</a> </span><div class=post-content><div><p>We have all used <code>Box<T></code> 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
|
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> {
|
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> {
|
||||||
|
|
@ -45,16 +45,17 @@ reveals the solution: (severely shortened to only show the relevant parts)</p><p
|
||||||
<code>noalias</code> is an LLVM attribute on pointers that allows for various optimizations. If there are two pointers,
|
<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. 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.
|
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’t contain interior mutability through
|
Therefore, we also apply <code>noalias</code> to <code>&mut T</code> and <code>&T</code> (if it doesn’t contain interior mutability through
|
||||||
<code>UnsafeCell<T></code>, since they uphold these rules.</li></ul><p>This might sound familiar to you if you’re a viewer of <a href=https://twitter.com/jonhoo>Jon Gjengset</a>’s content (which I can highly recommend). Jon has made an entire video about this before, since his crate <code>left-right</code>
|
<code>UnsafeCell<T></code>), since they uphold these rules.</li></ul><p>For more info on <code>noalias</code>, see <a href=https://llvm.org/docs/LangRef.html#parameter-attributes>LLVMs LangRef</a>.</p><p>This might sound familiar to you if you’re a viewer of <a href=https://twitter.com/jonhoo>Jon Gjengset</a>’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’re looking for <em>any</em> hint that using box emits <code>noalias</code>, you have to look no further than the documentation
|
was affected by this (<a href=https://youtu.be/EY7Wi9fV5bk)>https://youtu.be/EY7Wi9fV5bk)</a>.</p><p>If you’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
|
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 “just an
|
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
|
RAII pointer” (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>⌗</a></h1><p>TODO: introduce UB by explaining how it allows optimizations like the one above, don’t talk in standardese</p><p><a href=https://github.com/rust-lang/miri>Miri</a> is an interpreter for Rust code with the goal of finding undefined 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>⌗</a></h1><p>So, LLVM was completely correct in optimizing our code to make the assert fail. But what exactly gave it permission to do so?
|
||||||
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
|
Undefined Behaviour (UB for short). Undefined behaviour is at the root of many modern compiler optimizations. But what is undefined behaviour?
|
||||||
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
|
UB represents a contract between the program and the compiler. The compiler assumes that UB will not happen, and can therefore optimize based
|
||||||
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’re writing (sadly support for some IO functions
|
on these assumptions. Examples of UB also include use-after-free, out of bounds reads or data races. If UB is executed, <em>anything</em> can happen,
|
||||||
and FFI is still lacking, and it’s still very slow).</p><p>So, let’s see whether our code contains UB. It has to, since otherwise the optimizer wouldn’t be allowed to change
|
including segmentation faults, silent memory corruption, leakage of private keys or exactly what you intended to happen.</p><p><a href=https://github.com/rust-lang/miri>Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour in Rust. I cannot recommend Miri
|
||||||
|
highly enough for all unsafe code you’re writing (sadly support for some IO functions and FFI is still lacking, and it’s still very slow).</p><p>So, let’s see whether our code contains UB. It has to, since otherwise the optimizer wouldn’t be allowed to change
|
||||||
observable behaviour (since the assert doesn’t fail in debug mode). <code>$ cargo miri run</code>…</p><pre tabindex=0><code class=language-rust,ignore data-lang=rust,ignore>error: Undefined Behavior: attempting a read access using <3314> at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
observable behaviour (since the assert doesn’t fail in debug mode). <code>$ cargo miri run</code>…</p><pre tabindex=0><code class=language-rust,ignore data-lang=rust,ignore>error: Undefined Behavior: attempting a read access using <3314> at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
--> src/main.rs:2:26
|
--> src/main.rs:2:26
|
||||||
|
|
|
|
||||||
|
|
@ -105,22 +106,29 @@ This is fairly inconvenient, but totally acceptable. There are bigger problems t
|
||||||
that want to expose a generic interface over any type. Users like to choose box, and sometimes <em>have</em> to chose box because of
|
that want to expose a generic interface over any type. Users like to choose box, and sometimes <em>have</em> to chose box because of
|
||||||
other box-exclusive features it offers. Even worse is <code>string_cache</code>, which is extremely hard to fix.</p><p>Then last but not least, there’s the opinionated fact that <code>Box<T></code> shall be implementable entirely in user code. While we are
|
other box-exclusive features it offers. Even worse is <code>string_cache</code>, which is extremely hard to fix.</p><p>Then last but not least, there’s the opinionated fact that <code>Box<T></code> shall be implementable entirely in user code. While we are
|
||||||
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
||||||
user code ever having access to it.</p><p>There are also several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
user code ever having access to it.</p><p>There are several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
||||||
be said that <code>Box<T></code> <em>is</em> a very special type. It’s just like a <code>T</code>, but on the heap. Using this mental model, it’s very easy to
|
be said that <code>Box<T></code> <em>is</em> a very special type. It’s just like a <code>T</code>, but on the heap. Using this mental model, it’s very easy to
|
||||||
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
||||||
and I prefer the mental model of “reference that manages its own lifetime”, which doesn’t imply uniqueness.</p><h1 id=noalias-noslow>noalias, noslow<a href=#noalias-noslow class=hanchor arialabel=Anchor>⌗</a></h1><p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn’t exist for fun, it’s something
|
and I prefer the mental model of “reference that manages its own lifetime”, which doesn’t imply uniqueness.</p><p>But there are also crates on <a href=https://crates.io/>crates.io</a> like <a href=https://crates.io/crates/aliasable>aliasable</a> that already
|
||||||
|
provide an aliasable version of <code>Box<T></code>, which is used by the self-referential type helper crate <a href=https://crates.io/crates/ouroboros>ouroboros</a>.
|
||||||
|
So if box stayed unique, people could also just pick up that crate as a dependency and use the aliasable box from there instead of
|
||||||
|
having to write their own. Interestingly, this crate also provides a <code>Vec<T></code>, even though <code>Vec<T></code> can currently be aliased in practice and
|
||||||
|
in the current version of stacked borrows. just fine, although it’s also not clear whether we want to keep it like this, but I
|
||||||
|
don’t think this can reasonable be changed.</p><h1 id=noalias-noslow>noalias, noslow<a href=#noalias-noslow class=hanchor arialabel=Anchor>⌗</a></h1><p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn’t exist for fun, it’s something
|
||||||
that can bring clear performance wins (for <code>noalias</code> on <code>&mut T</code>, those were measureable). So the only question remains:
|
that can bring clear performance wins (for <code>noalias</code> on <code>&mut T</code>, those were measureable). So the only question remains:
|
||||||
<strong>How much performance does <code>noalias</code> on <code>Box<T></code> give us now, and how many potential performance improvements could we get in the
|
<strong>How much performance does <code>noalias</code> on <code>Box<T></code> give us now, and how many potential performance improvements could we get in the
|
||||||
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href=https://github.com/rust-lang/rust/pull/99527><em>no</em> performance improvements</a>
|
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href=https://github.com/rust-lang/rust/pull/99527><em>no</em> performance improvements</a>
|
||||||
from being compiled with <code>noalias</code> on <code>Box<T></code>.</p><p>I have not yet benchmarked ecosystem crates without box noalias and don’t have the capacity to do so right now, so I would be very
|
from being compiled with <code>noalias</code> on <code>Box<T></code>.</p><p>I have also benchmarked a few crates from the ecosystem with and without noalias on box, and the <a href=https://gist.github.com/Nilstrieb/9a0751fb9fd1044a30ab55cef9a7d335>results</a>
|
||||||
grateful if anyone wanted to pick that up and report the results.</p><p>There are also crates on <a href=https://crates.io/>crates.io</a> like <a href=https://crates.io/crates/aliasable>aliasable</a> that already
|
were inconclusive. (At the time of writing, only regex-syntax, tokio, and syn have been benchmarked.) regex-syntax showed no changes. Tokio showed a few improvements without noalias
|
||||||
provide an aliasable version of <code>Box<T></code>, which is used by the self-referential type helper crate <a href=https://crates.io/crates/ouroboros>ouroboros</a>.</p><h1 id=a-way-forward>a way forward<a href=#a-way-forward class=hanchor arialabel=Anchor>⌗</a></h1><p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions in ecosystem crates,
|
which is very weird, so maybe the benchmarks aren’t really good or something else was going on. And syn tended towards minor regressions without noalias, but the benchmarks had high
|
||||||
the overall tradeoff goes against the current box behaviour. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely
|
jitter so no real conclusion can be reached from this either, at least in my eyes, but I don’t have a lot of experience with benchmarks. Therefore, I would love for more people
|
||||||
remove all uniqueness from <code>Box<T></code>, and treat it just like a <code>*const T</code> for the purposes of aliasing. This will make it more
|
to benchmark more crates, especially if you have more experience with benchmarks.</p><h1 id=a-way-forward>a way forward<a href=#a-way-forward class=hanchor arialabel=Anchor>⌗</a></h1><p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions, they are not significant enough
|
||||||
predictable for unsafe code, and comes at none or only a minor performance cost.</p><p>But this performance cost may be real, and especially the future optimization value can’t be certain. The current uniqueness guarantees of box
|
to justify boxes uniqueness. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely remove all uniqueness from <code>Box<T></code>, and treat it
|
||||||
|
just like a <code>*const T</code> for the purposes of aliasing. This will make it more predictable for unsafe code, and is a step forward towards less magic from <code>Box<T></code>.</p><p>But the performance cost may be real, and especially the future optimization value can’t be certain. The current uniqueness guarantees of box
|
||||||
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
||||||
<code>&'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/316>unclear</a>.
|
<code>&'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/316>unclear</a>.
|
||||||
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
||||||
inside the standard library would have to be removed.</p><p>I guess what I am wishing for are some good and flexible raw pointer types. But that’s still in the stars…</p><p>For more information about this topic, see <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/326>https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2022 Powered by <a href=http://gohugo.io>Hugo</a></span>
|
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
|
||||||
|
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p><p>I guess what I am wishing for are some good and flexible raw pointer types. But that’s still in the stars…</p><p>For more information about this topic, see <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/326>https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2022 Powered by <a href=http://gohugo.io>Hugo</a></span>
|
||||||
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
|
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
|
||||||
<script src=/assets/prism.js></script></div></body></html>
|
<script src=/assets/prism.js></script></div></body></html>
|
||||||
|
|
@ -56,8 +56,9 @@ and at least one of them is <code>noalias</code>, there are some restricti
|
||||||
<li>If one of them writes, they must not point to the same value (alias each other)</li>
|
<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.
|
<li>If neither of them writes, they can alias just fine.
|
||||||
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
||||||
<code>UnsafeCell&lt;T&gt;</code>, since they uphold these rules.</li>
|
<code>UnsafeCell&lt;T&gt;</code>), since they uphold these rules.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>For more info on <code>noalias</code>, see <a href="https://llvm.org/docs/LangRef.html#parameter-attributes">LLVMs LangRef</a>.</p>
|
||||||
<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>
|
<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>
|
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
|
<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
|
||||||
|
|
@ -66,13 +67,13 @@ 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
|
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>
|
pointers are concerned.</p>
|
||||||
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
||||||
<p>TODO: introduce UB by explaining how it allows optimizations like the one above, don&rsquo;t talk in standardese</p>
|
<p>So, LLVM was completely correct in optimizing our code to make the assert fail. But what exactly gave it permission to do so?
|
||||||
<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). Undefined behaviour is at the root of many modern compiler optimizations. But what is undefined behaviour?
|
||||||
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
|
UB represents a contract between the program and the compiler. The compiler assumes that UB will not happen, and can therefore optimize based
|
||||||
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
|
on these assumptions. Examples of UB also include use-after-free, out of bounds reads or data races. If UB is executed, <em>anything</em> can happen,
|
||||||
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.</p>
|
including segmentation faults, silent memory corruption, leakage of private keys or exactly what you intended to happen.</p>
|
||||||
<p>I cannot recommend Miri highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions
|
<p><a href="https://github.com/rust-lang/miri">Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour in Rust. I cannot recommend Miri
|
||||||
and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
||||||
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
||||||
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
||||||
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
|
|
@ -137,29 +138,36 @@ other box-exclusive features it offers. Even worse is <code>string_cache</
|
||||||
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
||||||
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
||||||
user code ever having access to it.</p>
|
user code ever having access to it.</p>
|
||||||
<p>There are also several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
<p>There are several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
||||||
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
||||||
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
||||||
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
||||||
|
<p>But there are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
||||||
|
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.
|
||||||
|
So if box stayed unique, people could also just pick up that crate as a dependency and use the aliasable box from there instead of
|
||||||
|
having to write their own. Interestingly, this crate also provides a <code>Vec&lt;T&gt;</code>, even though <code>Vec&lt;T&gt;</code> can currently be aliased in practice and
|
||||||
|
in the current version of stacked borrows. just fine, although it&rsquo;s also not clear whether we want to keep it like this, but I
|
||||||
|
don&rsquo;t think this can reasonable be changed.</p>
|
||||||
<h1 id="noalias-noslow">noalias, noslow</h1>
|
<h1 id="noalias-noslow">noalias, noslow</h1>
|
||||||
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
||||||
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
||||||
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
||||||
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
||||||
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
||||||
<p>I have not yet benchmarked ecosystem crates without box noalias and don&rsquo;t have the capacity to do so right now, so I would be very
|
<p>I have also benchmarked a few crates from the ecosystem with and without noalias on box, and the <a href="https://gist.github.com/Nilstrieb/9a0751fb9fd1044a30ab55cef9a7d335">results</a>
|
||||||
grateful if anyone wanted to pick that up and report the results.</p>
|
were inconclusive. (At the time of writing, only regex-syntax, tokio, and syn have been benchmarked.) regex-syntax showed no changes. Tokio showed a few improvements without noalias
|
||||||
<p>There are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
which is very weird, so maybe the benchmarks aren&rsquo;t really good or something else was going on. And syn tended towards minor regressions without noalias, but the benchmarks had high
|
||||||
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.</p>
|
jitter so no real conclusion can be reached from this either, at least in my eyes, but I don&rsquo;t have a lot of experience with benchmarks. Therefore, I would love for more people
|
||||||
|
to benchmark more crates, especially if you have more experience with benchmarks.</p>
|
||||||
<h1 id="a-way-forward">a way forward</h1>
|
<h1 id="a-way-forward">a way forward</h1>
|
||||||
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions in ecosystem crates,
|
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions, they are not significant enough
|
||||||
the overall tradeoff goes against the current box behaviour. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely
|
to justify boxes uniqueness. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it
|
||||||
remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it just like a <code>*const T</code> for the purposes of aliasing. This will make it more
|
just like a <code>*const T</code> for the purposes of aliasing. This will make it more predictable for unsafe code, and is a step forward towards less magic from <code>Box&lt;T&gt;</code>.</p>
|
||||||
predictable for unsafe code, and comes at none or only a minor performance cost.</p>
|
<p>But the performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
||||||
<p>But this performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
|
||||||
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
||||||
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
||||||
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
||||||
inside the standard library would have to be removed.</p>
|
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
|
||||||
|
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p>
|
||||||
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
||||||
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
||||||
|
|
@ -56,8 +56,9 @@ and at least one of them is <code>noalias</code>, there are some restricti
|
||||||
<li>If one of them writes, they must not point to the same value (alias each other)</li>
|
<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.
|
<li>If neither of them writes, they can alias just fine.
|
||||||
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
||||||
<code>UnsafeCell&lt;T&gt;</code>, since they uphold these rules.</li>
|
<code>UnsafeCell&lt;T&gt;</code>), since they uphold these rules.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>For more info on <code>noalias</code>, see <a href="https://llvm.org/docs/LangRef.html#parameter-attributes">LLVMs LangRef</a>.</p>
|
||||||
<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>
|
<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>
|
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
|
<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
|
||||||
|
|
@ -66,13 +67,13 @@ 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
|
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>
|
pointers are concerned.</p>
|
||||||
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
||||||
<p>TODO: introduce UB by explaining how it allows optimizations like the one above, don&rsquo;t talk in standardese</p>
|
<p>So, LLVM was completely correct in optimizing our code to make the assert fail. But what exactly gave it permission to do so?
|
||||||
<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). Undefined behaviour is at the root of many modern compiler optimizations. But what is undefined behaviour?
|
||||||
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
|
UB represents a contract between the program and the compiler. The compiler assumes that UB will not happen, and can therefore optimize based
|
||||||
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
|
on these assumptions. Examples of UB also include use-after-free, out of bounds reads or data races. If UB is executed, <em>anything</em> can happen,
|
||||||
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.</p>
|
including segmentation faults, silent memory corruption, leakage of private keys or exactly what you intended to happen.</p>
|
||||||
<p>I cannot recommend Miri highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions
|
<p><a href="https://github.com/rust-lang/miri">Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour in Rust. I cannot recommend Miri
|
||||||
and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
||||||
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
||||||
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
||||||
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
|
|
@ -137,29 +138,36 @@ other box-exclusive features it offers. Even worse is <code>string_cache</
|
||||||
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
||||||
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
||||||
user code ever having access to it.</p>
|
user code ever having access to it.</p>
|
||||||
<p>There are also several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
<p>There are several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
||||||
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
||||||
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
||||||
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
||||||
|
<p>But there are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
||||||
|
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.
|
||||||
|
So if box stayed unique, people could also just pick up that crate as a dependency and use the aliasable box from there instead of
|
||||||
|
having to write their own. Interestingly, this crate also provides a <code>Vec&lt;T&gt;</code>, even though <code>Vec&lt;T&gt;</code> can currently be aliased in practice and
|
||||||
|
in the current version of stacked borrows. just fine, although it&rsquo;s also not clear whether we want to keep it like this, but I
|
||||||
|
don&rsquo;t think this can reasonable be changed.</p>
|
||||||
<h1 id="noalias-noslow">noalias, noslow</h1>
|
<h1 id="noalias-noslow">noalias, noslow</h1>
|
||||||
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
||||||
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
||||||
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
||||||
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
||||||
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
||||||
<p>I have not yet benchmarked ecosystem crates without box noalias and don&rsquo;t have the capacity to do so right now, so I would be very
|
<p>I have also benchmarked a few crates from the ecosystem with and without noalias on box, and the <a href="https://gist.github.com/Nilstrieb/9a0751fb9fd1044a30ab55cef9a7d335">results</a>
|
||||||
grateful if anyone wanted to pick that up and report the results.</p>
|
were inconclusive. (At the time of writing, only regex-syntax, tokio, and syn have been benchmarked.) regex-syntax showed no changes. Tokio showed a few improvements without noalias
|
||||||
<p>There are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
which is very weird, so maybe the benchmarks aren&rsquo;t really good or something else was going on. And syn tended towards minor regressions without noalias, but the benchmarks had high
|
||||||
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.</p>
|
jitter so no real conclusion can be reached from this either, at least in my eyes, but I don&rsquo;t have a lot of experience with benchmarks. Therefore, I would love for more people
|
||||||
|
to benchmark more crates, especially if you have more experience with benchmarks.</p>
|
||||||
<h1 id="a-way-forward">a way forward</h1>
|
<h1 id="a-way-forward">a way forward</h1>
|
||||||
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions in ecosystem crates,
|
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions, they are not significant enough
|
||||||
the overall tradeoff goes against the current box behaviour. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely
|
to justify boxes uniqueness. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it
|
||||||
remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it just like a <code>*const T</code> for the purposes of aliasing. This will make it more
|
just like a <code>*const T</code> for the purposes of aliasing. This will make it more predictable for unsafe code, and is a step forward towards less magic from <code>Box&lt;T&gt;</code>.</p>
|
||||||
predictable for unsafe code, and comes at none or only a minor performance cost.</p>
|
<p>But the performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
||||||
<p>But this performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
|
||||||
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
||||||
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
||||||
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
||||||
inside the standard library would have to be removed.</p>
|
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
|
||||||
|
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p>
|
||||||
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
||||||
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
||||||
|
|
@ -56,8 +56,9 @@ and at least one of them is <code>noalias</code>, there are some restricti
|
||||||
<li>If one of them writes, they must not point to the same value (alias each other)</li>
|
<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.
|
<li>If neither of them writes, they can alias just fine.
|
||||||
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
Therefore, we also apply <code>noalias</code> to <code>&amp;mut T</code> and <code>&amp;T</code> (if it doesn&rsquo;t contain interior mutability through
|
||||||
<code>UnsafeCell&lt;T&gt;</code>, since they uphold these rules.</li>
|
<code>UnsafeCell&lt;T&gt;</code>), since they uphold these rules.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>For more info on <code>noalias</code>, see <a href="https://llvm.org/docs/LangRef.html#parameter-attributes">LLVMs LangRef</a>.</p>
|
||||||
<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>
|
<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>
|
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
|
<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
|
||||||
|
|
@ -66,13 +67,13 @@ 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
|
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>
|
pointers are concerned.</p>
|
||||||
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
<h1 id="stacked-borrows-and-miri">Stacked Borrows and Miri</h1>
|
||||||
<p>TODO: introduce UB by explaining how it allows optimizations like the one above, don&rsquo;t talk in standardese</p>
|
<p>So, LLVM was completely correct in optimizing our code to make the assert fail. But what exactly gave it permission to do so?
|
||||||
<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). Undefined behaviour is at the root of many modern compiler optimizations. But what is undefined behaviour?
|
||||||
Undefined behaviour, UB for short, is behaviour of a program upon which no restrictions are imposed. If UB is executed,
|
UB represents a contract between the program and the compiler. The compiler assumes that UB will not happen, and can therefore optimize based
|
||||||
<em>anything</em> can happen, including segmentation faults, silent memory corruption, leakage of private keys or exactly
|
on these assumptions. Examples of UB also include use-after-free, out of bounds reads or data races. If UB is executed, <em>anything</em> can happen,
|
||||||
what you intended to happen. Examples of UB include use-after-free, out of bounds reads or data races.</p>
|
including segmentation faults, silent memory corruption, leakage of private keys or exactly what you intended to happen.</p>
|
||||||
<p>I cannot recommend Miri highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions
|
<p><a href="https://github.com/rust-lang/miri">Miri</a> is an interpreter for Rust code with the goal of finding undefined behaviour in Rust. I cannot recommend Miri
|
||||||
and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
highly enough for all unsafe code you&rsquo;re writing (sadly support for some IO functions and FFI is still lacking, and it&rsquo;s still very slow).</p>
|
||||||
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
<p>So, let&rsquo;s see whether our code contains UB. It has to, since otherwise the optimizer wouldn&rsquo;t be allowed to change
|
||||||
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
observable behaviour (since the assert doesn&rsquo;t fail in debug mode). <code>$ cargo miri run</code>&hellip;</p>
|
||||||
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
<pre tabindex="0"><code class="language-rust,ignore" data-lang="rust,ignore">error: Undefined Behavior: attempting a read access using &lt;3314&gt; at alloc1722[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
|
|
@ -137,29 +138,36 @@ other box-exclusive features it offers. Even worse is <code>string_cache</
|
||||||
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
<p>Then last but not least, there&rsquo;s the opinionated fact that <code>Box&lt;T&gt;</code> shall be implementable entirely in user code. While we are
|
||||||
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
many missing language features away from this being the case, the <code>noalias</code> case is also magic descended upon box itself, with no
|
||||||
user code ever having access to it.</p>
|
user code ever having access to it.</p>
|
||||||
<p>There are also several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
<p>There are several arguments in favour of box being unique and special cased here. To negate the last argument above, it can
|
||||||
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
be said that <code>Box&lt;T&gt;</code> <em>is</em> a very special type. It&rsquo;s just like a <code>T</code>, but on the heap. Using this mental model, it&rsquo;s very easy to
|
||||||
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
justify all the box magic and its unique behaviour. But in my opinion, this is not a useful mental model regarding unsafe code,
|
||||||
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
and I prefer the mental model of &ldquo;reference that manages its own lifetime&rdquo;, which doesn&rsquo;t imply uniqueness.</p>
|
||||||
|
<p>But there are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
||||||
|
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.
|
||||||
|
So if box stayed unique, people could also just pick up that crate as a dependency and use the aliasable box from there instead of
|
||||||
|
having to write their own. Interestingly, this crate also provides a <code>Vec&lt;T&gt;</code>, even though <code>Vec&lt;T&gt;</code> can currently be aliased in practice and
|
||||||
|
in the current version of stacked borrows. just fine, although it&rsquo;s also not clear whether we want to keep it like this, but I
|
||||||
|
don&rsquo;t think this can reasonable be changed.</p>
|
||||||
<h1 id="noalias-noslow">noalias, noslow</h1>
|
<h1 id="noalias-noslow">noalias, noslow</h1>
|
||||||
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
<p>There is one clear potential benefit from this box behaviour: ✨Optimizations✨. <code>noalias</code> doesn&rsquo;t exist for fun, it&rsquo;s something
|
||||||
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
that can bring clear performance wins (for <code>noalias</code> on <code>&amp;mut T</code>, those were measureable). So the only question remains:
|
||||||
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
<strong>How much performance does <code>noalias</code> on <code>Box&lt;T&gt;</code> give us now, and how many potential performance improvements could we get in the
|
||||||
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
future?</strong> For the latter, there is no simple answer. For the former, there is. <code>rustc</code> has <a href="https://github.com/rust-lang/rust/pull/99527"><em>no</em> performance improvements</a>
|
||||||
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
from being compiled with <code>noalias</code> on <code>Box&lt;T&gt;</code>.</p>
|
||||||
<p>I have not yet benchmarked ecosystem crates without box noalias and don&rsquo;t have the capacity to do so right now, so I would be very
|
<p>I have also benchmarked a few crates from the ecosystem with and without noalias on box, and the <a href="https://gist.github.com/Nilstrieb/9a0751fb9fd1044a30ab55cef9a7d335">results</a>
|
||||||
grateful if anyone wanted to pick that up and report the results.</p>
|
were inconclusive. (At the time of writing, only regex-syntax, tokio, and syn have been benchmarked.) regex-syntax showed no changes. Tokio showed a few improvements without noalias
|
||||||
<p>There are also crates on <a href="https://crates.io/">crates.io</a> like <a href="https://crates.io/crates/aliasable">aliasable</a> that already
|
which is very weird, so maybe the benchmarks aren&rsquo;t really good or something else was going on. And syn tended towards minor regressions without noalias, but the benchmarks had high
|
||||||
provide an aliasable version of <code>Box&lt;T&gt;</code>, which is used by the self-referential type helper crate <a href="https://crates.io/crates/ouroboros">ouroboros</a>.</p>
|
jitter so no real conclusion can be reached from this either, at least in my eyes, but I don&rsquo;t have a lot of experience with benchmarks. Therefore, I would love for more people
|
||||||
|
to benchmark more crates, especially if you have more experience with benchmarks.</p>
|
||||||
<h1 id="a-way-forward">a way forward</h1>
|
<h1 id="a-way-forward">a way forward</h1>
|
||||||
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions in ecosystem crates,
|
<p>Based on all of this, I do have a few solutions. First of all, I think that even if there might be some small performance regressions, they are not significant enough
|
||||||
the overall tradeoff goes against the current box behaviour. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely
|
to justify boxes uniqueness. Unsafe code wants to use box, and it is reasonable to do so. Therefore I propose to completely remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it
|
||||||
remove all uniqueness from <code>Box&lt;T&gt;</code>, and treat it just like a <code>*const T</code> for the purposes of aliasing. This will make it more
|
just like a <code>*const T</code> for the purposes of aliasing. This will make it more predictable for unsafe code, and is a step forward towards less magic from <code>Box&lt;T&gt;</code>.</p>
|
||||||
predictable for unsafe code, and comes at none or only a minor performance cost.</p>
|
<p>But the performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
||||||
<p>But this performance cost may be real, and especially the future optimization value can&rsquo;t be certain. The current uniqueness guarantees of box
|
|
||||||
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
are very strong, and still giving code an option to obtain these seems useful. One possibility would be for code to use a
|
||||||
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
<code>&amp;'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/316">unclear</a>.
|
||||||
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
|
||||||
inside the standard library would have to be removed.</p>
|
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
|
||||||
|
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p>
|
||||||
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
<p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&hellip;</p>
|
||||||
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
<p>For more information about this topic, see <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/326">https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p></content></item></channel></rss>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue