@@ -69,10 +69,11 @@ use rustc_middle::ty::{
6969} ;
7070use rustc_middle:: { bug, span_bug} ;
7171use rustc_mir_dataflow:: impls:: {
72- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
73- always_storage_live_locals,
72+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
73+ MaybeStorageLive , always_storage_live_locals,
7474} ;
75- use rustc_mir_dataflow:: { Analysis , Results , ResultsVisitor } ;
75+ use rustc_mir_dataflow:: move_paths:: MoveData ;
76+ use rustc_mir_dataflow:: { self , Analysis , MaybeReachable , Results , ResultsVisitor } ;
7677use rustc_span:: def_id:: { DefId , LocalDefId } ;
7778use rustc_span:: { Span , sym} ;
7879use rustc_target:: spec:: PanicStrategy ;
@@ -633,6 +634,12 @@ struct LivenessInfo {
633634 /// Which locals are live across any suspension point.
634635 saved_locals : CoroutineSavedLocals ,
635636
637+ /// Which locals are live *and* initialized across any suspension point.
638+ ///
639+ /// A local that is live but is not initialized (i.e. it has been moved out of) does
640+ /// not need to be accounted for in auto trait checking.
641+ init_locals : DenseBitSet < Local > ,
642+
636643 /// The set of saved locals live at each suspension point.
637644 live_locals_at_suspension_points : Vec < DenseBitSet < CoroutineSavedLocal > > ,
638645
@@ -686,10 +693,18 @@ fn locals_live_across_suspend_points<'tcx>(
686693 let mut liveness =
687694 MaybeLiveLocals . iterate_to_fixpoint ( tcx, body, Some ( "coroutine" ) ) . into_results_cursor ( body) ;
688695
696+ let move_data = MoveData :: gather_moves ( body, tcx, |_| true ) ;
697+
698+ // Calculate the set of locals which are initialized
699+ let mut inits = MaybeInitializedPlaces :: new ( tcx, body, & move_data)
700+ . iterate_to_fixpoint ( tcx, body, Some ( "coroutine" ) )
701+ . into_results_cursor ( body) ;
702+
689703 let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
690704 let mut live_locals_at_suspension_points = Vec :: new ( ) ;
691705 let mut source_info_at_suspension_points = Vec :: new ( ) ;
692706 let mut live_locals_at_any_suspension_point = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
707+ let mut init_locals_at_any_suspension_point = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
693708
694709 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
695710 if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -727,12 +742,26 @@ fn locals_live_across_suspend_points<'tcx>(
727742 // The coroutine argument is ignored.
728743 live_locals. remove ( SELF_ARG ) ;
729744
730- debug ! ( "loc = {:?}, live_locals = {:?}" , loc, live_locals) ;
745+ inits. seek_to_block_end ( block) ;
746+ let mut init_locals: DenseBitSet < _ > = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
747+ if let MaybeReachable :: Reachable ( bitset) = inits. get ( ) {
748+ for move_path_index in bitset. iter ( ) {
749+ if let Some ( local) = move_data. move_paths [ move_path_index] . place . as_local ( ) {
750+ init_locals. insert ( local) ;
751+ }
752+ }
753+ }
754+ init_locals. intersect ( & live_locals) ;
755+
756+ debug ! (
757+ "loc = {:?}, live_locals = {:?}, init_locals = {:?}" ,
758+ loc, live_locals, init_locals
759+ ) ;
731760
732761 // Add the locals live at this suspension point to the set of locals which live across
733762 // any suspension points
734763 live_locals_at_any_suspension_point. union ( & live_locals) ;
735-
764+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
736765 live_locals_at_suspension_points. push ( live_locals) ;
737766 source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
738767 }
@@ -757,6 +786,7 @@ fn locals_live_across_suspend_points<'tcx>(
757786
758787 LivenessInfo {
759788 saved_locals,
789+ init_locals : init_locals_at_any_suspension_point,
760790 live_locals_at_suspension_points,
761791 source_info_at_suspension_points,
762792 storage_conflicts,
@@ -929,6 +959,7 @@ fn compute_layout<'tcx>(
929959) {
930960 let LivenessInfo {
931961 saved_locals,
962+ init_locals,
932963 live_locals_at_suspension_points,
933964 source_info_at_suspension_points,
934965 storage_conflicts,
@@ -950,6 +981,9 @@ fn compute_layout<'tcx>(
950981 // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
951982 // default.
952983 let ignore_for_traits = match decl. local_info {
984+ // If only the storage is required to be live, but local is not initialized,
985+ // then we can ignore such type for auto trait purposes.
986+ _ if !init_locals. contains ( local) => true ,
953987 // Do not include raw pointers created from accessing `static` items, as those could
954988 // well be re-created by another access to the same static.
955989 ClearCrossCrate :: Set ( box LocalInfo :: StaticRef { is_thread_local, .. } ) => {
0 commit comments