Hi.
I have two traits A and B<T>, and struct C. C implements B<SomeType> and dyn B<T> implements A.
I can use method of A by (&c as &dyn B<SomeType>).method(), but are there any other way?
That's the only way. &C can be converted to &dyn B<T> just like i32 can be converted to i64.
No, the compiler needs to know what trait object type you're using. C could implement B<SomeType> and B<AnotherType>, and then c.method() would be ambiguous.
Possible alternatives might include making T an associated type like E is, adding a type parameter to C, adding a type parameter to A, or writing a new trait with a type parameter and a blanket impl for U: B<T>. That last one sounds complicated so here's what I mean:
trait Hello<T> {
type Err;
fn hello(&self);
}
impl<T, U: 'static + b::B<T>> Hello<T> for U {
type Err = U::E;
fn hello(&self) {
a::A::hello(self as &dyn b::B<T, E = Self::Err>);
}
}
fn main() {
let c = c::C {};
c.hello(); // the compiler can figure out `T` at this point
}
(Note that this relies on there being only one B<?> implemented for C; if you add another B implementation, you'll have to specify which one by writing something like <C as Hello<u8>>::hello(&c).)
For a situation like this, Iād provide an as_a() method on B, and also (more optionally) a struct that can use static dispatch instead of dynamic:
mod b {
pub trait B<T> {
type E;
fn as_a(&'_ self) -> AsA<'_, T, Self> {
AsA {
val: self,
param: std::marker::PhantomData,
}
}
}
pub struct AsA<'a, T, Inner: 'a + ?Sized> {
val: &'a Inner,
param: std::marker::PhantomData<T>,
}
impl<'a, T, Inner: B<T> + 'a + ?Sized> crate::a::A for AsA<'a, T, Inner> {}
}
fn main() {
let c = c::C {};
c.as_a().hello();
}
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.