@@ -540,21 +540,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
540
540
span : Span ,
541
541
body : & ' tcx hir:: Body < ' tcx > ,
542
542
) {
543
- let need_migrations_first_pass = self . compute_2229_migrations_first_pass (
543
+ let need_migrations = self . compute_2229_migrations (
544
544
closure_def_id,
545
545
span,
546
546
capture_clause,
547
547
body,
548
548
self . typeck_results . borrow ( ) . closure_min_captures . get ( & closure_def_id) ,
549
549
) ;
550
550
551
- let need_migrations = self . compute_2229_migrations_precise_pass (
552
- closure_def_id,
553
- span,
554
- self . typeck_results . borrow ( ) . closure_min_captures . get ( & closure_def_id) ,
555
- & need_migrations_first_pass,
556
- ) ;
557
-
558
551
if !need_migrations. is_empty ( ) {
559
552
let migrations_text = migration_suggestion_for_2229 ( self . tcx , & need_migrations) ;
560
553
@@ -583,15 +576,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
583
576
/// - It would have been moved into the closure when `capture_disjoint_fields` wasn't
584
577
/// enabled, **and**
585
578
/// - It wasn't completely captured by the closure, **and**
586
- /// - The type of the root variable needs Drop.
587
- fn compute_2229_migrations_first_pass (
579
+ /// - One of the paths starting at this root variable, that is not captured needs Drop.
580
+ fn compute_2229_migrations (
588
581
& self ,
589
582
closure_def_id : DefId ,
590
583
closure_span : Span ,
591
584
closure_clause : hir:: CaptureBy ,
592
585
body : & ' tcx hir:: Body < ' tcx > ,
593
586
min_captures : Option < & ty:: RootVariableMinCaptureList < ' tcx > > ,
594
- ) -> Vec < ( hir:: HirId , Ty < ' tcx > ) > {
587
+ ) -> Vec < hir:: HirId > {
595
588
fn resolve_ty < T : TypeFoldable < ' tcx > > (
596
589
fcx : & FnCtxt < ' _ , ' tcx > ,
597
590
span : Span ,
@@ -627,64 +620,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
627
620
628
621
match closure_clause {
629
622
// Only migrate if closure is a move closure
630
- hir:: CaptureBy :: Value => need_migrations. push ( ( var_hir_id, ty ) ) ,
623
+ hir:: CaptureBy :: Value => need_migrations. push ( var_hir_id) ,
631
624
632
625
hir:: CaptureBy :: Ref => { }
633
626
}
634
627
635
628
continue ;
636
629
} ;
637
630
638
- let is_moved = root_var_min_capture_list
631
+ let projections_list = root_var_min_capture_list
639
632
. iter ( )
640
- . any ( |capture| matches ! ( capture. info. capture_kind, ty:: UpvarCapture :: ByValue ( _) ) ) ;
641
-
642
- let is_not_completely_captured =
643
- root_var_min_capture_list. iter ( ) . any ( |capture| capture. place . projections . len ( ) > 0 ) ;
644
-
645
- if is_moved && is_not_completely_captured {
646
- need_migrations. push ( ( var_hir_id, ty) ) ;
647
- }
648
- }
649
-
650
- need_migrations
651
- }
652
-
653
- fn compute_2229_migrations_precise_pass (
654
- & self ,
655
- closure_def_id : DefId ,
656
- closure_span : Span ,
657
- min_captures : Option < & ty:: RootVariableMinCaptureList < ' tcx > > ,
658
- need_migrations : & [ ( hir:: HirId , Ty < ' tcx > ) ] ,
659
- ) -> Vec < hir:: HirId > {
660
- // Need migrations -- second pass
661
- let mut need_migrations_2 = Vec :: new ( ) ;
662
-
663
- for ( hir_id, ty) in need_migrations {
664
- let projections_list = min_captures
665
- . and_then ( |m| m. get ( hir_id) )
666
- . into_iter ( )
667
- . flatten ( )
668
633
. filter_map ( |captured_place| match captured_place. info . capture_kind {
669
634
// Only care about captures that are moved into the closure
670
635
ty:: UpvarCapture :: ByValue ( ..) => {
671
636
Some ( captured_place. place . projections . as_slice ( ) )
672
637
}
673
638
ty:: UpvarCapture :: ByRef ( ..) => None ,
674
639
} )
675
- . collect ( ) ;
640
+ . collect :: < Vec < _ > > ( ) ;
676
641
677
- if self . has_significant_drop_outside_of_captures (
678
- closure_def_id,
679
- closure_span,
680
- ty,
681
- projections_list,
682
- ) {
683
- need_migrations_2. push ( * hir_id) ;
642
+ let is_moved = !projections_list. is_empty ( ) ;
643
+
644
+ let is_not_completely_captured =
645
+ root_var_min_capture_list. iter ( ) . any ( |capture| capture. place . projections . len ( ) > 0 ) ;
646
+
647
+ if is_moved
648
+ && is_not_completely_captured
649
+ && self . has_significant_drop_outside_of_captures (
650
+ closure_def_id,
651
+ closure_span,
652
+ ty,
653
+ projections_list,
654
+ )
655
+ {
656
+ need_migrations. push ( var_hir_id) ;
684
657
}
685
658
}
686
659
687
- need_migrations_2
660
+ need_migrations
688
661
}
689
662
690
663
/// This is a helper function to `compute_2229_migrations_precise_pass`. Provided the type
@@ -822,21 +795,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
822
795
823
796
assert ! ( !is_completely_captured || ( captured_projs. len( ) == 1 ) ) ;
824
797
825
- if is_drop_defined_for_ty {
826
- // If drop is implemented for this type then we need it to be fully captured, or
827
- // it will require migration.
828
- return !is_completely_captured;
829
- }
830
-
831
798
if is_completely_captured {
832
799
// The place is captured entirely, so doesn't matter if needs dtor, it will be drop
833
800
// when the closure is dropped.
834
801
return false ;
835
802
}
836
803
837
- match base_path_ty. kind ( ) {
838
- _ if captured_projs. is_empty ( ) => needs_drop ( base_path_ty) ,
804
+ if is_drop_defined_for_ty {
805
+ // If drop is implemented for this type then we need it to be fully captured,
806
+ // which we know it is not because of the previous check. Therefore we need to
807
+ // do migrate.
808
+ return true ;
809
+ }
810
+
811
+ if captured_projs. is_empty ( ) {
812
+ return needs_drop ( base_path_ty) ;
813
+ }
839
814
815
+ match base_path_ty. kind ( ) {
840
816
// Observations:
841
817
// - `captured_projs` is not empty. Therefore we can call
842
818
// `captured_projs.first().unwrap()` safely.
0 commit comments