I'm attempting to implement a trait from crate A for a trait from crate B using static dispatch. I'm wrapping the foreign trait, but am having trouble with the impl<T>
line:
extern crate a;
extern crate b;
pub trait C: a::A {}
impl<T: C> b::B for T {}
The end result I am looking for is implementing b::B
for implementors of trait C
, using static dispatch.
I'm getting the following error:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> c/src/lib.rs:3:1
|
3 | impl<T: C> b::B for T {}
| ^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
I'm able to get around this by using dynamic dispatch — impl b::B for dyn C
— but want to accomplish this with static dispatch.
I've already tried:
Vec
, but my own typeGenerics have two major advantages over trait objects: Speed. When the compiler generates machine code for a generic function, it knows which types it's working with, so it knows at that time which writemethod to call. No need for dynamic dispatch.
Intro to Generics A generic function or type can be used with values of many different types.
A trait is a feature that any given type may or may not support. Think of a trait as a type capability. Rule: For trait methods to be accessible, the trait itself must be in scope! Otherwise, all of its methods are hidden. #![allow(unused)] fn main() { let mut buf: Vec<u8> = vec![]; buf.write_all(b"hello!")?; // ERR: no method named write_all }
Term: A trait that adds a single method to a type is called an extension traits. Generic implblocks can be used to add an extension trait to a whole family of types at once.
What I usually do is wrapping the foreign type in a struct
(as opposed to introducing a new trait
deriving from the foreign one):
extern crate a;
extern crate b;
pub struct C<T: a::A> {
pub t: T,
}
impl<T: a::A> b::B for C<T> {}
This, however, sometimes requires some boilerplate to convert between C
and the "normal" type.
This is sometimes called "NewType pattern" (as in https://github.com/Ixrec/rust-orphan-rules).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With