@@ -120,45 +120,115 @@ So how do we compute the contents of a region? This process is called _region
120
120
inference_ . The high-level idea is pretty simple, but there are some details we
121
121
need to take care of.
122
122
123
+ Here is the high-level idea: we start off each region with the MIR locations we
124
+ know must be in it from the liveness constraints. From there, we use all of the
125
+ outlives constraints computed from the type checker to _ propagate_ the
126
+ constraints: for each region ` 'a ` , if ` 'a: 'b ` , then we add all elements of
127
+ ` 'b ` to ` 'a ` , including ` end('b) ` . This all happens in
128
+ [ ` propagate_constraints ` ] .
129
+
130
+ Then, we will check for errors. We first check that type tests are satisfied by
131
+ calling [ ` check_type_tests ` ] . This checks constraints like ` T: 'a ` . Second, we
132
+ check that universal regions are not "too big". This is done by calling
133
+ [ ` check_universal_regions ` ] . This checks that for each region ` 'a ` if ` 'a `
134
+ contains the element ` end('b) ` , then we must already know that ` 'a: 'b ` holds
135
+ (e.g. from a where clause). If we don't already know this, that is an error...
136
+ well, almost. There is some special handling for closures that we will discuss
137
+ later.
138
+
139
+ ### Example
140
+
141
+ Consider the following example:
142
+
143
+ ``` rust,ignore
144
+ fn foo<'a, 'b>(x: &'a usize) -> &'b usize {
145
+ x
146
+ }
147
+ ```
148
+
149
+ Clearly, this should not compile because we don't know if ` 'a ` outlives ` 'b `
150
+ (if it doesn't then the return value could be a dangling reference).
151
+
152
+ Let's back up a bit. We need to introduce some free inference variables (as is
153
+ done in [ ` replace_regions_in_mir ` ] ). This example doesn't use the exact regions
154
+ produced, but it (hopefully) is enough to get the idea across.
155
+
156
+ ``` rust,ignore
157
+ fn foo<'a, 'b>(x: &'a /* '#1 */ usize) -> &'b /* '#3 */ usize {
158
+ x // '#2, location L1
159
+ }
160
+ ```
161
+
162
+ Some notation: ` '#1 ` , ` '#3 ` , and ` '#2 ` represent the universal regions for the
163
+ argument, return value, and the expression ` x ` , respectively. Additionally, I
164
+ will call the location of the expression ` x ` ` L1 ` .
165
+
166
+ So now we can use the liveness constraints to get the following starting points:
167
+
168
+ Region | Contents
169
+ --------|----------
170
+ '#1 |
171
+ '#2 | ` L1 `
172
+ '#3 | ` L1 `
173
+
174
+ Now we use the outlives constraints to expand each region. Specifically, we
175
+ know that ` '#2: '#3 ` ...
176
+
177
+ Region | Contents
178
+ --------|----------
179
+ '#1 | ` L1 `
180
+ '#2 | ` L1, end('#3) // add contents of '#3 and end('#3) `
181
+ '#3 | ` L1 `
182
+
183
+ ... and ` '#1: '#2 ` , so ...
184
+
185
+ Region | Contents
186
+ --------|----------
187
+ '#1 | ` L1, end('#2), end('#3) // add contents of '#2 and end('#2) `
188
+ '#2 | ` L1, end('#3) `
189
+ '#3 | ` L1 `
190
+
191
+ Now, we need to check that no regions were too big (we don't have any type
192
+ tests to check in this case). Notice that ` '#1 ` now contains ` end('#3) ` , but
193
+ we have no ` where ` clause or implied bound to say that ` 'a: 'b ` ... that's an
194
+ error!
195
+
196
+ ### Some details
197
+
123
198
The [ ` RegionInferenceContext ` ] type contains all of the information needed to
124
- do inference, including the universal regions from ` replace_regions_in_mir ` and
199
+ do inference, including the universal regions from [ ` replace_regions_in_mir ` ] and
125
200
the constraints computed for each region. It is constructed just after we
126
201
compute the liveness constraints.
127
202
128
203
Here are some of the fields of the struct:
129
204
130
- - ` constraints ` : contains all the outlives constraints.
131
- - ` liveness_constraints ` : contains all the liveness constraints.
132
- - ` universal_regions ` : contains the ` UniversalRegions ` returned by
133
- ` replace_regions_in_mir ` .
134
- - ` universal_region_relations ` : contains relations known to be true about
205
+ - [ ` constraints ` ] : contains all the outlives constraints.
206
+ - [ ` liveness_constraints ` ] : contains all the liveness constraints.
207
+ - [ ` universal_regions ` ] : contains the ` UniversalRegions ` returned by
208
+ [ ` replace_regions_in_mir ` ] .
209
+ - [ ` universal_region_relations ` ] : contains relations known to be true about
135
210
universal regions. For example, if we have a where clause that ` 'a: 'b ` , that
136
211
relation is assumed to be true while borrow checking the implementation (it
137
212
is checked at the caller), so ` universal_region_relations ` would contain `'a:
138
213
'b`.
139
- - ` type_tests ` : contains some constraints on types that we must check after
214
+ - [ ` type_tests ` ] : contains some constraints on types that we must check after
140
215
inference (e.g. ` T: 'a ` ).
141
- - ` closure_bounds_mapping ` : used for propagating region constraints from
216
+ - [ ` closure_bounds_mapping ` ] : used for propagating region constraints from
142
217
closures back out to the creater of the closure.
143
218
219
+ [ `constraints` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.constraints
220
+ [ `liveness_constraints` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints
221
+ [ `universal_regions` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.universal_regions
222
+ [ `universal_region_relations` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.universal_region_relations
223
+ [ `type_tests` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.type_tests
224
+ [ `closure_bounds_mapping` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.closure_bounds_mapping
225
+
144
226
TODO: should we discuss any of the others fields? What about the SCCs?
145
227
146
228
Ok, now that we have constructed a ` RegionInferenceContext ` , we can do
147
- inference. This is done by calling the [ ` solve ` ] method on the context.
148
-
149
- We will start off the value of each region with the liveness constraints (the
150
- places we already know must be in the region). We will then use the outlives
151
- constraints to widen each region until all constraints are met. This is done in
152
- [ ` propagate_constraints ` ] . For each region, if ` 'a: 'b ` , we add all elements of
153
- ` 'b ` to ` 'a ` .
154
-
155
- Then, we will check for errors. We first check that type tests are satisfied by
156
- calling [ ` check_type_tests ` ] . This checks constraints like ` T: 'a ` . Second, we
157
- check that universal regions are not "too big". This is done by calling
158
- [ ` check_universal_regions ` ] . This checks that for each region ` 'a ` if ` 'a `
159
- contains the element ` end('b) ` , then we must already know that ` 'a: 'b ` holds
160
- (e.g. from a where clause). If we don't already know this, that is an error...
161
- well, almost.
229
+ inference. This is done by calling the [ ` solve ` ] method on the context. This
230
+ is where we call [ ` propagate_constraints ` ] and then check the resulting type
231
+ tests and universal regions, as discussed above.
162
232
163
233
[ `propagate_constraints` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints
164
234
[ `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
@@ -174,15 +244,6 @@ and return them. Later, when we are borrow check the MIR node that created the
174
244
closure, we can also check that these constraints hold. At that time, if we
175
245
can't prove they hold, we report an error.
176
246
177
- ## Causal tracking
178
-
179
- * to be written* – describe how we can extend the values of a variable
180
- with causal tracking etc
181
-
182
- TODO: is this what I described above or something else?
183
-
184
- <a name =" placeholder " ></a >
185
-
186
247
## Placeholders and universes
187
248
188
249
(This section describes ongoing work that hasn't landed yet.)
0 commit comments