@@ -70,10 +70,12 @@ use rustc_middle::ty::InstanceDef;
7070use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
7171use rustc_middle:: ty:: { GeneratorArgs , GenericArgsRef } ;
7272use rustc_mir_dataflow:: impls:: {
73- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
73+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
74+ MaybeStorageLive ,
7475} ;
76+ use rustc_mir_dataflow:: move_paths:: MoveData ;
7577use rustc_mir_dataflow:: storage:: always_storage_live_locals;
76- use rustc_mir_dataflow:: { self , Analysis } ;
78+ use rustc_mir_dataflow:: { self , Analysis , MaybeReachable , MoveDataParamEnv } ;
7779use rustc_span:: def_id:: { DefId , LocalDefId } ;
7880use rustc_span:: symbol:: sym;
7981use rustc_span:: Span ;
@@ -567,6 +569,10 @@ struct LivenessInfo {
567569 /// Which locals are live across any suspension point.
568570 saved_locals : GeneratorSavedLocals ,
569571
572+ /// Which locals are live *and* initialized across any suspension point.
573+ /// A local that is live but is not initialized does not need to accounted in auto trait checking.
574+ init_locals : BitSet < Local > ,
575+
570576 /// The set of saved locals live at each suspension point.
571577 live_locals_at_suspension_points : Vec < BitSet < GeneratorSavedLocal > > ,
572578
@@ -620,10 +626,25 @@ fn locals_live_across_suspend_points<'tcx>(
620626 . iterate_to_fixpoint ( )
621627 . into_results_cursor ( body_ref) ;
622628
629+ let param_env = tcx. param_env ( body. source . def_id ( ) ) ;
630+ let move_data =
631+ MoveData :: gather_moves ( body, tcx, param_env) . unwrap_or_else ( |( move_data, _) | {
632+ tcx. sess . delay_span_bug ( body. span , "gather_moves failed" ) ;
633+ move_data
634+ } ) ;
635+ let mdpe = MoveDataParamEnv { move_data, param_env } ;
636+
637+ // Calculate the set of locals which are initialized
638+ let mut inits = MaybeInitializedPlaces :: new ( tcx, body, & mdpe)
639+ . into_engine ( tcx, body)
640+ . iterate_to_fixpoint ( )
641+ . into_results_cursor ( body_ref) ;
642+
623643 let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
624644 let mut live_locals_at_suspension_points = Vec :: new ( ) ;
625645 let mut source_info_at_suspension_points = Vec :: new ( ) ;
626646 let mut live_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
647+ let mut init_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
627648
628649 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
629650 if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -662,12 +683,27 @@ fn locals_live_across_suspend_points<'tcx>(
662683 // The generator argument is ignored.
663684 live_locals. remove ( SELF_ARG ) ;
664685
665- debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
686+ inits. seek_to_block_end ( block) ;
687+ let mut init_locals: BitSet < _ > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
688+ if let MaybeReachable :: Reachable ( bitset) = inits. get ( ) {
689+ for move_path_index in bitset. iter ( ) {
690+ if let Some ( local) = mdpe. move_data . move_paths [ move_path_index] . place . as_local ( )
691+ {
692+ init_locals. insert ( local) ;
693+ }
694+ }
695+ }
696+ init_locals. intersect ( & live_locals) ;
697+
698+ debug ! (
699+ "loc = {:?}, live_locals = {:?}, init_locals = {:?}" ,
700+ loc, live_locals, init_locals
701+ ) ;
666702
667703 // Add the locals live at this suspension point to the set of locals which live across
668704 // any suspension points
669705 live_locals_at_any_suspension_point. union ( & live_locals) ;
670-
706+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
671707 live_locals_at_suspension_points. push ( live_locals) ;
672708 source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
673709 }
@@ -692,6 +728,7 @@ fn locals_live_across_suspend_points<'tcx>(
692728
693729 LivenessInfo {
694730 saved_locals,
731+ init_locals : init_locals_at_any_suspension_point,
695732 live_locals_at_suspension_points,
696733 source_info_at_suspension_points,
697734 storage_conflicts,
@@ -863,6 +900,7 @@ fn compute_layout<'tcx>(
863900) {
864901 let LivenessInfo {
865902 saved_locals,
903+ init_locals,
866904 live_locals_at_suspension_points,
867905 source_info_at_suspension_points,
868906 storage_conflicts,
@@ -879,20 +917,26 @@ fn compute_layout<'tcx>(
879917 let decl = & body. local_decls [ local] ;
880918 debug ! ( ?decl) ;
881919
882- // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
883- // the information. This is alright, since `ignore_for_traits` is only relevant when
884- // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
885- // default.
886- let ignore_for_traits = match decl. local_info {
887- // Do not include raw pointers created from accessing `static` items, as those could
888- // well be re-created by another access to the same static.
889- ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
890- !is_thread_local
920+ let ignore_for_traits = if !init_locals. contains ( local) {
921+ // If only the storage is required to be live, but local is not initialized, then we can
922+ // ignore such type for auto trait purposes.
923+ true
924+ } else {
925+ // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
926+ // the information. This is alright, since `ignore_for_traits` is only relevant when
927+ // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
928+ // default.
929+ match decl. local_info {
930+ // Do not include raw pointers created from accessing `static` items, as those could
931+ // well be re-created by another access to the same static.
932+ ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
933+ !is_thread_local
934+ }
935+ // Fake borrows are only read by fake reads, so do not have any reality in
936+ // post-analysis MIR.
937+ ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
938+ _ => false ,
891939 }
892- // Fake borrows are only read by fake reads, so do not have any reality in
893- // post-analysis MIR.
894- ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
895- _ => false ,
896940 } ;
897941 let decl =
898942 GeneratorSavedTy { ty : decl. ty , source_info : decl. source_info , ignore_for_traits } ;
0 commit comments