Skip to content

Commit 81053b9

Browse files
committedJul 11, 2021
Auto merge of #86995 - sexxi-goose:rewrite, r=nikomatsakis
2229: Rewrite/Refactor Closure Capture Analaysis While handling all the differnet edge cases the code for the captur analysis got pretty compicated. Looking at the overall picture of the edge cases the rules can still be layed out simply. Alogithm: https://hackmd.io/D3I_gwvuT-SPnJ22tgJumw r? `@nikomatsakis` Closes rust-lang/project-rfc-2229#52 Implementation part of rust-lang/project-rfc-2229#53
2 parents 4581c4e + 5055569 commit 81053b9

File tree

7 files changed

+302
-224
lines changed

7 files changed

+302
-224
lines changed
 

‎compiler/rustc_typeck/src/check/upvar.rs

Lines changed: 160 additions & 168 deletions
Large diffs are not rendered by default.

‎src/test/ui/closures/2229_closure_analysis/by_value.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ fn big_box() {
2222
//~^ First Pass analysis includes:
2323
//~| Min Capture analysis includes:
2424
let p = t.0.0;
25-
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
26-
//~| NOTE: Capturing t[(0, 0)] -> ByValue
25+
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
2726
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
2827
println!("{} {:?}", t.1, p);
2928
//~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow

‎src/test/ui/closures/2229_closure_analysis/by_value.stderr

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,13 @@ LL | |
1919
LL | | };
2020
| |_____^
2121
|
22-
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
23-
--> $DIR/by_value.rs:24:17
24-
|
25-
LL | let p = t.0.0;
26-
| ^^^^^
27-
note: Capturing t[(0, 0)] -> ByValue
22+
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
2823
--> $DIR/by_value.rs:24:17
2924
|
3025
LL | let p = t.0.0;
3126
| ^^^^^
3227
note: Capturing t[(1, 0)] -> ImmBorrow
33-
--> $DIR/by_value.rs:28:29
28+
--> $DIR/by_value.rs:27:29
3429
|
3530
LL | println!("{} {:?}", t.1, p);
3631
| ^^^
@@ -53,7 +48,7 @@ note: Min Capture t[(0, 0)] -> ByValue
5348
LL | let p = t.0.0;
5449
| ^^^^^
5550
note: Min Capture t[(1, 0)] -> ImmBorrow
56-
--> $DIR/by_value.rs:28:29
51+
--> $DIR/by_value.rs:27:29
5752
|
5853
LL | println!("{} {:?}", t.1, p);
5954
| ^^^

‎src/test/ui/closures/2229_closure_analysis/move_closure.rs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn simple_move_closure() {
1616
//~^ ERROR: First Pass analysis includes:
1717
//~| ERROR: Min Capture analysis includes:
1818
t.0.0 = "new S".into();
19-
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue
19+
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
2020
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
2121
};
2222
c();
@@ -78,7 +78,7 @@ fn struct_contains_ref_to_another_struct_2() {
7878
//~^ ERROR: First Pass analysis includes:
7979
//~| ERROR: Min Capture analysis includes:
8080
let _t = t.0.0;
81-
//~^ NOTE: Capturing t[(0, 0),Deref] -> ImmBorrow
81+
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
8282
//~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
8383
};
8484

@@ -100,8 +100,7 @@ fn struct_contains_ref_to_another_struct_3() {
100100
//~^ ERROR: First Pass analysis includes:
101101
//~| ERROR: Min Capture analysis includes:
102102
let _t = t.0.0;
103-
//~^ NOTE: Capturing t[(0, 0),Deref] -> ImmBorrow
104-
//~| NOTE: Capturing t[(0, 0)] -> ByValue
103+
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
105104
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
106105
};
107106

