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.