Skip to content

Commit a6294b7

Browse files
committed
update/remove some old readmes
1 parent 14ea6e5 commit a6294b7

File tree

4 files changed

+85
-161
lines changed

4 files changed

+85
-161
lines changed

src/librustc/infer/lexical_region_resolve/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
> WARNING: This README is obsolete and will be removed soon! For
44
> more info on how the current borrowck works, see the [rustc guide].
5+
>
6+
> As of edition 2018, region inference is done using Non-lexical lifetimes,
7+
> which is described in the guide and [this RFC].
58
69
[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
10+
[this RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md
711

812
## Terminology
913

Original file line numberDiff line numberDiff line change
@@ -1,77 +1,3 @@
1-
# Region constraint collection
2-
3-
> WARNING: This README is obsolete and will be removed soon! For
4-
> more info on how the current borrowck works, see the [rustc guide].
1+
For info on how the current borrowck works, see the [rustc guide].
52

63
[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
7-
8-
## Terminology
9-
10-
Note that we use the terms region and lifetime interchangeably.
11-
12-
## Introduction
13-
14-
As described in the rustc guide [chapter on type inference][ti], and unlike
15-
normal type inference, which is similar in spirit to H-M and thus
16-
works progressively, the region type inference works by accumulating
17-
constraints over the course of a function. Finally, at the end of
18-
processing a function, we process and solve the constraints all at
19-
once.
20-
21-
[ti]: https://rust-lang.github.io/rustc-guide/type-inference.html
22-
23-
The constraints are always of one of three possible forms:
24-
25-
- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be
26-
a subregion of Rj
27-
- `ConstrainRegSubVar(R, Ri)` states that the concrete region R (which
28-
must not be a variable) must be a subregion of the variable Ri
29-
- `ConstrainVarSubReg(Ri, R)` states the variable Ri should be less
30-
than the concrete region R. This is kind of deprecated and ought to
31-
be replaced with a verify (they essentially play the same role).
32-
33-
In addition to constraints, we also gather up a set of "verifys"
34-
(what, you don't think Verify is a noun? Get used to it my
35-
friend!). These represent relations that must hold but which don't
36-
influence inference proper. These take the form of:
37-
38-
- `VerifyRegSubReg(Ri, Rj)` indicates that Ri <= Rj must hold,
39-
where Rj is not an inference variable (and Ri may or may not contain
40-
one). This doesn't influence inference because we will already have
41-
inferred Ri to be as small as possible, so then we just test whether
42-
that result was less than Rj or not.
43-
- `VerifyGenericBound(R, Vb)` is a more complex expression which tests
44-
that the region R must satisfy the bound `Vb`. The bounds themselves
45-
may have structure like "must outlive one of the following regions"
46-
or "must outlive ALL of the following regions. These bounds arise
47-
from constraints like `T: 'a` -- if we know that `T: 'b` and `T: 'c`
48-
(say, from where clauses), then we can conclude that `T: 'a` if `'b:
49-
'a` *or* `'c: 'a`.
50-
51-
## Building up the constraints
52-
53-
Variables and constraints are created using the following methods:
54-
55-
- `new_region_var()` creates a new, unconstrained region variable;
56-
- `make_subregion(Ri, Rj)` states that Ri is a subregion of Rj
57-
- `lub_regions(Ri, Rj) -> Rk` returns a region Rk which is
58-
the smallest region that is greater than both Ri and Rj
59-
- `glb_regions(Ri, Rj) -> Rk` returns a region Rk which is
60-
the greatest region that is smaller than both Ri and Rj
61-
62-
The actual region resolution algorithm is not entirely
63-
obvious, though it is also not overly complex.
64-
65-
## Snapshotting
66-
67-
It is also permitted to try (and rollback) changes to the graph. This
68-
is done by invoking `start_snapshot()`, which returns a value. Then
69-
later you can call `rollback_to()` which undoes the work.
70-
Alternatively, you can call `commit()` which ends all snapshots.
71-
Snapshots can be recursive---so you can start a snapshot when another
72-
is in progress, but only the root snapshot can "commit".
73-
74-
## Skolemization
75-
76-
For a discussion on skolemization and higher-ranked subtyping, please
77-
see the module `middle::infer::higher_ranked::doc`.

src/librustc_data_structures/obligation_forest/README.md

-81
This file was deleted.

src/librustc_data_structures/obligation_forest/mod.rs

+80-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,84 @@
11
//! The `ObligationForest` is a utility data structure used in trait
2-
//! matching to track the set of outstanding obligations (those not
3-
//! yet resolved to success or error). It also tracks the "backtrace"
4-
//! of each pending obligation (why we are trying to figure this out
5-
//! in the first place). See README.md for a general overview of how
6-
//! to use this class.
2+
//! matching to track the set of outstanding obligations (those not yet
3+
//! resolved to success or error). It also tracks the "backtrace" of each
4+
//! pending obligation (why we are trying to figure this out in the first
5+
//! place).
6+
//!
7+
//! ### External view
8+
//!
9+
//! `ObligationForest` supports two main public operations (there are a
10+
//! few others not discussed here):
11+
//!
12+
//! 1. Add a new root obligations (`push_tree`).
13+
//! 2. Process the pending obligations (`process_obligations`).
14+
//!
15+
//! When a new obligation `N` is added, it becomes the root of an
16+
//! obligation tree. This tree can also carry some per-tree state `T`,
17+
//! which 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
20+
//! with every pending obligation (so that will include `N`, the first
21+
//! time). The callback also receives a (mutable) reference to the
22+
//! per-tree state `T`. The callback should process the obligation `O`
23+
//! that 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+
//!
44+
//! When the call to `process_obligations` completes, you get back an `Outcome`,
45+
//! which 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.
63+
//!
64+
//! #### Snapshots
65+
//!
66+
//! The `ObligationForest` supports a limited form of snapshots; see
67+
//! `start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In
68+
//! particular, you can use a snapshot to roll back new root
69+
//! obligations. However, it is an error to attempt to
70+
//! `process_obligations` during a snapshot.
71+
//!
72+
//! ### Implementation details
73+
//!
74+
//! For the most part, comments specific to the implementation are in the
75+
//! code. This file only contains a very high-level overview. Basically,
76+
//! the forest is stored in a vector. Each element of the vector is a node
77+
//! in some tree. Each node in the vector has the index of an (optional)
78+
//! parent and (for convenience) its root (which may be itself). It also
79+
//! has a current state, described by `NodeState`. After each
80+
//! processing step, we compress the vector to remove completed and error
81+
//! nodes, which aren't needed anymore.
782
883
use fx::{FxHashMap, FxHashSet};
984

0 commit comments

Comments
 (0)