@@ -122,8 +121,7 @@ fn truncate_box_derefs() {
122121
//~^ ERROR: First Pass analysis includes:
123122
//~| ERROR: Min Capture analysis includes:
124123
let _t = b.0;
125-
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
126-
//~| NOTE: Capturing b[] -> ByValue
124+
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
127125
//~| NOTE: Min Capture b[] -> ByValue
128126
};
129127

@@ -139,7 +137,7 @@ fn truncate_box_derefs() {
139137
//~^ ERROR: First Pass analysis includes:
140138
//~| ERROR: Min Capture analysis includes:
141139
println!("{}", b.0);
142-
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
140+
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
143141
//~| NOTE: Min Capture b[] -> ByValue
144142
};
145143

@@ -156,16 +154,54 @@ fn truncate_box_derefs() {
156154
//~^ ERROR: First Pass analysis includes:
157155
//~| ERROR: Min Capture analysis includes:
158156
println!("{}", t.1.0);
159-
//~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
157+
//~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
160158
//~| NOTE: Min Capture t[(1, 0)] -> ByValue
161159
};
162160
}
163161

162+
struct Foo { x: i32 }
163+
164+
// Ensure that even in move closures, if the data is not owned by the root variable
165+
// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
166+
fn box_mut_1() {
167+
let mut foo = Foo { x: 0 } ;
168+
169+
let p_foo = &mut foo;
170+
let box_p_foo = Box::new(p_foo);
171+
172+
let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
173+
//~^ ERROR: attributes on expressions are experimental
174+
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
175+
//~| First Pass analysis includes:
176+
//~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
177+
//~| Min Capture analysis includes:
178+
//~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
179+
}
180+
181+
// Ensure that even in move closures, if the data is not owned by the root variable
182+
// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
183+
fn box_mut_2() {
184+
let foo = Foo { x: 0 } ;
185+
186+
let mut box_foo = Box::new(foo);
187+
let p_foo = &mut box_foo;
188+
189+
let c = #[rustc_capture_analysis] move || p_foo.x += 10;
190+
//~^ ERROR: attributes on expressions are experimental
191+
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
192+
//~| First Pass analysis includes:
193+
//~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
194+
//~| Min Capture analysis includes:
195+
//~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
196+
}
197+
164198
fn main() {
165199
simple_move_closure();
166200
simple_ref();
167201
struct_contains_ref_to_another_struct_1();
168202
struct_contains_ref_to_another_struct_2();
169203
struct_contains_ref_to_another_struct_3();
170204
truncate_box_derefs();
205+
box_mut_2();
206+
box_mut_1();
171207
}

‎src/test/ui/closures/2229_closure_analysis/move_closure.stderr

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ LL | let mut c = #[rustc_capture_analysis]
4444
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
4545

4646
error[E0658]: attributes on expressions are experimental
47-
--> $DIR/move_closure.rs:118:13
47+
--> $DIR/move_closure.rs:117:13
4848
|
4949
LL | let c = #[rustc_capture_analysis]
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | let c = #[rustc_capture_analysis]
5353
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
5454

5555
error[E0658]: attributes on expressions are experimental
56-
--> $DIR/move_closure.rs:135:13
56+
--> $DIR/move_closure.rs:133:13
5757
|
5858
LL | let c = #[rustc_capture_analysis]
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,14 +62,32 @@ LL | let c = #[rustc_capture_analysis]
6262
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
6363

6464
error[E0658]: attributes on expressions are experimental
65-
--> $DIR/move_closure.rs:152:13
65+
--> $DIR/move_closure.rs:150:13
6666
|
6767
LL | let c = #[rustc_capture_analysis]
6868
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6969
|
7070
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
7171
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
7272

