To cover the basic trait lowering, we define a few domain goals:
DomainGoal := Implemented(TraitRef)
| Declared(TraitRef)
| FromEnv(TraitRef)
| ... // other kinds of domain goals exist, but they are not relevant here
// A "TraitRef" is a trait plus its input parameters
TraitRef := P0: Trait<P1..Pn>
// A parameter "P" is either a type or a lifetime
P := <type> | <lifetime>
You might be surprised to see all of the options. The reasons we have them is to accommodate implied bounds. Let’s walk through the goals one by one:
Implemented(TraitRef) — this means that the trait-ref is considered fully implemented. This implies both that there is an impl for the trait-reference but also that all where clauses declared on the trait are satisfied.
Declared(TraitRef) — this means that an impl of TraitRef exists
FromEnv(TraitRef) — this means that TraitRef appears in the environment(e.g., when checking a function with where-clause).
DomainGoal := Implemented(TraitRef)
| Declared(TraitRef)
| FromEnv(TraitRef)
| ... // other kinds of domain goals exist, but they are not relevant here
// A "TraitRef" is a trait plus its input parameters
TraitRef := P0: Trait<P1..Pn>
// A parameter "P" is either a type or a lifetime
P := <type> | <lifetime>
// from the trait:
trait Trait<V..> where WC { }
// forall<Self, V..> { Implemented(Self: Trait<V..>) :- FromEnv(Self: Trait<V..>) }
// forall<Self, V..> { FromEnv(WC) :- FromEnv(Self: Trait<V..>) }
// forall<Self, V..> {
// Implemented(Self: Trait<V..>) :-
// Declared(Self: Trait<V..>),
// Implemented(WC)
// }
// User gives:
impl<V..> Trait<P1..> for P0 { .. }
// forall<V..> { Declared(P0: Trait<P1..>) }