@@ -67,10 +67,12 @@ use rustc_middle::mir::*;
67
67
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
68
68
use rustc_middle:: ty:: { GeneratorSubsts , SubstsRef } ;
69
69
use rustc_mir_dataflow:: impls:: {
70
- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
70
+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
71
+ MaybeStorageLive ,
71
72
} ;
73
+ use rustc_mir_dataflow:: move_paths:: MoveData ;
72
74
use rustc_mir_dataflow:: storage:: always_storage_live_locals;
73
- use rustc_mir_dataflow:: { self , Analysis } ;
75
+ use rustc_mir_dataflow:: { self , Analysis , MoveDataParamEnv } ;
74
76
use rustc_span:: def_id:: { DefId , LocalDefId } ;
75
77
use rustc_span:: symbol:: sym;
76
78
use rustc_span:: Span ;
@@ -561,6 +563,10 @@ struct LivenessInfo {
561
563
/// Which locals are live across any suspension point.
562
564
saved_locals : GeneratorSavedLocals ,
563
565
566
+ /// Which locals are live *and* initialized across any suspension point.
567
+ /// A local that is live but is not initialized does not need to accounted in auto trait checking.
568
+ init_locals : BitSet < Local > ,
569
+
564
570
/// The set of saved locals live at each suspension point.
565
571
live_locals_at_suspension_points : Vec < BitSet < GeneratorSavedLocal > > ,
566
572
@@ -615,10 +621,21 @@ fn locals_live_across_suspend_points<'tcx>(
615
621
. iterate_to_fixpoint ( )
616
622
. into_results_cursor ( body_ref) ;
617
623
624
+ let param_env = tcx. param_env ( body. source . def_id ( ) ) ;
625
+ let ( _, move_data) = MoveData :: gather_moves ( body, tcx, param_env) . unwrap ( ) ;
626
+ let mdpe = MoveDataParamEnv { move_data, param_env } ;
627
+
628
+ // Calculate the set of locals which are initialized
629
+ let mut inits = MaybeInitializedPlaces :: new ( tcx, body, & mdpe)
630
+ . into_engine ( tcx, body)
631
+ . iterate_to_fixpoint ( )
632
+ . into_results_cursor ( body_ref) ;
633
+
618
634
let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
619
635
let mut live_locals_at_suspension_points = Vec :: new ( ) ;
620
636
let mut source_info_at_suspension_points = Vec :: new ( ) ;
621
637
let mut live_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
638
+ let mut init_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
622
639
623
640
for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
624
641
if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -657,12 +674,24 @@ fn locals_live_across_suspend_points<'tcx>(
657
674
// The generator argument is ignored.
658
675
live_locals. remove ( SELF_ARG ) ;
659
676
660
- debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
677
+ inits. seek_to_block_end ( block) ;
678
+ let mut init_locals: BitSet < _ > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
679
+ for move_path_index in inits. get ( ) . iter ( ) {
680
+ if let Some ( local) = mdpe. move_data . move_paths [ move_path_index] . place . as_local ( ) {
681
+ init_locals. insert ( local) ;
682
+ }
683
+ }
684
+ init_locals. intersect ( & live_locals) ;
685
+
686
+ debug ! (
687
+ "loc = {:?}, live_locals = {:?}, init_locals = {:?}" ,
688
+ loc, live_locals, init_locals
689
+ ) ;
661
690
662
691
// Add the locals live at this suspension point to the set of locals which live across
663
692
// any suspension points
664
693
live_locals_at_any_suspension_point. union ( & live_locals) ;
665
-
694
+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
666
695
live_locals_at_suspension_points. push ( live_locals) ;
667
696
source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
668
697
}
@@ -687,6 +716,7 @@ fn locals_live_across_suspend_points<'tcx>(
687
716
688
717
LivenessInfo {
689
718
saved_locals,
719
+ init_locals : init_locals_at_any_suspension_point,
690
720
live_locals_at_suspension_points,
691
721
source_info_at_suspension_points,
692
722
storage_conflicts,
@@ -909,6 +939,7 @@ fn compute_layout<'tcx>(
909
939
) {
910
940
let LivenessInfo {
911
941
saved_locals,
942
+ init_locals,
912
943
live_locals_at_suspension_points,
913
944
source_info_at_suspension_points,
914
945
storage_conflicts,
@@ -926,20 +957,26 @@ fn compute_layout<'tcx>(
926
957
debug ! ( ?decl) ;
927
958
928
959
let ignore_for_traits = if tcx. sess . opts . unstable_opts . drop_tracking_mir {
929
- // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
930
- // the information. This is alright, since `ignore_for_traits` is only relevant when
931
- // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
932
- // default.
933
- match decl. local_info {
934
- // Do not include raw pointers created from accessing `static` items, as those could
935
- // well be re-created by another access to the same static.
936
- ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
937
- !is_thread_local
960
+ if !init_locals. contains ( local) {
961
+ // If only the storage is required to be live, but local is not initialized, then we can
962
+ // ignore such type for auto trait purposes.
963
+ true
964
+ } else {
965
+ // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
966
+ // the information. This is alright, since `ignore_for_traits` is only relevant when
967
+ // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
968
+ // default.
969
+ match decl. local_info {
970
+ // Do not include raw pointers created from accessing `static` items, as those could
971
+ // well be re-created by another access to the same static.
972
+ ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
973
+ !is_thread_local
974
+ }
975
+ // Fake borrows are only read by fake reads, so do not have any reality in
976
+ // post-analysis MIR.
977
+ ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
978
+ _ => false ,
938
979
}
939
- // Fake borrows are only read by fake reads, so do not have any reality in
940
- // post-analysis MIR.
941
- ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
942
- _ => false ,
943
980
}
944
981
} else {
945
982
// FIXME(#105084) HIR-based drop tracking does not account for all the temporaries that
0 commit comments