@@ -66,10 +66,12 @@ use rustc_middle::mir::*;
66
66
use rustc_middle:: ty:: { self , CoroutineArgs , CoroutineArgsExt , InstanceKind , Ty , TyCtxt } ;
67
67
use rustc_middle:: { bug, span_bug} ;
68
68
use rustc_mir_dataflow:: impls:: {
69
- MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
69
+ MaybeBorrowedLocals , MaybeInitializedPlaces , MaybeLiveLocals , MaybeRequiresStorage ,
70
+ MaybeStorageLive ,
70
71
} ;
72
+ use rustc_mir_dataflow:: move_paths:: MoveData ;
71
73
use rustc_mir_dataflow:: storage:: always_storage_live_locals;
72
- use rustc_mir_dataflow:: Analysis ;
74
+ use rustc_mir_dataflow:: { self , Analysis , MaybeReachable } ;
73
75
use rustc_span:: def_id:: { DefId , LocalDefId } ;
74
76
use rustc_span:: symbol:: sym;
75
77
use rustc_span:: Span ;
@@ -725,6 +727,10 @@ struct LivenessInfo {
725
727
/// Which locals are live across any suspension point.
726
728
saved_locals : CoroutineSavedLocals ,
727
729
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
+
728
734
/// The set of saved locals live at each suspension point.
729
735
live_locals_at_suspension_points : Vec < BitSet < CoroutineSavedLocal > > ,
730
736
@@ -784,10 +790,25 @@ fn locals_live_across_suspend_points<'tcx>(
784
790
. iterate_to_fixpoint ( )
785
791
. into_results_cursor ( body) ;
786
792
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
+
787
807
let mut storage_liveness_map = IndexVec :: from_elem ( None , & body. basic_blocks ) ;
788
808
let mut live_locals_at_suspension_points = Vec :: new ( ) ;
789
809
let mut source_info_at_suspension_points = Vec :: new ( ) ;
790
810
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 ( ) ) ;
791
812
792
813
for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
793
814
if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
@@ -826,12 +847,27 @@ fn locals_live_across_suspend_points<'tcx>(
826
847
// The coroutine argument is ignored.
827
848
live_locals. remove ( SELF_ARG ) ;
828
849
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
+ ) ;
830
866
831
867
// Add the locals live at this suspension point to the set of locals which live across
832
868
// any suspension points
833
869
live_locals_at_any_suspension_point. union ( & live_locals) ;
834
-
870
+ init_locals_at_any_suspension_point . union ( & init_locals ) ;
835
871
live_locals_at_suspension_points. push ( live_locals) ;
836
872
source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ;
837
873
}
@@ -856,6 +892,7 @@ fn locals_live_across_suspend_points<'tcx>(
856
892
857
893
LivenessInfo {
858
894
saved_locals,
895
+ init_locals : init_locals_at_any_suspension_point,
859
896
live_locals_at_suspension_points,
860
897
source_info_at_suspension_points,
861
898
storage_conflicts,
@@ -1030,6 +1067,7 @@ fn compute_layout<'tcx>(
1030
1067
) {
1031
1068
let LivenessInfo {
1032
1069
saved_locals,
1070
+ init_locals,
1033
1071
live_locals_at_suspension_points,
1034
1072
source_info_at_suspension_points,
1035
1073
storage_conflicts,
@@ -1046,20 +1084,26 @@ fn compute_layout<'tcx>(
1046
1084
let decl = & body. local_decls [ local] ;
1047
1085
debug ! ( ?decl) ;
1048
1086
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 ,
1058
1106
}
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 ,
1063
1107
} ;
1064
1108
let decl =
1065
1109
CoroutineSavedTy { ty : decl. ty , source_info : decl. source_info , ignore_for_traits } ;
0 commit comments