@@ -510,6 +510,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
510
510
)
511
511
. as_str ( ) ,
512
512
) ;
513
+ for ( var_hir_id, diagnostics_info) in need_migrations. iter ( ) {
514
+ for ( captured_hir_id, captured_name) in diagnostics_info. iter ( ) {
515
+ if let Some ( captured_hir_id) = captured_hir_id {
516
+ let cause_span = self . tcx . hir ( ) . span ( * captured_hir_id) ;
517
+ diagnostics_builder. span_label ( cause_span, format ! ( "in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`" ,
518
+ self . tcx. hir( ) . name( * var_hir_id) ,
519
+ captured_name,
520
+ ) ) ;
521
+ }
522
+ }
523
+ }
513
524
diagnostics_builder. note ( "for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>" ) ;
514
525
let closure_body_span = self . tcx . hir ( ) . span ( body_id. hir_id ) ;
515
526
let ( sugg, app) =
@@ -579,13 +590,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
579
590
var_hir_id : hir:: HirId ,
580
591
check_trait : Option < DefId > ,
581
592
closure_clause : hir:: CaptureBy ,
582
- ) -> bool {
593
+ ) -> Option < ( Option < hir :: HirId > , String ) > {
583
594
let root_var_min_capture_list = if let Some ( root_var_min_capture_list) =
584
595
min_captures. and_then ( |m| m. get ( & var_hir_id) )
585
596
{
586
597
root_var_min_capture_list
587
598
} else {
588
- return false ;
599
+ return None ;
589
600
} ;
590
601
591
602
let ty = self . infcx . resolve_vars_if_possible ( self . node_ty ( var_hir_id) ) ;
@@ -639,10 +650,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639
650
. unwrap_or ( false ) ;
640
651
641
652
if !obligation_holds_for_capture && obligation_should_hold {
642
- return true ;
653
+ return Some ( ( capture . info . path_expr_id , capture . to_string ( self . tcx ) ) ) ;
643
654
}
644
655
}
645
- false
656
+ None
646
657
}
647
658
648
659
/// Figures out the list of root variables (and their types) that aren't completely
@@ -660,68 +671,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
660
671
min_captures : Option < & ty:: RootVariableMinCaptureList < ' tcx > > ,
661
672
var_hir_id : hir:: HirId ,
662
673
closure_clause : hir:: CaptureBy ,
663
- ) -> Option < FxHashSet < & str > > {
674
+ ) -> Option < ( FxHashSet < & str > , FxHashSet < ( Option < hir :: HirId > , String ) > ) > {
664
675
let tcx = self . infcx . tcx ;
665
676
666
677
// Check whether catpured fields also implement the trait
667
678
let mut auto_trait_reasons = FxHashSet :: default ( ) ;
679
+ let mut diagnostics_info = FxHashSet :: default ( ) ;
668
680
669
- if self . need_2229_migrations_for_trait (
681
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
670
682
min_captures,
671
683
var_hir_id,
672
684
tcx. lang_items ( ) . clone_trait ( ) ,
673
685
closure_clause,
674
686
) {
675
687
auto_trait_reasons. insert ( "`Clone`" ) ;
688
+ diagnostics_info. insert ( info) ;
676
689
}
677
690
678
- if self . need_2229_migrations_for_trait (
691
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
679
692
min_captures,
680
693
var_hir_id,
681
694
tcx. lang_items ( ) . sync_trait ( ) ,
682
695
closure_clause,
683
696
) {
684
697
auto_trait_reasons. insert ( "`Sync`" ) ;
698
+ diagnostics_info. insert ( info) ;
685
699
}
686
700
687
- if self . need_2229_migrations_for_trait (
701
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
688
702
min_captures,
689
703
var_hir_id,
690
704
tcx. get_diagnostic_item ( sym:: send_trait) ,
691
705
closure_clause,
692
706
) {
693
707
auto_trait_reasons. insert ( "`Send`" ) ;
708
+ diagnostics_info. insert ( info) ;
694
709
}
695
710
696
- if self . need_2229_migrations_for_trait (
711
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
697
712
min_captures,
698
713
var_hir_id,
699
714
tcx. lang_items ( ) . unpin_trait ( ) ,
700
715
closure_clause,
701
716
) {
702
717
auto_trait_reasons. insert ( "`Unpin`" ) ;
718
+ diagnostics_info. insert ( info) ;
703
719
}
704
720
705
- if self . need_2229_migrations_for_trait (
721
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
706
722
min_captures,
707
723
var_hir_id,
708
724
tcx. get_diagnostic_item ( sym:: unwind_safe_trait) ,
709
725
closure_clause,
710
726
) {
711
727
auto_trait_reasons. insert ( "`UnwindSafe`" ) ;
728
+ diagnostics_info. insert ( info) ;
712
729
}
713
730
714
- if self . need_2229_migrations_for_trait (
731
+ if let Some ( info ) = self . need_2229_migrations_for_trait (
715
732
min_captures,
716
733
var_hir_id,
717
734
tcx. get_diagnostic_item ( sym:: ref_unwind_safe_trait) ,
718
735
closure_clause,
719
736
) {
720
737
auto_trait_reasons. insert ( "`RefUnwindSafe`" ) ;
738
+ diagnostics_info. insert ( info) ;
721
739
}
722
740
723
741
if auto_trait_reasons. len ( ) > 0 {
724
- return Some ( auto_trait_reasons) ;
742
+ return Some ( ( auto_trait_reasons, diagnostics_info ) ) ;
725
743
}
726
744
727
745
return None ;
@@ -746,11 +764,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
746
764
min_captures : Option < & ty:: RootVariableMinCaptureList < ' tcx > > ,
747
765
closure_clause : hir:: CaptureBy ,
748
766
var_hir_id : hir:: HirId ,
749
- ) -> bool {
767
+ ) -> Option < FxHashSet < ( Option < hir :: HirId > , String ) > > {
750
768
let ty = self . infcx . resolve_vars_if_possible ( self . node_ty ( var_hir_id) ) ;
751
769
752
770
if !ty. has_significant_drop ( self . tcx , self . tcx . param_env ( closure_def_id. expect_local ( ) ) ) {
753
- return false ;
771
+ return None ;
754
772
}
755
773
756
774
let root_var_min_capture_list = if let Some ( root_var_min_capture_list) =
@@ -763,21 +781,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
763
781
764
782
match closure_clause {
765
783
// Only migrate if closure is a move closure
766
- hir:: CaptureBy :: Value => return true ,
784
+ hir:: CaptureBy :: Value => return Some ( FxHashSet :: default ( ) ) ,
767
785
hir:: CaptureBy :: Ref => { }
768
786
}
769
787
770
- return false ;
788
+ return None ;
771
789
} ;
772
790
773
- let projections_list = root_var_min_capture_list
774
- . iter ( )
775
- . filter_map ( |captured_place| match captured_place. info . capture_kind {
791
+ let mut projections_list = Vec :: new ( ) ;
792
+ let mut diagnostics_info = FxHashSet :: default ( ) ;
793
+
794
+ for captured_place in root_var_min_capture_list. iter ( ) {
795
+ match captured_place. info . capture_kind {
776
796
// Only care about captures that are moved into the closure
777
- ty:: UpvarCapture :: ByValue ( ..) => Some ( captured_place. place . projections . as_slice ( ) ) ,
778
- ty:: UpvarCapture :: ByRef ( ..) => None ,
779
- } )
780
- . collect :: < Vec < _ > > ( ) ;
797
+ ty:: UpvarCapture :: ByValue ( ..) => {
798
+ projections_list. push ( captured_place. place . projections . as_slice ( ) ) ;
799
+ diagnostics_info. insert ( (
800
+ captured_place. info . path_expr_id ,
801
+ captured_place. to_string ( self . tcx ) ,
802
+ ) ) ;
803
+ }
804
+ ty:: UpvarCapture :: ByRef ( ..) => { }
805
+ }
806
+ }
781
807
782
808
let is_moved = !projections_list. is_empty ( ) ;
783
809
@@ -793,10 +819,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
793
819
projections_list,
794
820
)
795
821
{
796
- return true ;
822
+ return Some ( diagnostics_info ) ;
797
823
}
798
824
799
- return false ;
825
+ return None ;
800
826
}
801
827
802
828
/// Figures out the list of root variables (and their types) that aren't completely
@@ -820,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
820
846
closure_span : Span ,
821
847
closure_clause : hir:: CaptureBy ,
822
848
min_captures : Option < & ty:: RootVariableMinCaptureList < ' tcx > > ,
823
- ) -> ( Vec < hir:: HirId > , String ) {
849
+ ) -> ( Vec < ( hir:: HirId , FxHashSet < ( Option < hir :: HirId > , String ) > ) > , String ) {
824
850
let upvars = if let Some ( upvars) = self . tcx . upvars_mentioned ( closure_def_id) {
825
851
upvars
826
852
} else {
@@ -834,14 +860,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
834
860
// Perform auto-trait analysis
835
861
for ( & var_hir_id, _) in upvars. iter ( ) {
836
862
let mut need_migration = false ;
837
- if let Some ( trait_migration_cause) =
863
+ let mut responsible_captured_hir_ids = FxHashSet :: default ( ) ;
864
+
865
+ if let Some ( ( trait_migration_cause, diagnostics_info) ) =
838
866
self . compute_2229_migrations_for_trait ( min_captures, var_hir_id, closure_clause)
839
867
{
840
868
need_migration = true ;
841
869
auto_trait_reasons. extend ( trait_migration_cause) ;
870
+ responsible_captured_hir_ids. extend ( diagnostics_info) ;
842
871
}
843
872
844
- if self . compute_2229_migrations_for_drop (
873
+ if let Some ( diagnostics_info ) = self . compute_2229_migrations_for_drop (
845
874
closure_def_id,
846
875
closure_span,
847
876
min_captures,
@@ -850,10 +879,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
850
879
) {
851
880
need_migration = true ;
852
881
drop_reorder_reason = true ;
882
+ responsible_captured_hir_ids. extend ( diagnostics_info) ;
853
883
}
854
884
855
885
if need_migration {
856
- need_migrations. push ( var_hir_id) ;
886
+ need_migrations. push ( ( var_hir_id, responsible_captured_hir_ids ) ) ;
857
887
}
858
888
}
859
889
@@ -1877,10 +1907,10 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
1877
1907
/// - s2: Comma separated names of the variables being migrated.
1878
1908
fn migration_suggestion_for_2229 (
1879
1909
tcx : TyCtxt < ' _ > ,
1880
- need_migrations : & Vec < hir:: HirId > ,
1910
+ need_migrations : & Vec < ( hir:: HirId , FxHashSet < ( Option < hir :: HirId > , String ) > ) > ,
1881
1911
) -> ( String , String ) {
1882
1912
let need_migrations_variables =
1883
- need_migrations. iter ( ) . map ( |v | var_name ( tcx, * v) ) . collect :: < Vec < _ > > ( ) ;
1913
+ need_migrations. iter ( ) . map ( |( v , _ ) | var_name ( tcx, * v) ) . collect :: < Vec < _ > > ( ) ;
1884
1914
1885
1915
let migration_ref_concat =
1886
1916
need_migrations_variables. iter ( ) . map ( |v| format ! ( "&{}" , v) ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
0 commit comments