Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upWhat's the definition of mutable aliasing for ZSTs? #44
Comments
This comment has been minimized.
This comment has been minimized.
nagisa
commented
Jan 3, 2018
•
|
This is pretty easy to answer. Aliasing only occurs when memory regions, within which the objects are stored, overlap. Since the memory regions occupied by ZSTs are, obviously, zero-sized, there can never be any overlap, even for pointers with the same address. |
This comment has been minimized.
This comment has been minimized.
|
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 "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. |
This comment has been minimized.
This comment has been minimized.
ExpHP
commented
Jan 3, 2018
•
|
In response specifically to the conclusion that all ZSTs can be safely copied; if this were true, it would spell very bad news for all existing Drop impls for ZSTs. |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Jan 4, 2018
•
|
@ExpHP I'm not convinced a ZST can have a sensible Drop impl (Just to be clear: I'm very much on the side that we can't copy things that are not Copy, that breaks type safety.. and we use type safety to have memory safety). |
This comment has been minimized.
This comment has been minimized.
Amanieu
commented
Jan 4, 2018
|
@bluss A ZST can be used as a proxy for global state. For example, a |
This comment has been minimized.
This comment has been minimized.
I am not sure where you are getting this conclusion from. It is not correct. I specifically argue above that ZSTs may not be copied by unsafe Code! Copying them does not raise immediate UB, but that doesn't make it okay. Or are you just confirming that it should not be okay? In that case I agree :D |
This comment has been minimized.
This comment has been minimized.
ExpHP
commented
Jan 4, 2018
Yes. |
This comment has been minimized.
This comment has been minimized.
Does that mean, then, that the following function is well-defined? fn zst_index2<T>(x: &mut Vec<T>, (i, j): (usize, usize)) -> (&mut T, &mut T) {
assert_eq!(std::mem::size_of::<T>(), 0);
let ps = (
&mut x[i] as *mut _,
&mut x[j] as *mut _,
);
unsafe {
(
&mut* ps.0,
&mut* ps.1,
)
}
}
#[derive(Debug)]
struct MyZst;
fn main() {
let mut v = vec![MyZst];
let p = zst_index2(&mut v, (0, 0));
println!("{:?}", p);
}https://play.rust-lang.org/?gist=0ef8d9bbbbc8fd477f2e2fc1be0ccb1d&version=stable (Apologies for the distraction about cloning; I'll move that discussion elsewhere.) |
This comment has been minimized.
This comment has been minimized.
Amanieu
commented
Jan 7, 2018
|
Yes it is well defined. If it helps your mental model, think of it like this: each memory address contains an infinite number of distinct ZSTs. Every time you dereference a ZST pointer, you are accessing a new, separate instance of a ZST. Therefore it is impossible to have aliasing with ZSTs: all ZST pointers point to a different ZST instance, even if they have the same address. |
This comment has been minimized.
This comment has been minimized.
Amanieu
commented
Jan 7, 2018
Actually, let me clarify that. The code that you have given will not trigger any UB due to aliasing violations. However it may violate the semantics of the |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Jan 7, 2018
|
@scottmcm I agree with @Amanieu that your function does not preserve the ownership semantics of the |
rkruppe
referenced this issue
Jan 7, 2018
Closed
What rule prevents me from Copying arbitrary ZSTs? #47255
This comment has been minimized.
This comment has been minimized.
|
Ok, so checking for aliasing is not enough to know that two |
scottmcm
closed this
Jan 7, 2018
This comment has been minimized.
This comment has been minimized.
|
I agree with @Amanieu and @bluss. And, in fact, I think my formal model in RustBelt also agrees: Owning an For private types or types with private fields, libraries get to pick what "owning |
This comment has been minimized.
This comment has been minimized.
Notice that this would be the case even without considering ZSTs. For example, there may never be two |
scottmcm commentedJan 3, 2018
•
edited
For
sizeof(T)>0, I understand the rules: no two&muts can reference overlapping memory.What exactly are the rules for ZSTs, though?
For
x: ((),())to be a ZST (which we want),&mut x.0and&mut x.1are 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 itas *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 likesplit_at_muton a&mut [()], which is also creating multiple pointers of the same value.But if all ZST reads are legal, that means all ZSTs are effectivelyCopy, 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).