Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique references to temporary empty arrays are not actually unique #74154

Open
mcy opened this issue Jul 8, 2020 · 3 comments
Open

Unique references to temporary empty arrays are not actually unique #74154

mcy opened this issue Jul 8, 2020 · 3 comments
Labels
A-array Area: [T; N] C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@mcy
Copy link
Contributor

mcy commented Jul 8, 2020

fn two_muts<T>(a: &mut [T], b: &mut [T]) {
    assert_ne!(a.as_ptr(), b.as_ptr());
}

fn main() {
    two_muts::<u8>(&mut [], &mut []);
}

I expected this code to compile and exit without effect; instead, I get an assertion error. It seems that, when passing in unique references to temporary empty slices, the underlying pointers nonetheless alias.

I expected all such pointers to never alias; this even holds when replacing [T] above with the ZST [T; 0], which makes it significantly more worrying, since it does not hold for the same code using ().

I don't know if this behavior is actually specified, but I'd like an answer to whether this is a miscompilation or (un)documented implementation-defined behavior. At any rate, I wonder if it would be a good idea to make this behavior consistent for all ZST temporaries...

Also, I aught to mention that this is about ZSTs lying in distinct allocations. For a type such as ((), ()), we expect the two unit values to have the same addresses. The closest mention of this I could find in the nomicon to this was the implementation of Vec<()>, but that's still regarding same-allocation references, so that didn't give me a particularly satisfying answer.

Meta

This issue is reproducible on latest beta and nightly.

I could not find an issue corresponding to this bug; feel free to close as duplicate.

@mcy mcy added the C-bug Category: This is a bug. label Jul 8, 2020
@the8472
Copy link
Member

the8472 commented Jul 8, 2020

That isn't specific to temporaries. Mutable references to ZSTs in what normally are heap-allocated containers can also have identical values. References to ZSTs are basically pulled out of thin air and valid as long as they're non-null.

fn main() {
    let mut v1 = vec![(); 1];
    let mut v2 = vec![(); 1];
    assert_ne!(v1.as_mut_ptr(), v2.as_mut_ptr());
}
thread 'main' panicked at 'assertion failed: `(left != right)`
  left: `0x1`,
 right: `0x1`', src/main.rs:4:5

@gendx
Copy link

gendx commented Jul 9, 2020

Also, I aught to mention that this is about ZSTs lying in distinct allocations.

Correct me if I'm wrong, but in the original example I don't see any allocation. Aren't the empty arrays supposed to be on the stack (at least before any compiler optimization kicks in)?

two_muts::<u8>(&mut [], &mut []);

Isn't the following memory model a reasonable possible representation?

  • The first array [] at stack_start + 0
  • The second array [] at stack_start + 0
  • The first slice &mut [] at stack_start + 0
  • The second slice &mut [] at stack_start + 2 * pointer_size

In that case, both arrays - and even one of the slices - start at the same memory address. However, they don't overlap but simply "touch" each other.

In that sense, even though the underlying pointers point to the same address, the pointed-to objects don't actually alias, right? Or to put it differently, pointers to ZST can never alias, because the underlying zero-sized objects can never overlap each other (at worst they "touch", which isn't aliasing).

@sfackler
Copy link
Member

sfackler commented Jul 9, 2020

Also, I aught to mention that this is about ZSTs lying in distinct allocations.

Zero bytes of the allocations of those values overlap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-array Area: [T; N] C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants