]> git.proxmox.com Git - rustc.git/blame - src/librustc_data_structures/obligation_forest/README.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_data_structures / obligation_forest / README.md
CommitLineData
7453a54e
SL
1The `ObligationForest` is a utility data structure used in trait
2matching to track the set of outstanding obligations (those not yet
3resolved to success or error). It also tracks the "backtrace" of each
4pending obligation (why we are trying to figure this out in the first
5place).
6
7### External view
8
9`ObligationForest` supports two main public operations (there are a
10few others not discussed here):
11
121. Add a new root obligations (`push_tree`).
132. Process the pending obligations (`process_obligations`).
14
15When a new obligation `N` is added, it becomes the root of an
16obligation tree. This tree can also carry some per-tree state `T`,
17which is given at the same time. This tree is a singleton to start, so
18`N` is both the root and the only leaf. Each time the
19`process_obligations` method is called, it will invoke its callback
20with every pending obligation (so that will include `N`, the first
21time). The callback also receives a (mutable) reference to the
22per-tree state `T`. The callback should process the obligation `O`
23that it is given and return one of three results:
24
25- `Ok(None)` -> ambiguous result. Obligation was neither a success
26 nor a failure. It is assumed that further attempts to process the
27 obligation will yield the same result unless something in the
28 surrounding environment changes.
29- `Ok(Some(C))` - the obligation was *shallowly successful*. The
30 vector `C` is a list of subobligations. The meaning of this is that
31 `O` was successful on the assumption that all the obligations in `C`
32 are also successful. Therefore, `O` is only considered a "true"
33 success if `C` is empty. Otherwise, `O` is put into a suspended
34 state and the obligations in `C` become the new pending
35 obligations. They will be processed the next time you call
36 `process_obligations`.
37- `Err(E)` -> obligation failed with error `E`. We will collect this
38 error and return it from `process_obligations`, along with the
39 "backtrace" of obligations (that is, the list of obligations up to
40 and including the root of the failed obligation). No further
41 obligations from that same tree will be processed, since the tree is
42 now considered to be in error.
43
44When the call to `process_obligations` completes, you get back an `Outcome`,
45which includes three bits of information:
46
47- `completed`: a list of obligations where processing was fully
48 completed without error (meaning that all transitive subobligations
49 have also been completed). So, for example, if the callback from
50 `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
51 then `O` will be considered completed right away if `C` is the
52 empty vector. Otherwise it will only be considered completed once
53 all the obligations in `C` have been found completed.
54- `errors`: a list of errors that occurred and associated backtraces
55 at the time of error, which can be used to give context to the user.
56- `stalled`: if true, then none of the existing obligations were
57 *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
58 This implies that all obligations were either errors or returned an
59 ambiguous result, which means that any further calls to
60 `process_obligations` would simply yield back further ambiguous
61 results. This is used by the `FulfillmentContext` to decide when it
62 has reached a steady state.
54a0048b 63
7453a54e
SL
64#### Snapshots
65
66The `ObligationForest` supports a limited form of snapshots; see
67`start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In
68particular, you can use a snapshot to roll back new root
69obligations. However, it is an error to attempt to
70`process_obligations` during a snapshot.
71
72### Implementation details
73
74For the most part, comments specific to the implementation are in the
75code. This file only contains a very high-level overview. Basically,
76the forest is stored in a vector. Each element of the vector is a node
77in some tree. Each node in the vector has the index of an (optional)
78parent and (for convenience) its root (which may be itself). It also
79has a current state, described by `NodeState`. After each
80processing step, we compress the vector to remove completed and error
81nodes, which aren't needed anymore.