@@ -55,6 +55,11 @@ enum PlaceAncestryRelation {
55
55
Divergent ,
56
56
}
57
57
58
+ /// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
59
+ /// during capture analysis. Information in this map feeds into the minimum capture
60
+ /// analysis pass.
61
+ type InferredCaptureInformation < ' tcx > = FxIndexMap < Place < ' tcx > , ty:: CaptureInfo < ' tcx > > ;
62
+
58
63
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
59
64
pub fn closure_analyze ( & self , body : & ' tcx hir:: Body < ' tcx > ) {
60
65
InferBorrowKindVisitor { fcx : self } . visit_body ( body) ;
@@ -124,24 +129,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124
129
125
130
let local_def_id = closure_def_id. expect_local ( ) ;
126
131
127
- let mut capture_information: FxIndexMap < Place < ' tcx > , ty:: CaptureInfo < ' tcx > > =
128
- Default :: default ( ) ;
129
- if !self . tcx . features ( ) . capture_disjoint_fields {
130
- if let Some ( upvars) = self . tcx . upvars_mentioned ( closure_def_id) {
131
- for ( & var_hir_id, _) in upvars. iter ( ) {
132
- let place = self . place_for_root_variable ( local_def_id, var_hir_id) ;
133
-
134
- debug ! ( "seed place {:?}" , place) ;
135
-
136
- let upvar_id = ty:: UpvarId :: new ( var_hir_id, local_def_id) ;
137
- let capture_kind = self . init_capture_kind ( capture_clause, upvar_id, span) ;
138
- let info = ty:: CaptureInfo { expr_id : None , capture_kind } ;
139
-
140
- capture_information. insert ( place, info) ;
141
- }
142
- }
143
- }
144
-
145
132
let body_owner_def_id = self . tcx . hir ( ) . body_owner_def_id ( body. id ( ) ) ;
146
133
assert_eq ! ( body_owner_def_id. to_def_id( ) , closure_def_id) ;
147
134
let mut delegate = InferBorrowKind {
@@ -151,7 +138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
151
138
capture_clause,
152
139
current_closure_kind : ty:: ClosureKind :: LATTICE_BOTTOM ,
153
140
current_origin : None ,
154
- capture_information,
141
+ capture_information : Default :: default ( ) ,
155
142
} ;
156
143
euv:: ExprUseVisitor :: new (
157
144
& mut delegate,
@@ -168,6 +155,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
168
155
) ;
169
156
self . log_capture_analysis_first_pass ( closure_def_id, & delegate. capture_information , span) ;
170
157
158
+ self . compute_min_captures ( closure_def_id, delegate. capture_information ) ;
159
+
160
+ // We now fake capture information for all variables that are mentioned within the closure
161
+ // We do this after handling migrations so that min_captures computes before
162
+ if !self . tcx . features ( ) . capture_disjoint_fields {
163
+ let mut capture_information: InferredCaptureInformation < ' tcx > = Default :: default ( ) ;
164
+
165
+ if let Some ( upvars) = self . tcx . upvars_mentioned ( closure_def_id) {
166
+ for var_hir_id in upvars. keys ( ) {
167
+ let place = self . place_for_root_variable ( local_def_id, * var_hir_id) ;
168
+
169
+ debug ! ( "seed place {:?}" , place) ;
170
+
171
+ let upvar_id = ty:: UpvarId :: new ( * var_hir_id, local_def_id) ;
172
+ let capture_kind = self . init_capture_kind ( capture_clause, upvar_id, span) ;
173
+ let fake_info = ty:: CaptureInfo { expr_id : None , capture_kind } ;
174
+
175
+ capture_information. insert ( place, fake_info) ;
176
+ }
177
+ }
178
+
179
+ // This will update the min captures based on this new fake information.
180
+ self . compute_min_captures ( closure_def_id, capture_information) ;
181
+ }
182
+
171
183
if let Some ( closure_substs) = infer_kind {
172
184
// Unify the (as yet unbound) type variable in the closure
173
185
// substs with the kind we inferred.
@@ -184,7 +196,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
184
196
}
185
197
}
186
198
187
- self . compute_min_captures ( closure_def_id, delegate) ;
188
199
self . log_closure_min_capture_info ( closure_def_id, span) ;
189
200
190
201
self . min_captures_to_closure_captures_bridge ( closure_def_id) ;
@@ -328,6 +339,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
328
339
/// Places (and corresponding capture kind) that we need to keep track of to support all
329
340
/// the required captured paths.
330
341
///
342
+ ///
343
+ /// Note: If this function is called multiple times for the same closure, it will update
344
+ /// the existing min_capture map that is stored in TypeckResults.
345
+ ///
331
346
/// Eg:
332
347
/// ```rust,no_run
333
348
/// struct Point { x: i32, y: i32 }
@@ -368,11 +383,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
368
383
fn compute_min_captures (
369
384
& self ,
370
385
closure_def_id : DefId ,
371
- inferred_info : InferBorrowKind < ' _ , ' tcx > ,
386
+ capture_information : InferredCaptureInformation < ' tcx > ,
372
387
) {
373
- let mut root_var_min_capture_list: ty:: RootVariableMinCaptureList < ' _ > = Default :: default ( ) ;
388
+ if capture_information. is_empty ( ) {
389
+ return ;
390
+ }
391
+
392
+ let mut typeck_results = self . typeck_results . borrow_mut ( ) ;
393
+
394
+ let root_var_min_capture_list =
395
+ typeck_results. closure_min_captures . entry ( closure_def_id) . or_insert ( Default :: default ( ) ) ;
374
396
375
- for ( place, capture_info) in inferred_info . capture_information . into_iter ( ) {
397
+ for ( place, capture_info) in capture_information. into_iter ( ) {
376
398
let var_hir_id = match place. base {
377
399
PlaceBase :: Upvar ( upvar_id) => upvar_id. var_path . hir_id ,
378
400
base => bug ! ( "Expected upvar, found={:?}" , base) ,
@@ -451,13 +473,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
451
473
}
452
474
453
475
debug ! ( "For closure={:?}, min_captures={:#?}" , closure_def_id, root_var_min_capture_list) ;
454
-
455
- if !root_var_min_capture_list. is_empty ( ) {
456
- self . typeck_results
457
- . borrow_mut ( )
458
- . closure_min_captures
459
- . insert ( closure_def_id, root_var_min_capture_list) ;
460
- }
461
476
}
462
477
463
478
fn init_capture_kind (
@@ -587,9 +602,11 @@ struct InferBorrowKind<'a, 'tcx> {
587
602
///
588
603
/// For closure `fix_s`, (at a high level) the map contains
589
604
///
605
+ /// ```
590
606
/// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
591
607
/// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
592
- capture_information : FxIndexMap < Place < ' tcx > , ty:: CaptureInfo < ' tcx > > ,
608
+ /// ```
609
+ capture_information : InferredCaptureInformation < ' tcx > ,
593
610
}
594
611
595
612
impl < ' a , ' tcx > InferBorrowKind < ' a , ' tcx > {
0 commit comments