I found this in diesel, but I expect to see it happen elsewhere.
trait HasMetadata {
type Metadata;
}
struct Sql;
impl HasMetadata for Sql {
type Metadata = ();
}
trait Process<T>: HasMetadata {
fn process(t: T, metadata: Self::Metadata);
}
impl<T> Process<T> for Sql /* imagine `T` has some constraints that doesn't just make this an always-applicable blanket impl */ {
fn process(t: T, metadata: Self::Metadata) {}
}
fn process<T>() where Sql: Process<T> {
Sql::process((), ());
//~^ ERROR because `<Sql as HasMetadata>::Metadata != ()`
}
Basically, a crate will have a meaningful param-env like Rigid: Trait<T> which elaborates into a trivial param-env candidate like Rigid: OtherTrait. That causes <Rigid as OtherTrait>::Assoc to no longer project.
This is hard to work around, because users can't just control the elaboration of their where clauses, and the where clause they wrote (i.e. Rigid: Trait<T>) does mention params and therefore is needed in the environment.
I found this in diesel, but I expect to see it happen elsewhere.
Basically, a crate will have a meaningful param-env like
Rigid: Trait<T>
which elaborates into a trivial param-env candidate likeRigid: OtherTrait
. That causes<Rigid as OtherTrait>::Assoc
to no longer project.This is hard to work around, because users can't just control the elaboration of their where clauses, and the where clause they wrote (i.e.
Rigid: Trait<T>
) does mention params and therefore is needed in the environment.