What's the definition of mutable aliasing for ZSTs?
See original GitHub issueFor sizeof(T)>0
, I understand the rules: no two &mut
s can reference overlapping memory.
What exactly are the rules for ZSTs, though?
For x: ((),())
to be a ZST (which we want), &mut x.0
and &mut x.1
are allowed, but are NOP transformations of &mut x
, with the same value. But with unsafe code, I can take &mut x as *mut _
, perform two NOP transformations to it, cast it as *mut ()
, and dereference it, and I don’t know how to determine whether I’m reading the “first” or “second” fields, and thus whether I’m violating aliasing. Similar arguments apply to things like split_at_mut
on a &mut [()]
, which is also creating multiple pointers of the same value.
But if all ZST reads are legal, that means all ZSTs are effectively Copy
, which means a private-constructor ZST cannot safely be used as an access token, as it can be copied by ptr::read’ing it twice (legal because all ZST reads are legal, by premise).
Issue Analytics
- State:
- Created 6 years ago
- Comments:14 (12 by maintainers)
I agree with @nagisa. Moreover, this has no bearing on whether a private-constructor ZST can be used as an access token: If unsafe code forges such a private-constructor ZST, while no immediate UB is raised, that’s still clearly misbehaving unsafe code. Compare this to a
repr(C)
struct with two private fields that has an invariant: While it is no immediate UB to use unsafe code to modify the fields of this struct, that’s still misbehaving unsafe code and safe code may rely on unsafe code not doing this.“What code is UB” and “What safe code can rely on unsafe code to (not) do” don’t always have the same answer, though of course safe code can at least rely on unsafe code not triggering UB.
@scottmcm
Notice that this would be the case even without considering ZSTs. For example, there may never be two
&mut MutexGuard
for the same mutex, even if the guards themselves are disjoint in terms of the memory they occupy.