Foo<Cat> -> Foo<AnimalT>

I have the following

pub struct Foo<T: ?Sized> {
    ptr: *const T,
    weak: std::rc::Weak<T>,
}

Now, my question: Is there a way to write a function of type:

for any type X and trait T, where we have impl T for X, then this function
can do Foo<X> -> Foo<T> ?

You can’t write code that’s generic over multiple traits, but this should work for any particular trait:

use std::fmt::Debug;

fn f<'a, T:Debug+'a>(x:Foo<T>)->Foo<dyn Debug+'a> {
    Foo {
        ptr: x.ptr as *const dyn Debug,
        weak: x.weak as std::rc::Weak<dyn Debug>
    }
}

On nightly, you might be able to do something with CoerceUnsized, but there are enough caveats in the description that I don’t want to attempt an implementation.

1 Like

Careful with *const dyn Trait. Given your other post, you may end up comparing a fat pointer using crate-specific vtable-metadata: see this clippy lint.

That ptr ought to always be slim, imho:

struct Foo<T : ?Sized> {
    ptr: *const (),
    weak: ::std::rc::Weak<T>,
}
  • (and if it weren't for this very caveat regarding T = dyn Trait case, I'd even suggest to drop ptr altogether and use Weak::ptr_eq())
4 Likes

Comparing trait objects pointers compares an vtable addresses which are not guaranteed to be unique and could vary between different code generation units. Furthermore vtables for different types could have the same address after being merged together.

Okay, you're right; thanks for pointing this out.