# Proof trees While the trait solver itself only returns whether a goal holds and the necessary constraints, we sometimes also want to know what happened while trying to prove it. While the trait solver should generally be treated as a black box by the rest of the compiler, we cannot completely ignore its internals and provide "proof trees" as an interface for this. To use them you implement the [`ProofTreeVisitor`] trait, see its existing implementations for examples. The most notable uses are to compute the [intercrate ambiguity causes for coherence errors][intercrate-ambig], [improving trait solver errors][solver-errors], and [eagerly inferring closure signatures][closure-sig]. ## Computing proof trees The trait solver uses [Canonicalization] and uses completely separate `InferCtxt` for each nested goal. Both diagnostics and auto-traits in rustdoc need to correctly handle "looking into nested goals". Given a goal like `Vec>: Debug`, we canonicalize to `exists Vec>: Debug`, instantiate that goal as `Vec>: Debug`, get a nested goal `Vec: Debug`, canonicalize this to get `exists Vec: Debug`, instantiate this as `Vec: Debug` which then results in a nested `?0: Debug` goal which is ambiguous. We compute proof trees by passing a [`ProofTreeBuilder`] to the search graph which is converting the evaluation steps of the trait solver into a tree. When storing any data using inference variables or placeholders, the data is canonicalized together with the list of all unconstrained inference variables created during this computation. This [`CanonicalState`] is then instantiated in the parent inference context while walking the proof tree, using the list of inference variables to connect all the canonicalized values created during this evaluation. ## Debugging the solver We previously also tried to use proof trees to debug the solver implementation. This has different design requirements than analyzing it programmatically. The recommended way to debug the trait solver is by using `tracing`. The trait solver only uses the `debug` tracing level for its general 'shape' and `trace` for additional detail. `RUSTC_LOG=rustc_next_trait_solver=debug` therefore gives you a general outline and `RUSTC_LOG=rustc_next_trait_solver=trace` can then be used if more precise information is required. [`ProofTreeVisitor`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs#L403 [`ProofTreeBuilder`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs#L40 [`CanonicalState`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_type_ir/src/solve/inspect.rs#L31-L47 [intercrate-ambig]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/traits/coherence.rs#L742-L748 [solver-errors]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/solve/fulfill.rs#L343-L356 [closure-sig]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_hir_typeck/src/closure.rs#L333-L339 [Canonicalization]: ./canonicalization.md