@@ -55,6 +55,11 @@ enum PlaceAncestryRelation {
5555 Divergent ,
5656}
5757
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+
5863impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
5964 pub fn closure_analyze ( & self , body : & ' tcx hir:: Body < ' tcx > ) {
6065 InferBorrowKindVisitor { fcx : self } . visit_body ( body) ;
@@ -124,28 +129,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124129
125130 let local_def_id = closure_def_id. expect_local ( ) ;
126131
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 {
139- capture_kind_expr_id : None ,
140- path_expr_id : None ,
141- capture_kind,
142- } ;
143-
144- capture_information. insert ( place, info) ;
145- }
146- }
147- }
148-
149132 let body_owner_def_id = self . tcx . hir ( ) . body_owner_def_id ( body. id ( ) ) ;
150133 assert_eq ! ( body_owner_def_id. to_def_id( ) , closure_def_id) ;
151134 let mut delegate = InferBorrowKind {
@@ -155,7 +138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
155138 capture_clause,
156139 current_closure_kind : ty:: ClosureKind :: LATTICE_BOTTOM ,
157140 current_origin : None ,
158- capture_information,
141+ capture_information : Default :: default ( ) ,
159142 } ;
160143 euv:: ExprUseVisitor :: new (
161144 & mut delegate,
@@ -172,6 +155,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172155 ) ;
173156 self . log_capture_analysis_first_pass ( closure_def_id, & delegate. capture_information , span) ;
174157
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 {
174+ capture_kind_expr_id : None ,
175+ path_expr_id : None ,
176+ capture_kind,
177+ } ;
178+
179+ capture_information. insert ( place, fake_info) ;
180+ }
181+ }
182+
183+ // This will update the min captures based on this new fake information.
184+ self . compute_min_captures ( closure_def_id, capture_information) ;
185+ }
186+
175187 if let Some ( closure_substs) = infer_kind {
176188 // Unify the (as yet unbound) type variable in the closure
177189 // substs with the kind we inferred.
@@ -198,7 +210,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
198210 }
199211 }
200212
201- self . compute_min_captures ( closure_def_id, delegate) ;
202213 self . log_closure_min_capture_info ( closure_def_id, span) ;
203214
204215 self . min_captures_to_closure_captures_bridge ( closure_def_id) ;
@@ -345,6 +356,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
345356 /// Places (and corresponding capture kind) that we need to keep track of to support all
346357 /// the required captured paths.
347358 ///
359+ ///
360+ /// Note: If this function is called multiple times for the same closure, it will update
361+ /// the existing min_capture map that is stored in TypeckResults.
362+ ///
348363 /// Eg:
349364 /// ```rust,no_run
350365 /// struct Point { x: i32, y: i32 }
@@ -409,11 +424,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409424 fn compute_min_captures (
410425 & self ,
411426 closure_def_id : DefId ,
412- inferred_info : InferBorrowKind < ' _ , ' tcx > ,
427+ capture_information : InferredCaptureInformation < ' tcx > ,
413428 ) {
414- let mut root_var_min_capture_list: ty:: RootVariableMinCaptureList < ' _ > = Default :: default ( ) ;
429+ if capture_information. is_empty ( ) {
430+ return ;
431+ }
415432
416- for ( place, capture_info) in inferred_info. capture_information . into_iter ( ) {
433+ let mut typeck_results = self . typeck_results . borrow_mut ( ) ;
434+
435+ let root_var_min_capture_list =
436+ typeck_results. closure_min_captures . entry ( closure_def_id) . or_insert ( Default :: default ( ) ) ;
437+
438+ for ( place, capture_info) in capture_information. into_iter ( ) {
417439 let var_hir_id = match place. base {
418440 PlaceBase :: Upvar ( upvar_id) => upvar_id. var_path . hir_id ,
419441 base => bug ! ( "Expected upvar, found={:?}" , base) ,
@@ -501,13 +523,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
501523 }
502524
503525 debug ! ( "For closure={:?}, min_captures={:#?}" , closure_def_id, root_var_min_capture_list) ;
504-
505- if !root_var_min_capture_list. is_empty ( ) {
506- self . typeck_results
507- . borrow_mut ( )
508- . closure_min_captures
509- . insert ( closure_def_id, root_var_min_capture_list) ;
510- }
511526 }
512527
513528 fn init_capture_kind (
@@ -661,9 +676,11 @@ struct InferBorrowKind<'a, 'tcx> {
661676 ///
662677 /// For closure `fix_s`, (at a high level) the map contains
663678 ///
679+ /// ```
664680 /// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
665681 /// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
666- capture_information : FxIndexMap < Place < ' tcx > , ty:: CaptureInfo < ' tcx > > ,
682+ /// ```
683+ capture_information : InferredCaptureInformation < ' tcx > ,
667684}
668685
669686impl < ' a , ' tcx > InferBorrowKind < ' a , ' tcx > {
0 commit comments