As per the issue and it's dupes, you'll be in good company . Though with my suggestion, it just transforms it into the possibility of false positives in case of trait objects of both structs and their contents when they have the same size (which seems even more niche).
I've often wished for a NotDyn
bound. Sized
is a poor substitute. To base it off of DynMetadata
, you would need to be able to test for associated type non-equality, which isn't quite the same thing... though maybe implementing with associated type X
could be considered an opt-out for any other type Y
, and T: Trait<Assoc != Y>
could be sugar for T: Trait + !Trait<Assoc=Y>
or something.
I think that's a ways off though. Note that negative bounds are not implemented on unstable yet, even. (I think coherence is in the process of landing in nightly.) And disjoint associated type coherence is delayed until the broader issue of mutually exclusive traits is tackled.
Those the wrappers-around like str
that I mentioned. Their metadata is the same though, yep.
As for future possibilities, they'll have to work at least somewhat similarly due to the existence of methods like size_of_val
. Unless we get a new Sized
-like implicit-auto-trait.
Some comments implied that, but I don't actually know that the contents of the vtable are the same, so I can't answer this definitively. Another possibility is to unify the vtables when linking. There are trade-offs between compile time and run time cost.
That's a valid view, and one that motivated the acceptance of the RFC. And I'm not arguing against it, but there are other valid views.
Incidentally, you're throwing out behavior in the ZST case.
#[derive(Debug)] struct S;
#[derive(Debug)] struct T;
let (s, t) = (S, T);
// Maybe the same address
let v: Vec<&dyn Debug> = vec![&s, &t];
#[repr(transparent)] #[derive(Debug)] struct U(T);
// Definitely the same address
let u = U(T); // &u, &u.0
You may also have a bad time with "identity" due to optimization. Consider:
let const I: i32 = 0;
let i = 0;
let a: &dyn Debug = &i; // Base is i32 (stack address)
let b: &dyn Debug = &&i; // Base is &i32 (stack address)
let c: &dyn Debug = &a; // Base is &dyn Debug (stack address)
let e: &dyn Debug = &I; // Base is i32 (unstable address)
let d: &'static dyn Debug = &0; // Base is i32 (static address)
These all "behave the same" but compare differently. Is it okay if optimizations make some of them compare the same?
I'm not really making a point here, other that pointing out it's probably always going to be a "best effort" type of situation.
(Though if you want all things that "behave the same" to compare the same, you'll have a worse time due to the halting problem )