
Stacked Borrows: an aliasing model for Rust - fanf2
https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html
======
steveklabnik
For some context, Ralf is one of the people who's been working on proving Rust
code, and specifically unsafe Rust code. He's already had some really
impressive results.

One of the weakest areas of Rust (in some sense) is unsafe; we don't have a
proper understanding of what exactly is acceptable with unsafe code. Projects
like these are working on proposing a model for what those rules should be.

So, if you're most Rust programmers, this doesn't affect you, really, other
than making code you depend on a bit higher quality :). If you're an author of
unsafe Rust code, this would tell you what you can and can't do, and if you
work on a compiler, these rules would tell you what you can and can't
optimize.

Additionally, this is pretty neat:

> I hope to explore this question further in the following weeks by
> implementing a dynamic checker to test the model on real code.

If we accepted this model (which is, of course, a big if; it was just
proposed!), then we could take this tool and instrument your unsafe, an
"unsafegrind", if you will, that could tell you at runtime if your code trips
UB.

This tooling is enabled by MIRI, which is also amazing, but I've gone on too
long already. TL;DR: it's sort of a "rust interpreter" that we've invested in
for compile-time function evaluation, but also pays off with things like this.

~~~
ibdknox
Huh, does MIRI mean that rust is actually doing some form of partial
evaluation during compilation? What's the best way to learn more about that?

~~~
steveklabnik
MIRI is short for "MIR Interpreter"; it can run basically any Rust code. But,
in the compiler itself, its interface is restricted a bit; we haven't fully
defined what "const fn" will be.

[https://github.com/solson/miri](https://github.com/solson/miri) is probably
the best place to start poking around :)

------
obl
Beyond the technical aspect, the pedagogical side of this is huge.

An argument often made in favor of Rust's static analysis restrictions is that
"worst case scenario, you just drop down to unsafe and you're back to C
semantics".

However, this only holds true as long as the rules to uphold in unsafe code
are easy to explain. Strict type aliasing in C is already considered as
somewhat of a disaster by many, and is way simpler.

I hope they get this right.

------
Animats
It's fascinating to see the problem being addressed. But it all seems to be
about "raw pointers", which are mostly for talking to non-Rust code and
probably ought to be on the way out as more low-level libraries are
implemented in Rust.

The expressive problems with the ownership model mostly involve backpointers.
It's hard to create doubly-linked lists or trees with backpointers in safe
Rust, short of going to reference counts and weak pointers. This proposal
doesn't seem to address that. Backlinks imply a consistency constraint between
forward and back pointers, and Rust lacks the expressive power to talk about
that.

The other big expressive issue involves partially initialized arrays. The
underlying machinery for a vector involves getting uninitialized memory and
initializing it one entry at a time as more of the vector's space is used. You
can't talk about that within Rust. It's the sort of thing for which a simple
inductive proof is needed, once you're able to say things like "Only elements
0..N of this array are valid".

These are places where you need unsafe Rust because you can't say what you
mean in safe Rust. That's the first problem, insufficient expressive power.
The second problem is proving that what you said is correct. That's a
technical compiler/verifier issue.

~~~
anderskaseorg
After we have a formal understanding of exactly which invariants unsafe Rust
code may rely on and must preserve, we may be able to integrate a proof
assistant into Rust to allow all that functionality and more to be exposed
safely—we could replace unsafe {} blocks with automatically checked proof
annotations! That’s a dream for the far future, but Ralf’s work is an
important step toward making that possible.

~~~
Animats
_That’s a dream for the far future._

Which it has been for too long. I was doing automated program proving on basic
validity stuff like this over 30 years ago.

In order to prove something, you first need a notation for talking about it.
Few languages let you talk about uninitialized memory space properly.
Constructors are too magic.

Un-initialized memory can be viewed as write-only. You want to show that no
un-initialized byte is ever read. Memory comes from the allocator in blocks of
un-initialized bytes.

A constructor is simply a function that takes a block of un-initialized memory
and assigns every byte to something meaningful for that type. At the end of
construction, the memory block becomes a valid instance of that type.

Once you can talk about construction as a non-magic operation, you can talk
about partial construction of an array. Until you can talk about it, you can't
prove anything about it.

Some types, such as "byte", are fully mapped - any bit pattern is valid. So
they can be initialized by anything that fills them. That's how input buffers
can be expressed.

~~~
renox
> A constructor is simply a function that takes a block of un-initialized
> memory and assigns every byte

In C++, the constructor doesn't initialise _every_ bytes (padding for
example)..

~~~
Animats
Then you need to show that any un-initialized byte can either never be read or
is of a fully mapped type where it doesn't matter.

~~~
renox
I'm not sure what you mean by 'a fully mapped type' but uninitialised padding
bytes are read without problem in C++ when you do a memcpy of a structure..

------
foota
It's linked (with a broken link if the author's reading this) to in the
article, but I would highly recommend reading
[https://www.ralfj.de/blog/2018/08/07/2018-07-24/pointers-
and...](https://www.ralfj.de/blog/2018/08/07/2018-07-24/pointers-and-bytes).

It was a really amazing read.

~~~
faitswulff
Link seems to be live here now:
[https://www.ralfj.de/blog/2018/07/24/pointers-and-
bytes.html](https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html)

