Home > Enterprise >  Nested generic impl
Nested generic impl

Time:05-21

I don't understand why rust don't allow to use a generic inside an other generic constraint.

It's difficult to explain with normal words but for example this simple code don't work

trait GenericTraitA<T1> {}

trait GenericTraitB<T2> {}

impl<T1, T2: GenericTraitA<T1>> dyn GenericTraitB<T2> {}

It says that:

the type parameter T1 is not constrained by the impl trait, self type, or predicates

But i don't see why this is not constrained, i don't understand the ambiguity inside this code.

CodePudding user response:

What that compiler error is saying is, with that impl block definition, it would not be able to determine the appropriate type to substitute in for T1. Let's look at a concrete example to demonstrate this:

pub trait Trait<T> {
    fn foo(&self);
}

struct Bar;

impl Trait<u32> for Bar {
    fn foo(&self) {
        println!("u32 impl");
    }
}

impl Trait<u64> for Bar {
    fn foo(&self) {
        println!("u64 impl");
    }
}

impl<T, U> U
where
    U: Trait<T>,
{
    fn call_foo(&self) {
        self.foo();
    }
}

fn main() {
    let bar = Bar;
    bar.call_foo();
}

Trying to compile this program yields the following error:

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:19:6
   |
19 | impl<T, U> U
   |      ^ unconstrained type parameter

The reason why this error exists is that bar.call_foo() has ambiguous behavior if we were to allow that impl block to be well-formed. Bar implements both Trait<u32> and Trait<u64>, but how do we know which version of foo we're supposed to call? The answer is that we don't, which is why this program doesn't compile.

  • Related