Description
This was previously raised in #103763 (comment). Currently, comparing a pair of *const dyn Trait
raw pointers for equality will check that both the address and vtable are equal.
This is problematic because the vtable of a type is not guaranteed to be unique for each type: different types can share the same vtable and the same type can have its vtable instantiated multiple times.
To illustrate this issue, consider the following program which prints true
in release mode and false
in debug mode because LLVM is merging the two identical vtables (playground).
struct A;
struct B;
trait T {}
impl T for A {}
impl T for B {}
fn main() {
let ab = (A, B);
let a = &ab.0 as *const dyn T;
let b = &ab.1 as *const dyn T;
println!("{}", a == b);
println!("{}", a as *const u8 == b as *const u8);
}
It is also possible to achieve the reverse effect where two dyn Trait
pointers to the same value (with the same base type) compare unequal because a separate vtable was instantiated with each pointer (e.g. due to codegen units or separate crates).
In conclusion, vtables are completely useless as a source of truth for pointer equality, so we should only consider the pointer address when comparing dyn Trait
raw pointers. We currently document this as a footgun (#103567), but it would be better to eliminate this footgun entirely from the language.