How much more tricky is `unsafe` code than C code? (Aliases and `const_cast`)


Thinking about implications of strong aliasing rules and move semantics in Rust in context of unsafe code let me wondering how much more tricky it is to write unsafe code compared to C.

Rust does not allow value to be aliased by multiple pointers and programmer has to account for this manually in unsafe code. In contract C/C++ compilers use defensive alias analysis which leads to lower performance when the writing to memory through references or pointers because of excessive loads and stores but code aliasing single memory location by multiple pointers runs correctly. Also C compilers treat function calls as load/store barriers because they must expect that any memory can be accessed or changed inside the called function.

Rust could get rid of the alias analysis and excessive stores and loads. I do not know if it already does. However in that case it is not possible to modify any memory location that is referenced by immutable reference or raw pointer. The C/C++ has mutable keyword to allow modifications to data even through const references and comes handy for lazy initializations and similar situations. Because of its aliasing rules it is not problem. In Rust that is big problem because caller may not see changes.

Is it allowed to modify data behind immutable references in unsafe code? If yes, does it mean that these load/store optimizations will never happen? If no, what is a solution to situation where mutable is used in C++?


In no case are you allowed to modify &-borrowed data, or to modify actively-&mut-borrowed data except via the borrowing pointer, that isn’t behind an UnsafeCell.

If you want to play with mutability, you should use raw pointers (*mut and *const have identical aliasing semantics), and if you want to put something inside a regular object, put it behind an UnsafeCell – then you’ll have the safety of C++.


Thank you for pointing me to UnsafeCell.

You mean identical semantics to C/C++, right?

Does rustc currently use the semantics to optimize code or is it still future work?


*mut T and *const T have the same aliasing semantics as C-s T* (no cross-type aliasing i.e. TBAA and no data races). I’m not sure we use TBAA everywhere, but I think we do it sometimes, and may use it more often.


So it is possible that some unsafe code that is not valid today but works will stop working in the future?