@@ -67,10 +67,12 @@ use rustc_middle::mir::*;
6767use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
6868use rustc_middle:: ty:: { GeneratorSubsts , SubstsRef } ;
6969use rustc_mir_dataflow:: impls:: {
70- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
70+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
71+ MaybeStorageLive ,
7172} ;
73+ use rustc_mir_dataflow:: move_paths:: MoveData ;
7274use rustc_mir_dataflow:: storage:: always_storage_live_locals;
73- use rustc_mir_dataflow:: { self , Analysis } ;
75+ use rustc_mir_dataflow:: { self , Analysis , MoveDataParamEnv } ;
7476use rustc_span:: def_id:: { DefId , LocalDefId } ;
7577use rustc_span:: symbol:: sym;
7678use rustc_span:: Span ;
@@ -561,6 +563,10 @@ struct LivenessInfo {
561563 /// Which locals are live across any suspension point.
562564 saved_locals : GeneratorSavedLocals ,
563565
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+
564570 /// The set of saved locals live at each suspension point.
565571 live_locals_at_suspension_points : Vec < BitSet < GeneratorSavedLocal > > ,
566572
@@ -615,10 +621,21 @@ fn locals_live_across_suspend_points<'tcx>(
615621 . iterate_to_fixpoint ( )
616622 . into_results_cursor ( body_ref) ;
617623
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+
618634 let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
619635 let mut live_locals_at_suspension_points = Vec :: new ( ) ;
620636 let mut source_info_at_suspension_points = Vec :: new ( ) ;
621637 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 ( ) ) ;
622639
623640 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
624641 if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -657,12 +674,24 @@ fn locals_live_across_suspend_points<'tcx>(
657674 // The generator argument is ignored.
658675 live_locals. remove ( SELF_ARG ) ;
659676
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+ ) ;
661690
662691 // Add the locals live at this suspension point to the set of locals which live across
663692 // any suspension points
664693 live_locals_at_any_suspension_point. union ( & live_locals) ;
665-
694+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
666695 live_locals_at_suspension_points. push ( live_locals) ;
667696 source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
668697 }
@@ -687,6 +716,7 @@ fn locals_live_across_suspend_points<'tcx>(
687716
688717 LivenessInfo {
689718 saved_locals,
719+ init_locals : init_locals_at_any_suspension_point,
690720 live_locals_at_suspension_points,
691721 source_info_at_suspension_points,
692722 storage_conflicts,
@@ -909,6 +939,7 @@ fn compute_layout<'tcx>(
909939) {
910940 let LivenessInfo {
911941 saved_locals,
942+ init_locals,
912943 live_locals_at_suspension_points,
913944 source_info_at_suspension_points,
914945 storage_conflicts,
@@ -926,20 +957,26 @@ fn compute_layout<'tcx>(
926957 debug ! ( ?decl) ;
927958
928959 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 ,
938979 }
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 ,
943980 }
944981 } else {
945982 // FIXME(#105084) HIR-based drop tracking does not account for all the temporaries that
0 commit comments