Restricting generics to traits
There's no simple way of restricting a generic U to trait V, because the ?Sized
bound can accept traits, but does not require traits.
However, you can create a marker trait to assign with this:
/// A marker for a trait type
pub trait Implements<T: ?Sized> {}
#[cfg(test)]
mod test {
use std::marker::PhantomData;
use super::Implements;
trait Foo { fn hi(&self); }
struct Bar { x: u32 }
struct FooBar<U, V: ?Sized> where U: Implements<V> {
pub instance: U,
pub _v: PhantomData<*const V>
}
impl Foo for Bar {
fn hi(&self) { println!("Hello {}", self.x ); }
}
impl Implements<Foo> for Bar {}
impl<U, V: ?Sized> FooBar<U, V> where U : Implements<V> {
pub fn as_ref(&self) -> &U {
return &self.instance;
}
}
#[test]
fn test_trait() {
let x:FooBar<Bar, Foo> = FooBar {
instance: Bar { x: 100u32 },
_v: PhantomData
};
x.as_ref().hi();
}
Notice how we can now create a generic handler to accept this type:
fn receive_target<T>(target: &FooBar<T, Foo>) where T: Foo + Implements<Foo> {
target.as_ref().hi();
}
#[test]
fn test_trait() {
let x:FooBar<Bar, Foo> = FooBar {
instance: Bar { x: 100u32 },
_v: PhantomData
};
receive_target(&x);
}