Closed
Description
Hi, we've been trying to understand what's the correct way to model ZST pointers. What is UB and what has well defined behavior.
- Does a ZST pointer have provenance?
- Does ZST pointer identity hold?
- If it point to a ZST field in a structure, will it always be inbounds?
- Will the address of a static ZST always fall in the memory section of statics? Will the address of a local ZST always point to a location in the stack frame?
- Should a ZST pointer comparison take provenance into account or just the address?
Thanks!
Activity
Lokathor commentedon Apr 9, 2024
a == a
will be true for a ZST pointer, if that's what you mean.Pointer comparison doesn't compare provenance, just the address (and possibly more with a DST, but we'll ignore that for now).EDIT: see What are the guarantees over ZST pointers #503 (comment)chorman0773 commentedon Apr 9, 2024
For almost all purposes related to provenance, a pointer to a ZST is not distinct from a pointer to another type.
There are additional guarantees in terms of what operations are valid, when that operation is done with zero size. For example, memory accesses of zero size are trivially valid when well-aligned.
celinval commentedon Apr 9, 2024
Sorry, my phone keeps auto correcting provenance for some reason. Or maybe it was my brain malfunction. 🤷🏻♀️
celinval commentedon Apr 9, 2024
I thought that was still up for debate from reading this issue: #239
RalfJung commentedon Apr 10, 2024
For further information on provenance, see the RFC. The pointee type and being a reference vs a raw pointer makes no difference for provenance.
Yes, we haven't made an official t-lang decision on this. But at this point it seems unlikely that provenance will affect pointer comparison. The main unknown here is how to resolve #328.
On today's Rust, provenance does not affect pointer comparison.
The Rust specification does not have a notion of memory sections for statics or stack frames. All allocated objects are placed at arbitrary locations in memory and there is no guarantee whatsoever that stack allocations are in "the stack" or
Box
allocations are on "the heap".I think this answers all questions, or would you like further clarification?
tautschnig commentedon Apr 10, 2024
https://doc.rust-lang.org/reference/variables.html says that "A local variable (or stack-local allocation) holds a value directly, allocated within the stack's memory." (And https://doc.rust-lang.org/reference/memory-allocation-and-lifetime.html says something about Box and heap, but indeed does not promise that all Box allocations would be on the heap.)
RalfJung commentedon Apr 10, 2024
That should be fixed then, these guarantees make no sense on the level of the Rust spec. Stack and heap as distinct parts of the address space are target-specific notions that do not exist in the Abstract Machine.
celinval commentedon Apr 17, 2024
I think that would be a simple way to go about it, since these are no-op, but if I understand it correctly, a zero-size access is invalid if the pointer points to a deallocated memory, correct? I'm assuming that's because of provenance.
I am curious if provenance is also taken into account if the pointer is out-of-bounds of the original object? Would a zero-size access be valid in out-of-bounds pointers?
RalfJung commentedon Apr 17, 2024
This used to be the case but we decided to change it and allow more code. See rust-lang/rust#117945. Once that is fully implemented, zero-sized accesses will ignore provenance.
Under the current rules as implemented by Miri today, that would be UB. But rust-lang/rust#117945 will make it allowed.
celinval commentedon Apr 17, 2024
I think this answers all my questions. Thank you!
RalfJung commentedon Apr 17, 2024
Sure, happy to help. :)