Re: C aggregate passing (Rust kernel policy)

Ventura Jack
2025-02-24T09:57:48Z

On Sun, Feb 23, 2025 at 5:27 PM Gary Guo <gary@garyguo.net> wrote:
>
> On Sun, 23 Feb 2025 08:30:06 -0700
> Ventura Jack <venturajack85@gmail.com> wrote:
>
> > - In unsafe Rust, it is the programmer's responsibility
> > to obey the aliasing rules, though the type system
> > can offer limited help.
> > - The aliasing rules in Rust are possibly as hard or
> > harder than for C "restrict", and it is not possible to
> > opt out of aliasing in Rust, which is cited by some
> > as one of the reasons for unsafe Rust being
> > harder than C.
>
> The analogy is correct, you can more or less treat all Rust references
> a `restrict` pointers. However it is possible to opt out, and it is
> done at a per-type basis.
>
> Rust provides `UnsafeCell` to make a immutable reference mutable (i.e.
> "interior mutability"), and this makes `&UnsafeCell<T>` behaves like
> `T*` in C.
>
> There's another mechanism (currently under rework, though) that makes a
> mutable reference behave like `T*` in C.
>
> RfL provides a `Opaque` type that wraps these mechanisms so it
> absolutely cancel out any assumptions that the compiler can make about
> a pointer whatsoever. For extra peace of mind, this is used for all
> data structure that we share with C.
>
> This type granularity is very useful. It allows selective opt-out for
> harder to reason stuff, while it allows the compiler (and programmers!)
> to assume that, say, if you're dealing with an immutable sequence of
> bytes, then calling an arbitrary function will not magically change
> contents of it.
>
> Best,
> Gary

In regards to `UnsafeCell`, I believe that you are correct in regards
to mutability. However, if I understand you correctly, and if I
am not mistaken, I believe that you are wrong about `UnsafeCell`
making it possible to opt-out of the aliasing rules. And thus that
`UnsafeCell` does not behave like `T*` in C.

Documentation for `UnsafeCell`:
https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html

"Note that only the immutability guarantee for shared
references is affected by `UnsafeCell`. The uniqueness
guarantee for mutable references is unaffected. There is no
legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`."

"Note that whilst mutating the contents of an `&UnsafeCell<T>`
(even while other `&UnsafeCell<T>` references alias the cell) is
ok (provided you enforce the above invariants some other way),
it is still undefined behavior to have multiple
`&mut UnsafeCell<T>` aliases."

The documentation for `UnsafeCell` is long, and also mentions
that the precise aliasing rules for Rust are somewhat in flux.

"The precise Rust aliasing rules are somewhat in flux, but the
main points are not contentious:"

In regards to the `Opaque` type, it looks a bit like a C++
"smart pointer" or wrapper type, if I am not mistaken.

Documentation and related links for `Opaque`:
https://rust.docs.kernel.org/kernel/types/struct.Opaque.html
https://rust.docs.kernel.org/src/kernel/types.rs.html#307-310
https://github.com/Rust-for-Linux/pinned-init

It uses `UnsafeCell`, Rust "pinning", and the Rust for Linux library
"pinned-init". "pinned-init" uses a number of experimental,
unstable and nightly features of Rust. Working with the library
implementation requires having a good understanding of unsafe
Rust and many advanced features of Rust.

`Opaque` looks interesting. Do you know if it will become a more
widely used abstraction outside the Linux kernel?

Best, VJ.