Skip to content

Commit acee479

Browse files
authored
update proof tree chapter (rust-lang#2054)
* update proof tree chapter * uwu * cool beans
1 parent 33731b7 commit acee479

File tree

1 file changed

+35
-38
lines changed

1 file changed

+35
-38
lines changed

Diff for: src/solve/proof-trees.md

+35-38
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
# Proof trees
22

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
3+
While the trait solver itself only returns whether a goal holds and the necessary
4+
constraints, we sometimes also want to know what happened while trying to prove
5+
it. While the trait solver should generally be treated as a black box by the rest
6+
of the compiler, we cannot completely ignore its internals and provide "proof trees"
7+
as an interface for this. To use them you implement the [`ProofTreeVisitor`] trait,
8+
see its existing implementations for examples. The most notable uses are to compute
9+
the [intercrate ambiguity causes for coherence errors][intercrate-ambig],
10+
[improving trait solver errors][solver-errors], and
11+
[eagerly inferring closure signatures][closure-sig].
12+
13+
## Computing proof trees
2314

2415
The trait solver uses [Canonicalization] and uses completely separate `InferCtxt` for
2516
each nested goal. Both diagnostics and auto-traits in rustdoc need to correctly
@@ -29,22 +20,28 @@ canonicalize to `exists<T0> Vec<Vec<T0>>: Debug`, instantiate that goal as
2920
`exists<T0> Vec<T0>: Debug`, instantiate this as `Vec<?0>: Debug` which then results
3021
in a nested `?0: Debug` goal which is ambiguous.
3122

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
23+
We compute proof trees by passing a [`ProofTreeBuilder`] to the search graph which is
24+
converting the evaluation steps of the trait solver into a tree. When storing any
25+
data using inference variables or placeholders, the data is canonicalized together
26+
with the list of all unconstrained inference variables created during this computation.
27+
This [`CanonicalState`] is then instantiated in the parent inference context while
28+
walking the proof tree, using the list of inference variables to connect all the
29+
canonicalized values created during this evaluation.
30+
31+
## Debugging the solver
32+
33+
We previously also tried to use proof trees to debug the solver implementation. This
34+
has different design requirements than analyzing it programmatically. The recommended
35+
way to debug the trait solver is by using `tracing`. The trait solver only uses the
36+
`debug` tracing level for its general 'shape' and `trace` for additional detail.
37+
`RUSTC_LOG=rustc_next_trait_solver=debug` therefore gives you a general outline
38+
and `RUSTC_LOG=rustc_next_trait_solver=trace` can then be used if more precise
39+
information is required.
40+
41+
[`ProofTreeVisitor`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs#L403
42+
[`ProofTreeBuilder`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs#L40
43+
[`CanonicalState`]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_type_ir/src/solve/inspect.rs#L31-L47
44+
[intercrate-ambig]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/traits/coherence.rs#L742-L748
45+
[solver-errors]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_trait_selection/src/solve/fulfill.rs#L343-L356
46+
[closure-sig]: https://github.com/rust-lang/rust/blob/d6c8169c186ab16a3404cd0d0866674018e8a19e/compiler/rustc_hir_typeck/src/closure.rs#L333-L339
5047
[Canonicalization]: ./canonicalization.md

0 commit comments

Comments
 (0)