73+
error[E0658]: attributes on expressions are experimental
74+
--> $DIR/move_closure.rs:172:13
75+
|
76+
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
78+
|
79+
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
80+
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
81+
82+
error[E0658]: attributes on expressions are experimental
83+
--> $DIR/move_closure.rs:189:13
84+
|
85+
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
86+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
87+
|
88+
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
89+
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
90+
7391
error: First Pass analysis includes:
7492
--> $DIR/move_closure.rs:15:5
7593
|
@@ -82,7 +100,7 @@ LL | |
82100
LL | | };
83101
| |_____^
84102
|
85-
note: Capturing t[(0, 0),(0, 0)] -> ByValue
103+
note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
86104
--> $DIR/move_closure.rs:18:9
87105
|
88106
LL | t.0.0 = "new S".into();
@@ -190,7 +208,7 @@ LL | |
190208
LL | | };
191209
| |_____^
192210
|
193-
note: Capturing t[(0, 0),Deref] -> ImmBorrow
211+
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
194212
--> $DIR/move_closure.rs:80:18
195213
|
196214
LL | let _t = t.0.0;
@@ -221,17 +239,12 @@ LL | / move || {
221239
LL | |
222240
LL | |
223241
LL | | let _t = t.0.0;
224-
... |
242+
LL | |
225243
LL | |
226244
LL | | };
227245
| |_____^
228246
|
229-
note: Capturing t[(0, 0),Deref] -> ImmBorrow
230-
--> $DIR/move_closure.rs:102:18
231-
|
232-
LL | let _t = t.0.0;
233-
| ^^^^^
234-
note: Capturing t[(0, 0)] -> ByValue
247+
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
235248
--> $DIR/move_closure.rs:102:18
236249
|
237250
LL | let _t = t.0.0;
@@ -244,7 +257,7 @@ LL | / move || {
244257
LL | |
245258
LL | |
246259
LL | | let _t = t.0.0;
247-
... |
260+
LL | |
248261
LL | |
249262
LL | | };
250263
| |_____^
@@ -256,48 +269,43 @@ LL | let _t = t.0.0;
256269
| ^^^^^
257270

258271
error: First Pass analysis includes:
259-
--> $DIR/move_closure.rs:121:5
272+
--> $DIR/move_closure.rs:120:5
260273
|
261274
LL | / move || {
262275
LL | |
263276
LL | |
264277
LL | | let _t = b.0;
265-
... |
278+
LL | |
266279
LL | |
267280
LL | | };
268281
| |_____^
269282
|
270-
note: Capturing b[Deref,(0, 0)] -> ByValue
271-
--> $DIR/move_closure.rs:124:18
272-
|
273-
LL | let _t = b.0;
274-
| ^^^
275-
note: Capturing b[] -> ByValue
276-
--> $DIR/move_closure.rs:124:18
283+
note: Capturing b[Deref,(0, 0)] -> ImmBorrow
284+
--> $DIR/move_closure.rs:123:18
277285
|
278286
LL | let _t = b.0;
279287
| ^^^
280288

281289
error: Min Capture analysis includes:
282-
--> $DIR/move_closure.rs:121:5
290+
--> $DIR/move_closure.rs:120:5
283291
|
284292
LL | / move || {
285293
LL | |
286294
LL | |
287295
LL | | let _t = b.0;
288-
... |
296+
LL | |
289297
LL | |
290298
LL | | };
291299
| |_____^
292300
|
293301
note: Min Capture b[] -> ByValue
294-
--> $DIR/move_closure.rs:124:18
302+
--> $DIR/move_closure.rs:123:18
295303
|
296304
LL | let _t = b.0;
297305
| ^^^
298306

299307
error: First Pass analysis includes:
300-
--> $DIR/move_closure.rs:138:5
308+
--> $DIR/move_closure.rs:136:5
301309
|
302310
LL | / move || {
303311
LL | |
@@ -308,14 +316,14 @@ LL | |
308316
LL | | };
309317
| |_____^
310318
|
311-
note: Capturing b[Deref,(0, 0)] -> ByValue
312-
--> $DIR/move_closure.rs:141:24
319+
note: Capturing b[Deref,(0, 0)] -> ImmBorrow
320+
--> $DIR/move_closure.rs:139:24
313321
|
314322
LL | println!("{}", b.0);
315323
| ^^^
316324

