Description
Using an associated type as an argument to a GAT will sometimes fail with an incorrect [E0277]
"trait bound is not satisfied" error, when that type is used to constrain an associated type of another trait.
#![feature(generic_associated_types)]
trait SomeTrait {}
trait OtherTrait { type Item; }
trait ErrorSimpleExample {
type AssociatedType: SomeTrait;
type GatBounded<T: SomeTrait>;
type ErrorMinimal: OtherTrait<Item = Self::GatBounded<Self::AssociatedType>>;
}
Playground link including the other examples in this issue
This code should compile fine. In particular, Self::GatBounded<Self::AssociatedType>
should be valid because Self::AssociatedType
is constrained to implement SomeTrait
.
However, the compilation fails with the following error:
error[E0277]: the trait bound `<Self as ErrorSimpleExample>::AssociatedType: SomeTrait` is not satisfied
--> src/lib.rs:9:35
|
9 | type ErrorMinimal: OtherTrait<Item = Self::GatBounded<Self::AssociatedType>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait` is not implemented for `<Self as ErrorSimpleExample>::AssociatedType`
|
note: required by a bound in `ErrorSimpleExample::GatBounded`
--> src/lib.rs:8:24
|
8 | type GatBounded<T: SomeTrait>;
| ^^^^^^^^^ required by this bound in `ErrorSimpleExample::GatBounded`
help: consider further restricting the associated type
|
6 | trait ErrorSimpleExample where <Self as ErrorSimpleExample>::AssociatedType: SomeTrait {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
For more information about this error, try `rustc --explain E0277`.
The trait bound Self::AssociatedType: SomeTrait
is obviously satisfied, so something is wrong here. The suggested where
clause does not fix the error, instead the compiler will suggest you add another one.
Adding the same bound again and again
#![feature(generic_associated_types)]
trait SomeTrait {}
trait OtherTrait {
type Item;
}
trait ErrorSimpleExample
where
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
<Self as ErrorSimpleExample>::AssociatedType: SomeTrait,
{
type AssociatedType: SomeTrait;
type GatBounded<T: SomeTrait>;
type ErrorMinimal: OtherTrait<Item = Self::GatBounded<Self::AssociatedType>>;
}
help: consider further restricting the associated type
|
15 | <Self as ErrorSimpleExample>::AssociatedType: SomeTrait, <Self as ErrorSimpleExample>::AssociatedType: SomeTrait
|
Further observations
Spreading types over several traits causes the same issue
This error occurs even if the first two type
s, AssociatedType
and GatBounded
, are part of other traits (implemented either by Self
or some generic type arguments).
trait ExampleSetup {
type AssociatedTypeOfSomeTrait: SomeTrait;
type GatBoundedOnSomeTrait<T: SomeTrait>;
}
trait ErrorUsingSupertrait: ExampleSetup {
type ErrorSupertrait: OtherTrait<Item = Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>>;
}
Error also happens in generic argument
trait ErrorInTraitArgument: ExampleSetup {
type ErrorTraitArg: From<Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>>;
}
Error affected by other items in trait
The error seems to be affected by the presence and ordering of other items in the trait. This code happily compiles:
trait OkInReturnBefore: ExampleSetup {
fn ok_before_type() -> Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>;
type OkAfterFn: OtherTrait<Item = Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>>;
}
But swapping the two items causes the above error:
trait ErrorInReturnAfter: ExampleSetup {
type ErrorBeforeFn: OtherTrait<Item = Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>>;
fn error_after_type() -> Self::GatBoundedOnSomeTrait<Self::AssociatedTypeOfSomeTrait>;
}
Make sure to write each test in a separate trait to avoid other items messing with your testing. I initially thought the ErrorTraitArg
example did not produce an error because I had put it into the same trait as other working examples.
Potentially related issue
I found another issue, #88287, that produces the same error message. However, I'm not sure if that is the same bug because I could not get Self::GatBounded<Self::AssociatedType>
to error in only the return type position. That issue's example also uses the TAIT feature (which I'm unfamiliar with) so I was unable to reduce it enough to see similarities to my example.
Meta
rustc --version --verbose
:
rustc 1.56.0-nightly (0afc20860 2021-08-25)
binary: rustc
commit-hash: 0afc20860eb98a29d9bbeea80f2acc5be38c6bf3
commit-date: 2021-08-25
host: x86_64-pc-windows-msvc
release: 1.56.0-nightly
LLVM version: 13.0.0
As well as rust playground 1.56.0-nightly (2021-08-25 0afc20860eb98a29d9bb)
@rustbot label +T-compiler +F-generic_associated_types +A-Traits +requires-nightly