Hello!
I’d like too know what are the exact differences between *const T and *mut T types, what guarantees they provide and what invariants the programmer must maintain. i find documentation on the topic a bit thin:
- Non-exhaustive list of “properties to remember” in Rust book: https://doc.rust-lang.org/book/first-edition/raw-pointers.html
- A similar list in the second edition https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html
- A bit of important info about variance in nomicon: https://doc.rust-lang.org/nomicon/subtyping.html
- Nothing in the reference
Here is what I think is true about *const T and *mut T. Please correct me if I am wrong and confirm, if I am right.
- It’s not UB to cast between
*const T and *mut T.
-
*const T is variant and *mut T is invariant over T.
- 1) implies that 2) is the single real difference between them.
So if you are using raw pointers to implement a data structure (that is, not for FFI), you can pretty much use any of *const or *mut, provided that variance is correct. You may even have to use *const for “mutable” data if you need variance. The prime example of this is a Unique<T> type, which is logically an owning-raw pointer. It stores *const T to be variant over T, but give access to T via *mut.
If you are using raw pointers for FFI (as parameter and return types of extern “C” functions), then *const vs *mut is purely a question of documenting intent, and does not affect the generated code at all. However, documenting intent is important, because C and C++ have a rule that you can’t mutate a constant object.