317325
error: Min Capture analysis includes:
318-
--> $DIR/move_closure.rs:138:5
326+
--> $DIR/move_closure.rs:136:5
319327
|
320328
LL | / move || {
321329
LL | |
@@ -327,13 +335,13 @@ LL | | };
327335
| |_____^
328336
|
329337
note: Min Capture b[] -> ByValue
330-
--> $DIR/move_closure.rs:141:24
338+
--> $DIR/move_closure.rs:139:24
331339
|
332340
LL | println!("{}", b.0);
333341
| ^^^
334342

335343
error: First Pass analysis includes:
336-
--> $DIR/move_closure.rs:155:5
344+
--> $DIR/move_closure.rs:153:5
337345
|
338346
LL | / move || {
339347
LL | |
@@ -344,14 +352,14 @@ LL | |
344352
LL | | };
345353
| |_____^
346354
|
347-
note: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
348-
--> $DIR/move_closure.rs:158:24
355+
note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
356+
--> $DIR/move_closure.rs:156:24
349357
|
350358
LL | println!("{}", t.1.0);
351359
| ^^^^^
352360

353361
error: Min Capture analysis includes:
354-
--> $DIR/move_closure.rs:155:5
362+
--> $DIR/move_closure.rs:153:5
355363
|
356364
LL | / move || {
357365
LL | |
@@ -363,11 +371,59 @@ LL | | };
363371
| |_____^
364372
|
365373
note: Min Capture t[(1, 0)] -> ByValue
366-
--> $DIR/move_closure.rs:158:24
374+
--> $DIR/move_closure.rs:156:24
367375
|
368376
LL | println!("{}", t.1.0);
369377
| ^^^^^
370378

371-
error: aborting due to 24 previous errors
379+
error: First Pass analysis includes:
380+
--> $DIR/move_closure.rs:172:39
381+
|
382+
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
383+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
384+
|
385+
note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
386+
--> $DIR/move_closure.rs:172:47
387+
|
388+
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
389+
| ^^^^^^^^^^^
390+
391+
error: Min Capture analysis includes:
392+
--> $DIR/move_closure.rs:172:39
393+
|
394+
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
395+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
396+
|
397+
note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
398+
--> $DIR/move_closure.rs:172:47
399+
|
400+
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
401+
| ^^^^^^^^^^^
402+
403+
error: First Pass analysis includes:
404+
--> $DIR/move_closure.rs:189:39
405+
|
406+
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
407+
| ^^^^^^^^^^^^^^^^^^^^^
408+
|
409+
note: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
410+
--> $DIR/move_closure.rs:189:47
411+
|
412+
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
413+
| ^^^^^^^
414+
415+
error: Min Capture analysis includes:
416+
--> $DIR/move_closure.rs:189:39
417+
|
418+
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
419+
| ^^^^^^^^^^^^^^^^^^^^^
420+
|
421+
note: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
422+
--> $DIR/move_closure.rs:189:47
423+
|
424+
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
425+
| ^^^^^^^
426+
427+
error: aborting due to 30 previous errors
372428

373429
For more information about this error, try `rustc --explain E0658`.

‎src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
2222
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
2323
//~| ERROR: First Pass analysis includes:
2424
//~| ERROR: Min Capture analysis includes:
25-
//~| NOTE: Capturing m[Deref,(0, 0),Deref] -> ImmBorrow
25+
//~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
2626
//~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
2727
c
2828
}

‎src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ error: First Pass analysis includes:
1313
LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
1414
| ^^^^^^^^^^^^^^^
1515
|
16-
note: Capturing m[Deref,(0, 0),Deref] -> ImmBorrow
16+
note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
1717
--> $DIR/edge_case.rs:20:48
1818
|
1919
LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);

0 commit comments

Comments
 (0)
Please sign in to comment.