trait Collection<T> {}
trait Nice {}
trait Blue {}
// this works
impl<T> Nice for T
where
T: Collection<usize>
{}
// this does not
impl<T, U> Nice for T
where
T: Collection<U>,
U: Blue,
{}
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:10:9
|
10 | impl<T, U> Nice for T
| ^ unconstrained type parameter
I'm not making this up. I actually need it, and I don't understand why it doesn't work. playground
The compiler can't even decide this case, because that Collection<U> could be implemented in some future crate! For instance, somewhere there could be something like:
struct X;
impl Blue for X {}
impl Collection<X> for i32 {}
... and then your blanket impl would cover Nice for i32 too, everywhere.
The compiler needs a consistent answer whether i32 implements Nice, and it can't wait for all possible crates to decide this. But if it were constrained like Nice<U>, then we only ever need to resolve implementations for a U that we already know about.