@@ -174,6 +174,27 @@ trait Qualif: QualifIdx {
174174 Self :: in_any_value_of_ty ( cx, ty) . unwrap_or ( true )
175175 }
176176
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+
177198 fn in_local ( cx : & ConstCx < ' _ , ' _ > , local : Local ) -> bool {
178199 cx. per_local . 0 [ Self :: IDX ] . contains ( local)
179200 }
@@ -428,6 +449,22 @@ impl Qualif for NeedsDrop {
428449struct IsNotPromotable ;
429450
430451impl 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+
431468 fn in_static ( cx : & ConstCx < ' _ , ' tcx > , static_ : & Static < ' tcx > ) -> bool {
432469 match static_. kind {
433470 StaticKind :: Promoted ( _, _) => unreachable ! ( ) ,
@@ -578,6 +615,12 @@ impl Qualif for IsNotPromotable {
578615struct IsNotImplicitlyPromotable ;
579616
580617impl 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+
581624 fn in_call (
582625 cx : & ConstCx < ' _ , ' tcx > ,
583626 callee : & Operand < ' tcx > ,
@@ -729,18 +772,30 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
729772 per_local : PerQualif :: new ( BitSet :: new_empty ( body. local_decls . len ( ) ) ) ,
730773 } ;
731774
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) ;
738780 }
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+
744799 if let LocalKind :: Var = body. local_kind ( local) {
745800 // Sanity check to prevent implicit and explicit promotion of
746801 // named locals
0 commit comments