Closed rom1v closed 4 years ago
We don't guarantee that vtables are unique. For example, a separate copy could be generated in multiple codegen units, or multiple crates.
OK.
In that case, shouldn't ptr::eq()
ignore the vtable part?
This also affects slices:
use std::ptr;
fn main() {
let array = [1, 2, 3, 4];
let slice1 = &array[0..1];
let slice2 = &array[0..3];
println!("{:p} == {:p} ? {}", slice1, slice2, ptr::eq(slice1, slice2));
}
0x7fff0a6595b8 == 0x7fff0a6595b8 ? false
Here is the smallest sample I managed to find to demonstrate this on my system using rustups's 1.27.0-nightly. It appears this is only reproducible with incremental builds, which is why it won't show up when trying it with Rust Playground.
use std::path::Path;
pub trait Block { }
struct Inner {
data: i32,
}
impl Block for Inner { }
impl Inner {
fn new_box(data: i32) -> Box<Inner> {
Box::new(Inner {
data: data,
})
}
}
pub struct Outer {
inner: Box<Inner>,
block: *mut Block,
}
impl Outer {
pub fn new_box<P: AsRef<Path>>() -> Box<Outer> {
let mut inner = Inner::new_box(123);
let block = &mut *inner as *mut _;
Box::new(Outer {
inner: inner,
block: block,
})
}
pub fn get_inner(&mut self) -> &mut Block {
&mut *self.inner
}
}
fn main() {
let mut outer = Outer::new_box::<&str>();
let b = outer.block;
let a = outer.get_inner() as *mut Block;
println!("{:p} == {:p}: {}", a, b, a == b);
}
Result:
$ rustc main.rs -C incremental=./inc
$ ./main
0x7f0672a23008 == 0x7f0672a23008: false
I'm being bit by this problem also. It's causing ptr::eq
to fail which is breaking my program. It seems as though you could compare the vtable itself byte-for-byte to fix the problem, as their contents are the same.
Closing as duplicate of https://github.com/rust-lang/rust/issues/46139.
I did not manage to reproduce in a minimal sample, but in my application, I ended up with:
printing:
After investigations (and discussion on freenode/##rust), it appeared that
x
andy
were fat pointers having the same data part (the 64 first bits), but a different vtable (the last 64 bits).I applied this patch to my application, which solves the reported issue: https://github.com/Genymobile/gnirehtet/commit/c36fa4d1a1086aa03e56aabae12669f8b1a1a1c4
But I can't understand how two fat pointers for the same objects may have different vtables. Is it expected?