Hello! I am learning Rust and am trying to modify my code to use an object+dynamic dispatch. However, I don't understand enough about the Rust object model to do this successfully. I put together this playground with a simplified version of my code and the issues.
Apologies if these questions have been answered before--I wasn't able to find them when searching.
My first question is really a few related questions. I'll walk through my code and then ask at the end. If I were to create my trait in the playground in the following way:
trait Data {
fn get_value<T: Copy>(&self, offset: I) -> T;
}
impl Data for [u8] { ... }
I can call get_value
on a slice (or array) and everything works as I expected:
const TWO_BYTES: [u8; 2] = [0xAA, 0xBB];
TWO_BYTES.get_value::<u16>(0)
However, if I want to make my trait object safe, I have to remove the generic method from the interface. I understand why the generic method inhibits creating a vtable, but I thought by moving the generic method to an impl
, it would still be available as part of the type:
trait Data {
type Index: From<usize>;
fn get_bytes(&self, offset: Self::Index, buf: &mut [u8]);
}
impl<I> dyn Data<Index = I>
where
I: From<usize>,
{
fn get_value<T: Copy>(&self, offset: I) -> T { ... }
}
impl Data for [u8] { ... }
Unfortunately, this doesn't work how I expected (I was thinking this would be similar to a Swift protocol extension). It breaks the existing get_value
call sites and I cannot find a way to call get_value
with [u8]
types.
To help build up my object model understanding and resolve the issues:
- How does the compiler resolve methods implemented in
impl dyn Trait
? Does the type name have to literally spell that (likeget_first_word
in the playground and below)? - Is there a way I can call the
impl dyn Trait
methods from something with a concrete type (e.g.[u8]
) since the trait is implemented for that type? - Similar to (2) but more generally, is there a more idiomatic pattern to solve using generic methods on with object traits in Rust?
Any additional information or pointers on the Rust object model to help develop my mental model would be greatly appreciated! I've read through Rust By Example, The Rust Programming Language, and The Rust Reference, but unfortunately didn't find (or understand) the concepts necessary to answer these questions.
My second question is, in this example, what has the static
lifetime? The vtable for the object, the referenced object instance, or something else?
fn get_first_word<Index>(data: &'static dyn Data<Index = Index>) -> u16
Thanks in advance for your time and thoughts!