---
# System prepended metadata

title: trait system refactor evaluate notes

---

# trait system refactor evaluate notes


assemble candidates should eagerly evaluate them. This requires us to use canonical results. We may have to cache trait candidate assembly as it's reused by `normalizes-to`. We can map stuff in `Canonical` as long as we don't add or remove canonicalized or bound variables in the process. This means that going from `CanonicalGoal` to `CanonicalTraitGoal` doesn't have to re-canonicalize.

caching `assemble_trait_candidates` is dangerous as its used both by `NormalizesTo` and by trait goals. Idea: all normalizes to goals start by eagerly checking the corresponding trait goal.

## query response

original idea was to only have `ExternalConstraints` for `Yes`, this is annoying as we have to somehow instantiate the canonical query result. Merging `Yes` and `Maybe` makes this a lot easier.

The response will still diverge from the existing `QueryResponse`, both in how it is built (we don't have a `FulfillmentContext` after all), and its contents (`Overflow`). Going with a different type for now. Should merge them once the new solver is in a stable-ish state.

## making outlives goals canonical

It's nice to simply have `evaluate_goal` and canonicalize and cache everything. But considering that especially region outlives goals are completely trivial as we erase all region information, fully canonicalizing everything is probably not worth it. Can figure out how to do that at a later point :shrug: 

## projection and normalizes-to

How do we deal with them? In rustc rn we only have `Projection` goals. Can we try to change them to normalizes-to goals in general? Probably not with eager inference replacement. So maybe change their behavior depending on which solver we're in.

## coinduction, guessing substitutions and overflow

We repeately rerun evaluate until we reach a fixpoint for coinduction. This does have a few issues:
- how do we deal with overflow, probably the same way we do it for `AND`.
- because we're making guesses during solving, we may not actually work towards a fixpoint? That might not be an issue as we simply rerun in that case, but it does mean that coinduction may not necessarily result in ever increasing types so the type size limit would not be enough.

## reusing trait candidates in project

Converting assemble trait candidates and evaluate to a pseudo-query is hard because it would then also deal with coinductive cycles and what not.

If we don't cache the results of `assemble_and_evaluate_trait_candidates` we can just as well fully reimplement assemble for impls and the few relevant builtin candidates. It may actually make the code easier to read and also makes it easier to switch to the full "projection is also unification model".