-
Notifications
You must be signed in to change notification settings - Fork 61
Closed
Labels
A-validityTopic: Related to validity invariantsTopic: Related to validity invariants
Description
Discussing the validity invariant of raw pointers.
For pointers to sized types, this should probably be the same as the invariant for usize
-- see the integer topic for discussing whether uninitialized bits are allowed or not.
For pointers to unsized types, there is an additional question: to what extent does the metadata have to be initialized/valid? Do we require it to be "valid" enough to determine size and alignment, e.g. do we require that the vtable pointer actually point to allocated memory?
Metadata
Metadata
Assignees
Labels
A-validityTopic: Related to validity invariantsTopic: Related to validity invariants
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
nikomatsakis commentedon Jan 31, 2019
Agreed, I think a cast from raw pointer to
usize
(and vice versa) should not be UB.This is worth drilling a bit more into. I know I've had conversations with @eddyb, @Manishearth, @withoutboats, and a few others about this, and I'd love to hear more from them.
I believe that @Manishearth's argument boiled down to "it's really useful to be able to create the equivalent of a NULL pointer: a kind of 'universally valid' value that you know will be overwritten before the reference is ultimately used". I find this a compelling argument: we should make sure we can support that. I suppose the answer is that you can use
MaybeUninit
, though that definitely comes at an ergonomic cost.I think it's certainly an option to say that the "metadata must always be valid". It'd be good to drill into the reasons we might want this to be true. Perhaps it's helpful to list out the times we need metadata to be valid?
Some examples I can think of:
fn foo(*mut self)
methods, which are presently blocked on resolving this discussion)Mostly these do seem to be tied to discrete actions in the code, though, and hence point to an invariant that could be enforced at the point of use.
Amanieu commentedon Jan 31, 2019
I would argue that since all of these examples require references, valid metadata should only be needed for references while raw pointers (as long as they are not dereferenced) would be allowed to have invalid/null metadata.
Are there any cases where we need to access the metadata of a raw pointer without first turning it into a reference?
SimonSapin commentedon Jan 31, 2019
I think @RalfJung mentioned before we could/should have variants of
mem::size_of_val
andmem::align_of_val
that take a raw pointer instead of a reference, for example for use inBox
’s destructor https://github.com/rust-lang/rust/blob/8a0e5faec7f62e3cfd88d6625ce213d93b061305/src/liballoc/alloc.rs#L195-L196gnzlbg commentedon Feb 4, 2019
If we accept uninitialized bits as being a valid representation for
usize
, I wonder how that would impact what valid means for thin raw pointers and raw pointers in general. It might be weird to say that*mut i32
can be uninitialized, but that*mut dyn Trait
cannot (or at least that some part of it cannot be, like e.g. the pointer to the vtable). We would be adding another rule that's not simple: instead of it being all raw pointers can / can't be uninitialized, we are adding a rule of the form: "some" raw pointers can be uninitialized.Amanieu commentedon Feb 4, 2019
It makes sense if you consider that we are only keeping
mem::uninitialized
valid for a limited set of types to maintain backwards compatibility with existing code. The majority of uses ofmem::uninitialized
are used with C structs which are then initialized through an FFI call, where fat pointers will not be used.RalfJung commentedon Feb 5, 2019
I assume if we allow uninitialized integers, we will also allow uninitialized data in the metadata of a raw pointer. I see no harm in that.
JakobDegen commentedon Jun 6, 2023
Closing, partially answered partially in favor of #166