|
| 1 | +# Proof trees |
| 2 | + |
| 3 | +The trait solver can optionally emit a "proof tree", a tree representation of what |
| 4 | +happened while trying to prove a goal. |
| 5 | + |
| 6 | +The used datastructures for which are currently stored in |
| 7 | +[`rustc_middle::traits::solve::inspect`]. |
| 8 | + |
| 9 | +## What are they used for |
| 10 | + |
| 11 | +There are 3 intended uses for proof trees. These uses are not yet implemented as |
| 12 | +the representation of proof trees itself is currently still unstable. |
| 13 | + |
| 14 | +They should be used by type system diagnostics to get information about |
| 15 | +why a goal failed or remained ambiguous. They should be used by rustdoc to get the |
| 16 | +auto-trait implementations for user-defined types, and they should be usable to |
| 17 | +vastly improve the debugging experience of the trait solver. |
| 18 | + |
| 19 | +For debugging you can use `-Zdump-solver-proof-tree` which dumps the proof tree |
| 20 | +for all goals proven by the trait solver in the current session. |
| 21 | + |
| 22 | +## Requirements and design constraints for proof trees |
| 23 | + |
| 24 | +The trait solver uses [Canonicalization] and uses completely separate `InferCtxt` for |
| 25 | +each nested goal. Both diagnostics and auto-traits in rustdoc need to correctly |
| 26 | +handle "looking into nested goals". Given a goal like `Vec<Vec<?x>>: Debug`, we |
| 27 | +canonicalize to `exists<T0> Vec<Vec<T0>>: Debug`, instantiate that goal as |
| 28 | +`Vec<Vec<?0>>: Debug`, get a nested goal `Vec<?0>: Debug`, canonicalize this to get |
| 29 | +`exists<T0> Vec<T0>: Debug`, instantiate this as `Vec<?0>: Debug` which then results |
| 30 | +in a nested `?0: Debug` goal which is ambiguous. |
| 31 | + |
| 32 | +We need to be able to figure out that `?x` corresponds to `?0` in the nested queries. |
| 33 | + |
| 34 | +The debug output should also accurately represent the state at each point in the solver. |
| 35 | +This means that even though a goal like `fn(?0): FnOnce(i32)` infers `?0` to `i32`, the |
| 36 | +proof tree should still store `fn(<some infer var>): FnOnce(i32)` instead of |
| 37 | +`fn(i32): FnOnce(i32)` until we actually infer `?0` to `i32`. |
| 38 | + |
| 39 | +## The current implementation and how to extract information from proof trees. |
| 40 | + |
| 41 | +Proof trees will be quite involved as they should accurately represent everything the |
| 42 | +trait solver does, which includes fixpoint iterations and performance optimizations. |
| 43 | + |
| 44 | +We intend to provide a lossy user interface for all usecases. |
| 45 | + |
| 46 | +TODO: implement this user interface and explain how it can be used here. |
| 47 | + |
| 48 | + |
| 49 | +[`rustc_middle::traits::solve::inspect`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/traits/solve/inspect/index.html |
| 50 | +[Canonicalization]: ./canonicalization.md |
0 commit comments