Rust &f32 vs C &const float

#1

This is related to Is there a way to implement Index/IndexMut on a Vec<Cell<f32>>

Is the following correct: Rust’s &f32 offers far far greater guarantees than C’s &const float.

  1. A &const float in C/C++ says: I can not change this variable via this ref, however some other piece of code can change it at will.

  2. A rust &f32, due to borrow rules, says: during the lifetime which I hold this ref, NO ONE (outside of unsafe) is allowed to modify the underlying f32.

Is this correct?

0 Likes

#2

C doesn’t have references, only C++, but I suspect the answer will be similar to const* anyway. I don’t recall whether writes are allowed from elsewhere though.

If unsafe code forces a write, this is UB, which you might as well call “not allowed” too. Most likely this just means that the readers might not see that update, but all bets are off.

2 Likes

#3

This is correct. Rust’s shared references have a strong guarantee that the data is immutable (and exclusive references that the data is not seen by anyone else at the same time)

1 Like

#4

Oh, I should add that the immutability is logical, not physical in memory. Cell, RefCell, Mutex, etc. can mutate data behind a shared reference, but they force the code to do it with synchronization or atomic access.

0 Likes

#5

And those all mutate through UnsafeCell, which is a lang item getting special treatment in the compiler.

2 Likes

#6

For even more clarification: that only applies to references to types that actually contain UnsafeCell, such as &Cell<f32>. &f32 itself is truly immutable as long as it exists; there is no (legal) way to somehow use UnsafeCell to mutate it.

1 Like

#7

Could you please clarify this a bit? Of course, I didn’t dive deep into the code, but AFAIK, the definition of UnsafeCell is simply “hold the value, give the * mut to it on demand” (and other Cell types are safe wrappers around this pointer). Is there anything else underneath?

0 Likes

#8

UnsafeCell gets special treatment by the compiler in being allowed to mutate its internals via a shared reference. Values that don’t involve an UnsafeCell can be assumed to never change through a shared reference under any circumstances.

1 Like

#9

Its #[lang = "unsafe_cell"] attribute is what indicates special treatment. You can search for that in the compiler sources to track down its effect in more detail. This blog post also offered a good overview of lang items:

2 Likes