Why would people even code in C anymore? Rust is the way, truth, and light brotha!!
I've always enjoyed occultism anyways... there's indeed some crazy things in this universe. Oh, and on the side if you're curious, check out this book I wrote. https://thomaspbraun.com/TheBridge.pdf
It actually got academic recognition this past April, despite it being quite... well, you'll see
Note that while you can get &mut T
from &UnsafeCell<T>
, converting &UnsafeCell<T>
into &mut UnsafeCell<T>
still is UB.
This comment made me feel unsafe...
Not... that you could do very much with a &mut UnsafeCell<T>
that you couldn't do with a &UnsafeCell<T>
, other than the following:
let x: &UnsafeCell<T> = /**/;
*x = UnsafeCell::new(/**/);
But there would be no point to that because then you'd just
*x.get() = /**/;
True, but I think he was pointing it out to just get the idea across of the meta-ness of how the compiler may work
Right I understand.
But in addressing dynamics you wouldn't want to skip the additional checks?
Hence it's notorious overhead?
Have you heard the infinitely dense space theory in physics?
I 100% believe the guy. Brilliant! A genius.
"This comment made me feel unsafe..."
I am supposed to feel unsafe rather than be unsafe? I thought I was supposed to feel transient anxiety.
Oh no, you are thinking about this wrong, without UnsafeCell
the compiler will assume that writing to something that is transitively behing a shared reference is impossible, and will optimize based on that assumption. If you do write to something behind an shared reference, unless it is wrapped in a UnsafeCell
, the compiler is free to throw out that write completely. This is not what you wanted, so to remove these optimizations, you must use UnsafeCell
.
That sounds awesome. Can you send me a link? I'm getting, as expected, lots of results for theories regarding black holes via Google
In release mode, or debug? In debug, I am able to write via a shared ref no problem.
In both modes. That it works is a coincidence, and the same code may suddenly start failing in the future if some optimization is added to llvm or rust.
Uhhhhh, guys?
You don't need an UnsafeCell if you have a *const T
or *mut T
.
- If you did, then it would be difficult to use
UnsafeCell::get
safely, as you would have to be paranoid about the possible accidental construction of a&*mut T
(e.g. when you Clone a pointer). If you're still not convinced, here's proof that they disable all of the same optimizations.
Wait a second, I misread the code I linked. What the heck!?!?!
unsafe impl<T: ?Sized> Freeze for *const T {}
unsafe impl<T: ?Sized> Freeze for *mut T {}
That... that can't be right!
@cuviper how did you construct those playground tests before? I'm having a difficult time getting the functions to not be eliminated as dead code. (I wish the playground had a --lib
mode...).
(edit: never mind, I finally spotted the playground link in your post)
I may need to read up on LLVM's noalias. Perhaps it only extends to data accessed through an offset of the pointer itself, and not to data accessed through another layer of indirection.
UnsafeCell
does not have this function
I meant UnsafeCell::get
.
Okay, here's what happens when UnsafeCell appears behind multiple layers of indirection:
pub fn f(_: &&Cell<i32>) {} // i32** noalias readonly align 8 dereferenceable(8)
pub fn f(_: &*mut i32) {} // i32** noalias readonly align 8 dereferenceable(8)
pub fn f(_: &i32) {} // i32* noalias readonly align 4 dereferenceable(4)
pub fn f(_: &Cell<i32>) {} // i32* align 4 dereferenceable(4)
pub fn f(_: *mut i32) {} // i32*
pub fn f(_: *const i32) {} // i32*
Notice how &&Cell
has noalias readonly
, just like &*mut i32
. Hence I stand by what I said: You only need UnsafeCell<T>
if you have a T
stored by value in rust code. You do not need it if all you have is a raw pointer to a T
.
Yeah, that's what I thought. I didn't know what was happening through the lens of LLVM though. In this struct's case, there is no need for T except when the user casts to it
The pointer itself implements Freeze
, but this says nothing about T
.
/// Compiler-internal trait used to determine whether a type contains
/// any `UnsafeCell` internally, but not through an indirection.
Yes, that's how I understand it.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.