@@ -365,11 +365,11 @@ impl Qualif for NeedsDrop {
365365 }
366366}
367367
368- // Not constant at all - non-`const fn` calls, asm!,
368+ // Not promotable at all - non-`const fn` calls, asm!,
369369// pointer comparisons, ptr-to-int casts, etc.
370- struct IsNotConst ;
370+ struct IsNotPromotable ;
371371
372- impl Qualif for IsNotConst {
372+ impl Qualif for IsNotPromotable {
373373 const IDX : usize = 2 ;
374374
375375 fn in_static ( cx : & ConstCx < ' _ , ' tcx > , static_ : & Static < ' tcx > ) -> bool {
@@ -508,13 +508,17 @@ impl Qualif for IsNotConst {
508508 }
509509}
510510
511- // Refers to temporaries which cannot be promoted as
512- // promote_consts decided they weren't simple enough.
513- // FIXME(oli-obk,eddyb): Remove this flag entirely and
514- // solely process this information via `IsNotConst`.
515- struct IsNotPromotable ;
516-
517- impl Qualif for IsNotPromotable {
511+ /// Refers to temporaries which cannot be promoted *implicitly*.
512+ /// Explicit promotion happens e.g. for constant arguments declared via `rustc_args_required_const`.
513+ /// Inside a const context all constness rules
514+ /// apply, so implicit promotion simply has to follow the regular constant rules (modulo interior
515+ /// mutability or `Drop` rules which are handled `HasMutInterior` and `NeedsDrop` respectively).
516+ /// Implicit promotion inside regular functions does not happen if `const fn` calls are involved,
517+ /// as the call may be perfectly alright at runtime, but fail at compile time e.g. due to addresses
518+ /// being compared inside the function.
519+ struct IsNotImplicitlyPromotable ;
520+
521+ impl Qualif for IsNotImplicitlyPromotable {
518522 const IDX : usize = 3 ;
519523
520524 fn in_call (
@@ -550,33 +554,36 @@ macro_rules! static_assert_seq_qualifs {
550554 static_assert!( SEQ_QUALIFS : QUALIF_COUNT == $i) ;
551555 } ;
552556}
553- static_assert_seq_qualifs ! ( 0 => HasMutInterior , NeedsDrop , IsNotConst , IsNotPromotable ) ;
557+ static_assert_seq_qualifs ! (
558+ 0 => HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
559+ ) ;
554560
555561impl ConstCx < ' _ , ' tcx > {
556562 fn qualifs_in_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> PerQualif < bool > {
557563 let mut qualifs = PerQualif :: default ( ) ;
558564 qualifs[ HasMutInterior ] = HasMutInterior :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
559565 qualifs[ NeedsDrop ] = NeedsDrop :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
560- qualifs[ IsNotConst ] = IsNotConst :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
561566 qualifs[ IsNotPromotable ] = IsNotPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
567+ qualifs[ IsNotImplicitlyPromotable ] =
568+ IsNotImplicitlyPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
562569 qualifs
563570 }
564571
565572 fn qualifs_in_local ( & self , local : Local ) -> PerQualif < bool > {
566573 let mut qualifs = PerQualif :: default ( ) ;
567574 qualifs[ HasMutInterior ] = HasMutInterior :: in_local ( self , local) ;
568575 qualifs[ NeedsDrop ] = NeedsDrop :: in_local ( self , local) ;
569- qualifs[ IsNotConst ] = IsNotConst :: in_local ( self , local) ;
570576 qualifs[ IsNotPromotable ] = IsNotPromotable :: in_local ( self , local) ;
577+ qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_local ( self , local) ;
571578 qualifs
572579 }
573580
574581 fn qualifs_in_value ( & self , source : ValueSource < ' _ , ' tcx > ) -> PerQualif < bool > {
575582 let mut qualifs = PerQualif :: default ( ) ;
576583 qualifs[ HasMutInterior ] = HasMutInterior :: in_value ( self , source) ;
577584 qualifs[ NeedsDrop ] = NeedsDrop :: in_value ( self , source) ;
578- qualifs[ IsNotConst ] = IsNotConst :: in_value ( self , source) ;
579585 qualifs[ IsNotPromotable ] = IsNotPromotable :: in_value ( self , source) ;
586+ qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_value ( self , source) ;
580587 qualifs
581588 }
582589}
@@ -631,26 +638,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
631638 } ;
632639
633640 for ( local, decl) in mir. local_decls . iter_enumerated ( ) {
634- match mir. local_kind ( local) {
635- LocalKind :: Arg => {
636- let qualifs = cx. qualifs_in_any_value_of_ty ( decl. ty ) ;
637- for ( per_local, qualif) in & mut cx. per_local . as_mut ( ) . zip ( qualifs) . 0 {
638- if * qualif {
639- per_local. insert ( local) ;
640- }
641+ if let LocalKind :: Arg = mir. local_kind ( local) {
642+ let qualifs = cx. qualifs_in_any_value_of_ty ( decl. ty ) ;
643+ for ( per_local, qualif) in & mut cx. per_local . as_mut ( ) . zip ( qualifs) . 0 {
644+ if * qualif {
645+ per_local. insert ( local) ;
641646 }
642- cx. per_local [ IsNotConst ] . insert ( local) ;
643647 }
644-
645- LocalKind :: Var if mode == Mode :: Fn => {
646- cx. per_local [ IsNotConst ] . insert ( local) ;
647- }
648-
649- LocalKind :: Temp if !temps[ local] . is_promotable ( ) => {
650- cx. per_local [ IsNotConst ] . insert ( local) ;
651- }
652-
653- _ => { }
648+ }
649+ if !temps[ local] . is_promotable ( ) {
650+ cx. per_local [ IsNotPromotable ] . insert ( local) ;
651+ }
652+ if let LocalKind :: Var = mir. local_kind ( local) {
653+ // Sanity check to prevent implicit and explicit promotion of
654+ // named locals
655+ assert ! ( cx. per_local[ IsNotPromotable ] . contains( local) ) ;
654656 }
655657 }
656658
@@ -698,11 +700,11 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
698700 // the borrowed place is disallowed from being borrowed,
699701 // due to either a mutable borrow (with some exceptions),
700702 // or an shared borrow of a value with interior mutability.
701- // Then `HasMutInterior` is replaced with `IsNotConst `,
703+ // Then `HasMutInterior` is replaced with `IsNotPromotable `,
702704 // to avoid duplicate errors (e.g. from reborrowing).
703705 if qualifs[ HasMutInterior ] {
704706 qualifs[ HasMutInterior ] = false ;
705- qualifs[ IsNotConst ] = true ;
707+ qualifs[ IsNotPromotable ] = true ;
706708
707709 if self . mode != Mode :: Fn {
708710 if let BorrowKind :: Mut { .. } = kind {
@@ -817,15 +819,15 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
817819 }
818820 }
819821
820- // Ensure the `IsNotConst ` qualification is preserved.
822+ // Ensure the `IsNotPromotable ` qualification is preserved.
821823 // NOTE(eddyb) this is actually unnecessary right now, as
822824 // we never replace the local's qualif, but we might in
823825 // the future, and so it serves to catch changes that unset
824826 // important bits (in which case, asserting `contains` could
825827 // be replaced with calling `insert` to re-set the bit).
826828 if kind == LocalKind :: Temp {
827829 if !self . temp_promotion_state [ index] . is_promotable ( ) {
828- assert ! ( self . cx. per_local[ IsNotConst ] . contains( index) ) ;
830+ assert ! ( self . cx. per_local[ IsNotPromotable ] . contains( index) ) ;
829831 }
830832 }
831833 }
@@ -911,7 +913,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
911913
912914 // Account for errors in consts by using the
913915 // conservative type qualification instead.
914- if qualifs[ IsNotConst ] {
916+ if qualifs[ IsNotPromotable ] {
915917 qualifs = self . qualifs_in_any_value_of_ty ( mir. return_ty ( ) ) ;
916918 }
917919
@@ -1326,7 +1328,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
13261328 // which happens even without the user requesting it.
13271329 // We can error out with a hard error if the argument is not
13281330 // constant here.
1329- if !IsNotConst :: in_operand ( self , arg) {
1331+ if !IsNotPromotable :: in_operand ( self , arg) {
13301332 debug ! ( "visit_terminator_kind: candidate={:?}" , candidate) ;
13311333 self . promotion_candidates . push ( candidate) ;
13321334 } else {
@@ -1444,7 +1446,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14441446
14451447 if mir. return_ty ( ) . references_error ( ) {
14461448 tcx. sess . delay_span_bug ( mir. span , "mir_const_qualif: Mir had errors" ) ;
1447- return ( 1 << IsNotConst :: IDX , Lrc :: new ( BitSet :: new_empty ( 0 ) ) ) ;
1449+ return ( 1 << IsNotPromotable :: IDX , Lrc :: new ( BitSet :: new_empty ( 0 ) ) ) ;
14481450 }
14491451
14501452 Checker :: new ( tcx, def_id, mir, Mode :: Const ) . check_const ( )
0 commit comments