@@ -162,34 +162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162
162
163
163
let closure_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
164
164
if should_do_migration_analysis ( self . tcx , closure_hir_id) {
165
- let need_migrations = self . compute_2229_migrations_first_pass (
166
- closure_def_id,
167
- span,
168
- capture_clause,
169
- body,
170
- self . typeck_results . borrow ( ) . closure_min_captures . get ( & closure_def_id) ,
171
- ) ;
172
-
173
- if !need_migrations. is_empty ( ) {
174
- let need_migrations_hir_id =
175
- need_migrations. iter ( ) . map ( |m| m. 0 ) . collect :: < Vec < _ > > ( ) ;
176
-
177
- let migrations_text =
178
- migration_suggestion_for_2229 ( self . tcx , & need_migrations_hir_id) ;
179
-
180
- self . tcx . struct_span_lint_hir (
181
- lint:: builtin:: DISJOINT_CAPTURE_DROP_REORDER ,
182
- closure_hir_id,
183
- span,
184
- |lint| {
185
- let mut diagnostics_builder = lint. build (
186
- "Drop order affected for closure because of `capture_disjoint_fields`" ,
187
- ) ;
188
- diagnostics_builder. note ( & migrations_text) ;
189
- diagnostics_builder. emit ( ) ;
190
- } ,
191
- ) ;
192
- }
165
+ self . perform_2229_migration_anaysis ( closure_def_id, capture_clause, span, body) ;
193
166
}
194
167
195
168
// We now fake capture information for all variables that are mentioned within the closure
@@ -510,6 +483,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
510
483
debug ! ( "For closure={:?}, min_captures={:#?}" , closure_def_id, root_var_min_capture_list) ;
511
484
}
512
485
486
+ /// Perform the migration analysis for RFC 2229, and emit lint
487
+ /// `disjoint_capture_drop_reorder` if needed.
488
+ fn perform_2229_migration_anaysis (
489
+ & self ,
490
+ closure_def_id : DefId ,
491
+ capture_clause : hir:: CaptureBy ,
492
+ span : Span ,
493
+ body : & ' tcx hir:: Body < ' tcx > ,
494
+ ) {
495
+ let need_migrations = self . compute_2229_migrations_first_pass (
496
+ closure_def_id,
497
+ span,
498
+ capture_clause,
499
+ body,
500
+ self . typeck_results . borrow ( ) . closure_min_captures . get ( & closure_def_id) ,
501
+ ) ;
502
+
503
+ if !need_migrations. is_empty ( ) {
504
+ let need_migrations_hir_id = need_migrations. iter ( ) . map ( |m| m. 0 ) . collect :: < Vec < _ > > ( ) ;
505
+
506
+ let migrations_text = migration_suggestion_for_2229 ( self . tcx , & need_migrations_hir_id) ;
507
+
508
+ let local_def_id = closure_def_id. expect_local ( ) ;
509
+ let closure_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
510
+ self . tcx . struct_span_lint_hir (
511
+ lint:: builtin:: DISJOINT_CAPTURE_DROP_REORDER ,
512
+ closure_hir_id,
513
+ span,
514
+ |lint| {
515
+ let mut diagnostics_builder = lint. build (
516
+ "Drop order affected for closure because of `capture_disjoint_fields`" ,
517
+ ) ;
518
+ diagnostics_builder. note ( & migrations_text) ;
519
+ diagnostics_builder. emit ( ) ;
520
+ } ,
521
+ ) ;
522
+ }
523
+ }
524
+
513
525
/// Figures out the list of root variables (and their types) that aren't completely
514
526
/// captured by the closure when `capture_disjoint_fields` is enabled and drop order of
515
527
/// some path starting at that root variable **might** be affected.
@@ -572,17 +584,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
572
584
573
585
let is_moved = root_var_min_capture_list
574
586
. iter ( )
575
- . find ( |capture| matches ! ( capture. info. capture_kind, ty:: UpvarCapture :: ByValue ( _) ) )
576
- . is_some ( ) ;
577
-
578
- // 1. If we capture more than one path starting at the root variabe then the root variable
579
- // isn't being captured in its entirety
580
- // 2. If we only capture one path starting at the root variable, it's still possible
581
- // that it isn't the root variable completely.
582
- if is_moved
583
- && ( ( root_var_min_capture_list. len ( ) > 1 )
584
- || ( root_var_min_capture_list[ 0 ] . place . projections . len ( ) > 0 ) )
585
- {
587
+ . any ( |capture| matches ! ( capture. info. capture_kind, ty:: UpvarCapture :: ByValue ( _) ) ) ;
588
+
589
+ let is_not_completely_captured =
590
+ root_var_min_capture_list. iter ( ) . any ( |capture| capture. place . projections . len ( ) > 0 ) ;
591
+
592
+ if is_moved && is_not_completely_captured {
586
593
need_migrations. push ( ( var_hir_id, ty) ) ;
587
594
}
588
595
}
0 commit comments