Re: C aggregate passing (Rust kernel policy)

Gary Guo
2025-02-26T11:57:50Z

On Tue, 25 Feb 2025 18:34:42 -0500
Kent Overstreet <kent.overstreet@linux.dev> wrote:

> On Tue, Feb 25, 2025 at 01:24:42PM -0800, Linus Torvalds wrote:
> > On Tue, 25 Feb 2025 at 12:55, Kent Overstreet <kent.overstreet@linux.dev> wrote:
> > >
> > > The problem isn't that "pointer aliasing is fundamentally unsafe and
> > > dangerous and therefore the compiler just has to stay away from it
> > > completely" - the problem has just been the lack of a workable model.
> >
> > It's not entirely clear that a workable aliasing model exists outside
> > of "don't assume lack of aliasing".
> >
> > Because THAT is the only truly workable model I know of. It's the one
> > we use in the kernel, and it works just fine.
> >
> > For anything else, we only have clear indications that _unworkable_
> > models exist.
> >
> > We know type aliasing is garbage.
>
> The C people thinking casting to a union was a workable escape hatch was
> hilarious, heh. But now we've got mem::transmute(), i.e. that can (and
> must be) annotated to the compiler.

Well, you can still use unions to transmute different types in Rust,
and in addition to that, transmuting through pointers is also
perfecting valid. These don't need special annotations.

There's simply no type aliasing in Rust. In fact, there's a whole
library called zerocopy that exactly give you a way to transmute
between different types safely without copying!

I can completely concur that type aliasing is garbage and I'm glad that
it doesn't exist in Rust.

> > We know "restrict" doesn't work very well: part of that is that it's
> > fairly cumbersome to use, but a large part of that is that a pointer
> > will be restricted in one context and not another, and it's just
> > confusing and hard to get right.
>
> And it only works at all in the simplest of contexts...
>
> > What we do know works is hard rules based on provenance. All compilers
> > will happily do sane alias analysis based on "this is a variable that
> > I created, I know it cannot alias with anything else, because I didn't
> > expose the address to anything else".
>
> Yep. That's what all this is based on.

Correct. In fact, Rust has already stabilized the strict provenance
APIs so that developers can more easily express there intention on how
their operations on pointers should affect provenance. I'd say this is
a big step forward compared to C.

>
> > So *provenance*-based aliasing works, but it only works in contexts
> > where you can see the provenance. Having some way to express
> > provenance across functions (and not *just* at allocation time) might
> > be a good model.
>
> We have that! That's exactly what lifetime annotations are.
>
> We don't have that for raw pointers, but I'm not sure that would ever be
> needed since you use raw pointers in small and localized places, and a
> lot of the places where aliasing comes up in C (e.g. memmove()) you
> express differently in Rust, with slices and indices.

On thing to note is that Rust aliasing rules are not tied to lifetime
annotations. The rule applies equally to safe and unsafe Rust code.
It's just that with lifetime annotations, it *prevents* you from
writing code that does not conform to the aliasing rules.

Raw pointers stil have provenances, and misusing them can cause you
trouble -- although a lot of "pitfalls" in C does not exist, e.g.
comparing two pointers are properly defined as
comparision-without-provenance in Rust.

>
> (You want to drop from references to raw pointers at the last possible
> moment).
>
> And besides, a lot of the places where aliasing comes up in C are
> already gone in Rust, there's a lot of little things that help.
> Algebraic data types are a big one, since a lot of the sketchy hackery
> that goes on in C where aliasing is problematic is just working around
> the lack of ADTs.
>
> > But in the absence of knowledge, and in the absence of
> > compiler-imposed rules (and "unsafe" is by *definition* that absence),
> > I think the only rule that works is "don't assume they don't alias".
>
> Well, for the vast body of Rust code that's been written that just
> doesn't seem to be the case, and I think it's been pretty well
> demonstrated that anything we can do in C, we can also do just as
> effectively in Rust.
>
> treeborrow is already merged into Miri - this stuff is pretty far along.
>
> Now if you're imagining directly translating all the old grotty C code I
> know you have in your head - yeah, that won't work. But we already knew
> that.

If you translate some random C code to all-unsafe Rust I think there's
a good chance that it's (pedantically) undefined C code but well
defined Rust code!