I'm trying to implement abstractions upon existing abstractions.
In the following code:
I've got Trait1 defined
I've got Trait2 defined upon Trait1
I want to define Trait3 upon Trait2
I want to create Trait3's new method receiving a Vec of Trait2 implementations
I want each element from Vec of Trait2 to have any Trait1 implementation.
pub trait Trait1 {}
pub trait Trait2<X> where X: Trait1 {}
pub trait Trait3 {
/*
wrong number of type arguments: expected 1, found 0
expected 1 type argumentrustc(E0107)
- > underlined "Trait2"
*/
fn new (foo: Vec<Rc<impl Trait2>>) -> Self;
/*
the size for values of type `(dyn Trait1 + 'static)` cannot be known at compilation time
doesn't have a size known at compile-time
help: the trait `std::marker::Sized` is not implemented for `(dyn Trait1 + 'static)`
note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-
types.html#dynamically-sized-types-and-the-sized-trait>rustc(E0277)
-> underlined "Trait2<Trait1>"
*/
fn new (foo: Vec<Rc<impl Trait2<Trait1>>>) -> Self;
/* no compile errors, but I think it fixes Trait1 to a single implementation */
fn new<T>(functions: Vec<Rc<impl Trait2<T>>>) -> Self
where
T: Trait1;
}
Question:
How can I implement new method, so that Trait1 will have any implementation?
The use of ?Sized allows T1 to be unsized, so the user can choose T1 = dyn Trait1 if they wish multiple different ones. Of course, if you want to restrict it to always use dyn Trait1, you could do:
/*
the trait `Trait1` cannot be made into an objectrustc(E0038)
this trait cannot be made into an object...
...because associated function `new` has no `self` parameter
*/
pub trait Trait3 {
fn new<T1: ?Sized, T2>(foo: Vec<Rc<T2>>) -> Self
where
T2: Trait2<T1>, /* <-undelines here */
T1: Trait1;
}