I'm trying to use traits to remove arbitrary levels of nesting from nested structs, like peeling an onion:
#[derive(Debug)]
pub struct A();
pub trait Foo {}
impl Foo for A {}
#[derive(Debug)]
pub struct Container<C: Foo> {
contents: C, //container contains a `Foo`
}
//containers are themselves `Foo` so they can be nested, like layers of an onion
impl<C: Foo> Foo for Container<C> {}
//T being `ContainsFoo<F>` means T contains a `Foo` of type F and T is itself `Foo`
pub trait ContainsFoo<F: Foo>: Foo {
fn get(&self) -> &F; //get the contained F
}
//a `Foo` of type F trivially "contains" a `Foo` of type F (itself)
impl<F: Foo> ContainsFoo<F> for F {
fn get(&self) -> &F {
self
}
}
//if C is `ContainsFoo<F>`, then `Container<C>` also contains an F (the one contained in C)
//together with the above trait impl, this should allow us to go from any level of nested containers to any lower level,
//in other words: to peel an arbitrary number of layers from the onion
impl <F: Foo, C: ContainsFoo<F>> ContainsFoo<F> for Container<C> {
fn get(&self) -> &F {
self.contents.get()
}
}
This produces an error:
error[E0119]: conflicting implementations of trait `ContainsFoo<Container<_>>` for type `Container<_>`
--> src/main.rs:29:1
|
20 | impl<F: Foo> ContainsFoo<F> for F {
| --------------------------------- first implementation here
...
29 | impl <F: Foo, C: ContainsFoo<F>> ContainsFoo<F> for Container<C> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Container<_>`
Maybe I've been staring at this for too long, but I can't find a combination of values for the generic parameters that would create such a conflict. Container<_> is not a real type after all?
Playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=2f1c620b2c139f057a73392120b9a525
A browser interface to the Rust compiler to experiment with the language