@@ -174,6 +174,27 @@ trait Qualif: QualifIdx {
174
174
Self :: in_any_value_of_ty ( cx, ty) . unwrap_or ( true )
175
175
}
176
176
177
+ fn in_arg_initially ( cx : & ConstCx < ' _ , ' tcx > , local : Local ) -> bool {
178
+ Self :: in_any_value_of_ty ( cx, cx. body . local_decls [ local] . ty )
179
+ . expect ( "`in_arg_initially` is overridden if `in_any_value_of_ty` is `None`" )
180
+ }
181
+
182
+ fn in_temp_initially (
183
+ _cx : & ConstCx < ' _ , ' tcx > ,
184
+ _local : Local ,
185
+ _promotion_state : & IndexVec < Local , TempState > ,
186
+ ) -> bool {
187
+ false
188
+ }
189
+
190
+ fn in_user_variable_initially ( _cx : & ConstCx < ' _ , ' tcx > , _local : Local ) -> bool {
191
+ false
192
+ }
193
+
194
+ fn in_return_place_initially ( _cx : & ConstCx < ' _ , ' tcx > , _local : Local ) -> bool {
195
+ false
196
+ }
197
+
177
198
fn in_local ( cx : & ConstCx < ' _ , ' _ > , local : Local ) -> bool {
178
199
cx. per_local . 0 [ Self :: IDX ] . contains ( local)
179
200
}
@@ -428,6 +449,22 @@ impl Qualif for NeedsDrop {
428
449
struct IsNotPromotable ;
429
450
430
451
impl Qualif for IsNotPromotable {
452
+ fn in_arg_initially ( _cx : & ConstCx < ' _ , ' tcx > , _local : Local ) -> bool {
453
+ true
454
+ }
455
+
456
+ fn in_temp_initially (
457
+ _cx : & ConstCx < ' _ , ' tcx > ,
458
+ local : Local ,
459
+ promotion_state : & IndexVec < Local , TempState > ,
460
+ ) -> bool {
461
+ !promotion_state[ local] . is_promotable ( )
462
+ }
463
+
464
+ fn in_user_variable_initially ( _cx : & ConstCx < ' _ , ' tcx > , _local : Local ) -> bool {
465
+ true
466
+ }
467
+
431
468
fn in_static ( cx : & ConstCx < ' _ , ' tcx > , static_ : & Static < ' tcx > ) -> bool {
432
469
match static_. kind {
433
470
StaticKind :: Promoted ( _, _) => unreachable ! ( ) ,
@@ -578,6 +615,12 @@ impl Qualif for IsNotPromotable {
578
615
struct IsNotImplicitlyPromotable ;
579
616
580
617
impl Qualif for IsNotImplicitlyPromotable {
618
+ /// Function parameters will still never be promoted because this same function returns `true`
619
+ /// for `IsNotPromotable`, and both are checked before promoting a `Local`.
620
+ fn in_arg_initially ( _cx : & ConstCx < ' _ , ' tcx > , _local : Local ) -> bool {
621
+ false
622
+ }
623
+
581
624
fn in_call (
582
625
cx : & ConstCx < ' _ , ' tcx > ,
583
626
callee : & Operand < ' tcx > ,
@@ -729,18 +772,30 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
729
772
per_local : PerQualif :: new ( BitSet :: new_empty ( body. local_decls . len ( ) ) ) ,
730
773
} ;
731
774
732
- for ( local, decl) in body. local_decls . iter_enumerated ( ) {
733
- if let LocalKind :: Arg = body. local_kind ( local) {
734
- let qualifs = cx. qualifs_in_any_value_of_ty ( decl. ty ) ;
735
- for ( per_local, qualif) in & mut cx. per_local . as_mut ( ) . zip ( qualifs) . 0 {
736
- if * qualif {
737
- per_local. insert ( local) ;
775
+ for ( local, _) in body. local_decls . iter_enumerated ( ) {
776
+ match cx. body . local_kind ( local) {
777
+ LocalKind :: Arg => for_each_qualif ! ( |q: Q | {
778
+ if Q :: in_arg_initially( & cx, local) {
779
+ cx. per_local[ q] . insert( local) ;
738
780
}
739
- }
740
- }
741
- if !temps[ local] . is_promotable ( ) {
742
- cx. per_local [ IsNotPromotable ] . insert ( local) ;
743
- }
781
+ } ) ,
782
+ LocalKind :: Temp => for_each_qualif ! ( |q: Q | {
783
+ if Q :: in_temp_initially( & cx, local, & temps) {
784
+ cx. per_local[ q] . insert( local) ;
785
+ }
786
+ } ) ,
787
+ LocalKind :: Var => for_each_qualif ! ( |q: Q | {
788
+ if Q :: in_user_variable_initially( & cx, local) {
789
+ cx. per_local[ q] . insert( local) ;
790
+ }
791
+ } ) ,
792
+ LocalKind :: ReturnPointer => for_each_qualif ! ( |q: Q | {
793
+ if Q :: in_return_place_initially( & cx, local) {
794
+ cx. per_local[ q] . insert( local) ;
795
+ }
796
+ } ) ,
797
+ } ;
798
+
744
799
if let LocalKind :: Var = body. local_kind ( local) {
745
800
// Sanity check to prevent implicit and explicit promotion of
746
801
// named locals
0 commit comments