@@ -24,7 +24,7 @@ The MIR-based region analysis consists of two major functions:
24
24
- [ ` compute_regions ` ] , invoked second: this is given as argument the
25
25
results of move analysis. It has the job of computing values for all
26
26
the inference variables that ` replace_regions_in_mir ` introduced.
27
- - To do that, it first runs the [ MIR type checker] ( #mirtypeck ) . This
27
+ - To do that, it first runs the [ MIR type checker] . This
28
28
is basically a normal type-checker but specialized to MIR, which
29
29
is much simpler than full Rust, of course. Running the MIR type
30
30
checker will however create ** outlives constraints** between
@@ -44,29 +44,26 @@ The MIR-based region analysis consists of two major functions:
44
44
[ `RegionInferenceContext` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html
45
45
[ `solve` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.solve
46
46
[ NLL RFC ] : http://rust-lang.github.io/rfcs/2094-nll.html
47
+ [ MIR type checker ] : ./type_check.md
47
48
48
49
## Universal regions
49
50
50
- * to be written* – explain the ` UniversalRegions ` type
51
+ The [ ` UnversalRegions ` ] type represents a collection of _ unversal_ regions
52
+ corresponding to some MIR ` DefId ` . It is constructed in
53
+ [ ` replace_regions_in_mir ` ] when we replace all regions with fresh inference
54
+ variables. [ ` UniversalRegions ` ] contains indices for all the free regions in
55
+ the given MIR along with any relationships that are _ known_ to hold between
56
+ them (e.g. implied bounds, where clauses, etc.).
51
57
52
- ## Region variables and constraints
58
+ TODO: is there more to write here?
53
59
54
- * to be written* – describe the ` RegionInferenceContext ` and
55
- the role of ` liveness_constraints ` vs other ` constraints ` , plus
60
+ [ `UniversalRegions` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/universal_regions/struct.UniversalRegions.html
56
61
57
- ## Closures
58
-
59
- * to be written*
60
-
61
- <a name =" mirtypeck " ></a >
62
+ ## Region variables
62
63
63
- ## The MIR type-check
64
-
65
- ## Representing the "values" of a region variable
66
-
67
- The value of a region can be thought of as a ** set** ; we call the
68
- domain of this set a ` RegionElement ` . In the code, the value for all
69
- regions is maintained in
64
+ The value of a region can be thought of as a ** set** of points in the MIR where
65
+ the region is valid; we call the domain of this set a ` RegionElement ` . In the
66
+ code, the value for all regions is maintained in
70
67
[ the ` rustc_mir::borrow_check::nll::region_infer ` module] [ ri ] . For
71
68
each region we maintain a set storing what elements are present in its
72
69
value (to make this efficient, we give each kind of element an index,
@@ -90,11 +87,86 @@ The kinds of region elements are as follows:
90
87
for details on placeholders, see the section
91
88
[ placeholders and universes] ( #placeholder ) .
92
89
90
+ ## Constraints
91
+
92
+ Before we can infer the value of regions, we need to collect constraints on the
93
+ regions. There are two primary types of constraints.
94
+
95
+ 1 . Outlives constraints. These are constraints that one region outlives another
96
+ (e.g. ` 'a: 'b ` ). Outlives constraints are generated by the [ MIR type
97
+ checker] .
98
+ 2 . Liveness constraints. Each region needs to be live at points where it can be
99
+ used. These constraints are collected by [ ` generate_constraints ` ] .
100
+
101
+ [ `generate_constraints` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/constraint_generation/fn.generate_constraints.html
102
+
103
+ ## Inference Overview
104
+
105
+ So how do we compute the contents of a region? This process is called _ region
106
+ inference_ . The high-level idea is pretty simple, but there are some details we
107
+ need to take care of.
108
+
109
+ The [ ` RegionInferenceContext ` ] type contains all of the information needed to
110
+ do inference, including the universal regions from ` replace_regions_in_mir ` and
111
+ the constraints computed for each region. It is constructed just after we
112
+ compute the liveness constraints.
113
+
114
+ Here are some of the fields of the struct:
115
+
116
+ - ` constraints ` : contains all the outlives constraints.
117
+ - ` liveness_constraints ` : contains all the liveness constraints.
118
+ - ` universal_regions ` : contains the ` UniversalRegions ` returned by
119
+ ` replace_regions_in_mir ` .
120
+ - ` universal_region_relations ` : contains relations known to be true about
121
+ universal regions. For example, if we have a where clause that ` 'a: 'b ` , that
122
+ relation is assumed to be true while borrow checking the implementation (it
123
+ is checked at the caller), so ` universal_region_relations ` would contain `'a:
124
+ 'b`.
125
+ - ` type_tests ` : contains some constraints on types that we must check after
126
+ inference (e.g. ` T: 'a ` ).
127
+ - ` closure_bounds_mapping ` : used for propagating region constraints from
128
+ closures back out to the creater of the closure.
129
+
130
+ TODO: should we discuss any of the others fields? What about the SCCs?
131
+
132
+ Ok, now that we have constructed a ` RegionInferenceContext ` , we can do
133
+ inference. This is done by calling the [ ` solve ` ] method on the context.
134
+
135
+ We will start off the value of each region with the liveness constraints (the
136
+ places we already know must be in the region). We will then use the outlives
137
+ constraints to widen each region until all constraints are met. This is done in
138
+ [ ` propagate_constraints ` ] . For each region, if ` 'a: 'b ` , we add all elements of
139
+ ` 'b ` to ` 'a ` .
140
+
141
+ Then, we will check for errors. We first check that type tests are satisfied by
142
+ calling [ ` check_type_tests ` ] . This checks constraints like ` T: 'a ` . Second, we
143
+ check that universal regions are not "too big". This is done by calling
144
+ [ ` check_universal_regions ` ] . This checks that for each region ` 'a ` if ` 'a `
145
+ contains the element ` end('b) ` , then we must already know that ` 'a: 'b ` holds
146
+ (e.g. from a where clause). If we don't already know this, that is an error...
147
+ well, almost.
148
+
149
+ [ `propagate_constraints` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints
150
+ [ `check_type_tests` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.check_type_tests
151
+ [ `check_universal_regions` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions
152
+
153
+ ## Closures
154
+
155
+ When we are checking the type tests and universal regions, we may come across a
156
+ constraint that we can't prove yet if we are in a closure body! However, the
157
+ necessary constraints may actually hold (we just don't know it yet). Thus, if
158
+ we are inside a closure, we just collect all the constraints we can't prove yet
159
+ and return them. Later, when we are borrow check the MIR node that created the
160
+ closure, we can also check that these constraints hold. At that time, if we
161
+ can't prove they hold, we report an error.
162
+
93
163
## Causal tracking
94
164
95
165
* to be written* – describe how we can extend the values of a variable
96
166
with causal tracking etc
97
167
168
+ TODO: is this what I described above or something else?
169
+
98
170
<a name =" placeholder " ></a >
99
171
100
172
## Placeholders and universes
@@ -541,3 +613,6 @@ Now constraint propagation is done, but when we check the outlives
541
613
relationships, we find that ` V2 ` includes this new element ` placeholder(1) ` ,
542
614
so we report an error.
543
615
616
+ ## Borrow Checker Errors
617
+
618
+ TODO: we should discuss how to generate errors from the results of these analyses.
0 commit comments