@@ -70,10 +70,12 @@ use rustc_middle::ty::InstanceDef;
70
70
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
71
71
use rustc_middle:: ty:: { GeneratorArgs , GenericArgsRef } ;
72
72
use rustc_mir_dataflow:: impls:: {
73
- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
73
+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
74
+ MaybeStorageLive ,
74
75
} ;
76
+ use rustc_mir_dataflow:: move_paths:: MoveData ;
75
77
use rustc_mir_dataflow:: storage:: always_storage_live_locals;
76
- use rustc_mir_dataflow:: { self , Analysis } ;
78
+ use rustc_mir_dataflow:: { self , Analysis , MaybeReachable , MoveDataParamEnv } ;
77
79
use rustc_span:: def_id:: { DefId , LocalDefId } ;
78
80
use rustc_span:: symbol:: sym;
79
81
use rustc_span:: Span ;
@@ -567,6 +569,10 @@ struct LivenessInfo {
567
569
/// Which locals are live across any suspension point.
568
570
saved_locals : GeneratorSavedLocals ,
569
571
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
+
570
576
/// The set of saved locals live at each suspension point.
571
577
live_locals_at_suspension_points : Vec < BitSet < GeneratorSavedLocal > > ,
572
578
@@ -620,10 +626,25 @@ fn locals_live_across_suspend_points<'tcx>(
620
626
. iterate_to_fixpoint ( )
621
627
. into_results_cursor ( body_ref) ;
622
628
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
+
623
643
let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
624
644
let mut live_locals_at_suspension_points = Vec :: new ( ) ;
625
645
let mut source_info_at_suspension_points = Vec :: new ( ) ;
626
646
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 ( ) ) ;
627
648
628
649
for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
629
650
if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -662,12 +683,27 @@ fn locals_live_across_suspend_points<'tcx>(
662
683
// The generator argument is ignored.
663
684
live_locals. remove ( SELF_ARG ) ;
664
685
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
+ ) ;
666
702
667
703
// Add the locals live at this suspension point to the set of locals which live across
668
704
// any suspension points
669
705
live_locals_at_any_suspension_point. union ( & live_locals) ;
670
-
706
+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
671
707
live_locals_at_suspension_points. push ( live_locals) ;
672
708
source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
673
709
}
@@ -692,6 +728,7 @@ fn locals_live_across_suspend_points<'tcx>(
692
728
693
729
LivenessInfo {
694
730
saved_locals,
731
+ init_locals : init_locals_at_any_suspension_point,
695
732
live_locals_at_suspension_points,
696
733
source_info_at_suspension_points,
697
734
storage_conflicts,
@@ -863,6 +900,7 @@ fn compute_layout<'tcx>(
863
900
) {
864
901
let LivenessInfo {
865
902
saved_locals,
903
+ init_locals,
866
904
live_locals_at_suspension_points,
867
905
source_info_at_suspension_points,
868
906
storage_conflicts,
@@ -879,20 +917,26 @@ fn compute_layout<'tcx>(
879
917
let decl = & body. local_decls [ local] ;
880
918
debug ! ( ?decl) ;
881
919
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 ,
891
939
}
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 ,
896
940
} ;
897
941
let decl =
898
942
GeneratorSavedTy { ty : decl. ty , source_info : decl. source_info , ignore_for_traits } ;
0 commit comments