Now, i want to use this struct as a member of another struct in such a way that i could pass any struct to it as long as the struct implements the trait
pub struct Bar <'a> {
abc: &'a str,
def: T, // <--- Looking for something to replace this with
}
impl <'a> Bar <'a> {
pub fn some_function(&self) {
self.def.foo();
}
}
(ignore stuff such as lifetimes from the code as these are there for other reasons)
But this isn't possible. Is there a way I could pass in saying to accept any struct that implements the trait? (as i typed this I realised this looks unlikely)
Or should I change this to use traits or any other constructs instead?
Alternatively, if you don't want Bar parameterized, you can use a trait object, like def: Box<SomeTrait> or def: &'a SomeTrait depending on whether you want to own the value.
As another alternative, if you add the + ?Sized bound to T, and you're using Bar through a pointer of some kind, you can coerce any Bar<T> into a Bar<SomeTrait> and stop the propagation of type parameters.
Note: as a general recommendation, don't put trait bounds directly on a struct when it is avoidable (because such bounds are forced to appear all over the code). Instead, put it on the functions or impls which require that trait.
pub struct Bar<'a, T> { // Note: No mention of SomeTrait here
abc: &'a str,
def: T,
}
impl<'a, T> Bar<'a>
where T: SomeTrait // <-- this is where we do it
{
pub fn some_function(&self) {
self.def.foo();
}
}
There are only three instances where you are required to put a bound in the struct itself:
when the object has a field of an associated type
(see std::borrow::Cow which has a ToOwned bound because it actually may contain the associated type <B as ToOwned>::Owned)
(similarly Peekable holds a <T as Iterator>::Item)
when that trait is used in the destructor
(examples are rare; I could only find one in the standard library; that type needs Ord because its drop impl calls a method that requires Ord)
when you carry another struct that has a bound. (see? It's infectous!)
This should go away with https://github.com/rust-lang/rfcs/pull/2089. I actually find bounds on impls backwards when the struct can only function (or intended to) with a certain bound.
Man, that ergonomics initiative just keeps surprising!
Hmm, go figure, though, we'll still need K: Eq + Hash + Clone everywhere we want to use HashMaps, since the standard library types obviously cannot add the bounds to the type without breaking backwards compatibility...