3 ms·
There's a bit of a sentiment that the `*mut T`/`*const T` distinction is more unhelpful noise than an actually useful feature. They can be freely cast between e
by Rusky 4y ago
There's a bit of a sentiment that the `*mut T`/`*const T` distinction is more unhelpful noise than an actually useful feature. They can be freely cast between each other - `*mut T` to an immutable object is totally legal - and thus (much like C and C++'s const) don't really mean anything about the thing they point to. Further, writing through one or converting back to a reference is already `unsafe`, so even using them as a lint doesn't add much.
AIUI that is why NonNull only has one variant- it's just easier to have one kind of pointer. But interestingly, even though `NonNull`'s API is written in terms of `*mut T`, it is implemented in terms of `*const T`: https://github.com/rust-lang/rust/blob/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/core/src/ptr/non_null.rs#L52 https://github.com/rust-lang/rust/blob/4ca19e09d302a4cbde14f.... This makes it covariant (`NonNull<T>` for `T: 'long` is a subtype of `NonNull<T>` for `T: 'short`), while `*mut T` is invariant, since this is the more common mode, and also the more flexible option that can be restricted back down to invariance when necessary.
So NonNull is sort of a re-setting of the defaults: the unsafe mutability of `*mut T` (since people wind up needing to cast covariant `*const T`s to `*mut T` to write through them a lot anyway), with the covariance of `*const T`.