Invalid feature binding associated with associated type
Code
pub trait Q<S> {
fn f();
}
pub trait A {
type I;
type F: Q<Self::I>;
}
// this works (1)
//
// pub struct S<T>
// where
// T: A
// {
// unsatisfied trait bound (2)
pub struct S<T>
where
T: A<I = bool>,
{
t: T,
}
fails to compile:
error[E0277]: the trait bound `<T as A>::F: Q<bool>` is not satisfied --> src/main.rs:18:1 | 18 | / pub struct S<T> 19 | | where 20 | | T: A<I = bool>, 21 | | { 22 | | t: T, 23 | | } | |_^ the trait `Q<bool>` is not implemented for `<T as A>::F` | = help: consider adding a `where <T as A>::F: Q<bool>` bound = note: required by `A`
Interestingly, it works if you use the commented line (1) instead of (2). It also works if you include the related type I
in the generic type (write trait A<I>
and A<bool>
).
impl<T> S<T>
where T: A
{
fn g() {
T::F::f()
}
}
does well with line (1) or general type I
, so is T::F : Q<bool>
really assumed in these cases.
Why is trait binding automatically accepted with line (1) or generic types but not with line (2)?
Is it possible to fix the above code without adding where T::F: Q<bool>
every time we use T: A<I=bool>
?
source to share
As with Rust 1.18, the compiler requires you to write these bounds in order for the types to be well formed. In principle, in order to hold the border T: A<I = bool>
, it also requires that an assessment be performed T::F: Q<bool>
. For example, if some type tried to implement it A
like this:
struct Y;
struct Z;
impl A for Y {
type I = bool;
type F = Z; // Z does not implement Q<bool>
}
it Y
will not be formed correctly, because the boundary is T::F: Q<bool>
not met (and indeed, the compiler gives an error on impl
). But, unfortunately, for now, the border T::F: Q<bool>
must be specified explicitly when the border appears T: A<I = bool>
. In a way, it convinces the compiler that, hey, T::I = bool
too!
Why is trait binding automatically accepted with line (1) or generic types but not with line (2)?
With line (1), the estimate will be T::F: Q<T::I>
that exactly the requirement A
(with replacement T
by Self
). Indeed, we can also write the score equivalently like this:
pub trait A
where
Self::F: Q<Self::I>,
{
type I;
type F;
}
With line (2), the border T::F: Q<bool>
may look like a matter of substitution T::I
with bool
, but the difference is important to the compiler; T::I
is a related type, and bool
is a specific type.
The Rust developers are looking into improving the compiler so that such constraints do not have to be repeated throughout the compiler's output of these bounds .
source to share