@@ -66,10 +66,12 @@ use rustc_middle::mir::*;
6666use rustc_middle:: ty:: { self , CoroutineArgs , CoroutineArgsExt , InstanceKind , Ty , TyCtxt } ;
6767use rustc_middle:: { bug, span_bug} ;
6868use rustc_mir_dataflow:: impls:: {
69- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
69+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
70+ MaybeStorageLive ,
7071} ;
72+ use rustc_mir_dataflow:: move_paths:: MoveData ;
7173use rustc_mir_dataflow:: storage:: always_storage_live_locals;
72- use rustc_mir_dataflow:: Analysis ;
74+ use rustc_mir_dataflow:: { self , Analysis , MaybeReachable } ;
7375use rustc_span:: def_id:: { DefId , LocalDefId } ;
7476use rustc_span:: symbol:: sym;
7577use rustc_span:: Span ;
@@ -725,6 +727,10 @@ struct LivenessInfo {
725727 /// Which locals are live across any suspension point.
726728 saved_locals : CoroutineSavedLocals ,
727729
730+ /// Which locals are live *and* initialized across any suspension point.
731+ /// A local that is live but is not initialized does not need to accounted in auto trait checking.
732+ init_locals : BitSet < Local > ,
733+
728734 /// The set of saved locals live at each suspension point.
729735 live_locals_at_suspension_points : Vec < BitSet < CoroutineSavedLocal > > ,
730736
@@ -784,10 +790,25 @@ fn locals_live_across_suspend_points<'tcx>(
784790 . iterate_to_fixpoint ( )
785791 . into_results_cursor ( body) ;
786792
793+ let param_env = tcx. param_env ( body. source . def_id ( ) ) ;
794+ let move_data =
795+ MoveData :: gather_moves ( body, tcx, param_env) . unwrap_or_else ( |( move_data, _) | {
796+ tcx. sess . delay_span_bug ( body. span , "gather_moves failed" ) ;
797+ move_data
798+ } ) ;
799+ let mdpe = MoveDataParamEnv { move_data, param_env } ;
800+
801+ // Calculate the set of locals which are initialized
802+ let mut inits = MaybeInitializedPlaces :: new ( tcx, body, & mdpe)
803+ . into_engine ( tcx, body)
804+ . iterate_to_fixpoint ( )
805+ . into_results_cursor ( body_ref) ;
806+
787807 let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
788808 let mut live_locals_at_suspension_points = Vec :: new ( ) ;
789809 let mut source_info_at_suspension_points = Vec :: new ( ) ;
790810 let mut live_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
811+ let mut init_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
791812
792813 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
793814 if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -826,12 +847,27 @@ fn locals_live_across_suspend_points<'tcx>(
826847 // The coroutine argument is ignored.
827848 live_locals. remove ( SELF_ARG ) ;
828849
829- debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
850+ inits. seek_to_block_end ( block) ;
851+ let mut init_locals: BitSet < _ > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
852+ if let MaybeReachable :: Reachable ( bitset) = inits. get ( ) {
853+ for move_path_index in bitset. iter ( ) {
854+ if let Some ( local) = mdpe. move_data . move_paths [ move_path_index] . place . as_local ( )
855+ {
856+ init_locals. insert ( local) ;
857+ }
858+ }
859+ }
860+ init_locals. intersect ( & live_locals) ;
861+
862+ debug ! (
863+ "loc = {:?}, live_locals = {:?}, init_locals = {:?}" ,
864+ loc, live_locals, init_locals
865+ ) ;
830866
831867 // Add the locals live at this suspension point to the set of locals which live across
832868 // any suspension points
833869 live_locals_at_any_suspension_point. union ( & live_locals) ;
834-
870+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
835871 live_locals_at_suspension_points. push ( live_locals) ;
836872 source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
837873 }
@@ -856,6 +892,7 @@ fn locals_live_across_suspend_points<'tcx>(
856892
857893 LivenessInfo {
858894 saved_locals,
895+ init_locals : init_locals_at_any_suspension_point,
859896 live_locals_at_suspension_points,
860897 source_info_at_suspension_points,
861898 storage_conflicts,
@@ -1030,6 +1067,7 @@ fn compute_layout<'tcx>(
10301067) {
10311068 let LivenessInfo {
10321069 saved_locals,
1070+ init_locals,
10331071 live_locals_at_suspension_points,
10341072 source_info_at_suspension_points,
10351073 storage_conflicts,
@@ -1046,20 +1084,26 @@ fn compute_layout<'tcx>(
10461084 let decl = & body. local_decls [ local] ;
10471085 debug ! ( ?decl) ;
10481086
1049- // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
1050- // the information. This is alright, since `ignore_for_traits` is only relevant when
1051- // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
1052- // default.
1053- let ignore_for_traits = match decl. local_info {
1054- // Do not include raw pointers created from accessing `static` items, as those could
1055- // well be re-created by another access to the same static.
1056- ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
1057- !is_thread_local
1087+ let ignore_for_traits = if !init_locals. contains ( local) {
1088+ // If only the storage is required to be live, but local is not initialized, then we can
1089+ // ignore such type for auto trait purposes.
1090+ true
1091+ } else {
1092+ // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
1093+ // the information. This is alright, since `ignore_for_traits` is only relevant when
1094+ // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
1095+ // default.
1096+ match decl. local_info {
1097+ // Do not include raw pointers created from accessing `static` items, as those could
1098+ // well be re-created by another access to the same static.
1099+ ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
1100+ !is_thread_local
1101+ }
1102+ // Fake borrows are only read by fake reads, so do not have any reality in
1103+ // post-analysis MIR.
1104+ ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
1105+ _ => false ,
10581106 }
1059- // Fake borrows are only read by fake reads, so do not have any reality in
1060- // post-analysis MIR.
1061- ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow ) => true ,
1062- _ => false ,
10631107 } ;
10641108 let decl =
10651109 CoroutineSavedTy { ty : decl. ty , source_info : decl. source_info , ignore_for_traits } ;
0 commit comments