I'd like to define a trait that has as supertrait another trait with its own trait object type as an associated type:
/// A trait for making things.
trait Make {
type Output: ?Sized;
fn make(self: Box<Self>) -> Box<Self::Output>;
}
/// A special case of Make, which makes things that impl the same trait.
trait Bootstrapper: Make<Output = dyn Bootstrapper> {} // Will NOT compile.
However, I can't do this because it creates an infinite cycle. In the example above, I would need to specify Output for dyn Bootstrapper, which is itself (dyn Bootstrapper). But then, I'd need to specify Output for that dyn Bootstrapper, and so on and so forth, e.g. Make<Output = dyn Bootstrapper<Output = dyn Bootstrapper<Output = dyn Bootstrapper<...>>>.
The Rust compiler seems to agree that this won't work:
error[E0391]: cycle detected when computing the supertraits of `Bootstrapper`
--> src/lib.rs:8:1
|
8 | trait Bootstrapper: Make<Output = dyn Bootstrapper> {} // Will NOT compile.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires computing the supertraits of `Bootstrapper`, completing the cycle
note: cycle used when collecting item types in top-level module
--> src/lib.rs:8:1
|
8 | trait Bootstrapper: Make<Output = dyn Bootstrapper> {} // Will NOT compile.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I also can't specify Output = Self because that would overly constrain the trait, so that a given implementation of Bootstrapper could only make() more of itself. I want a Bootstrapper to be able to make() other kinds of Bootstrapper. Please see this Rust playground for an example of (roughly) what I'm trying to do.
Is there a way to get around this, and have Bootstrapper specify Bootstrapper (not Self) for Output?