@@ -365,11 +365,11 @@ impl Qualif for NeedsDrop {
365
365
}
366
366
}
367
367
368
- // Not constant at all - non-`const fn` calls, asm!,
368
+ // Not promotable at all - non-`const fn` calls, asm!,
369
369
// pointer comparisons, ptr-to-int casts, etc.
370
- struct IsNotConst ;
370
+ struct IsNotPromotable ;
371
371
372
- impl Qualif for IsNotConst {
372
+ impl Qualif for IsNotPromotable {
373
373
const IDX : usize = 2 ;
374
374
375
375
fn in_static ( cx : & ConstCx < ' _ , ' tcx > , static_ : & Static < ' tcx > ) -> bool {
@@ -508,13 +508,17 @@ impl Qualif for IsNotConst {
508
508
}
509
509
}
510
510
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 {
518
522
const IDX : usize = 3 ;
519
523
520
524
fn in_call (
@@ -550,33 +554,36 @@ macro_rules! static_assert_seq_qualifs {
550
554
static_assert!( SEQ_QUALIFS : QUALIF_COUNT == $i) ;
551
555
} ;
552
556
}
553
- static_assert_seq_qualifs ! ( 0 => HasMutInterior , NeedsDrop , IsNotConst , IsNotPromotable ) ;
557
+ static_assert_seq_qualifs ! (
558
+ 0 => HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
559
+ ) ;
554
560
555
561
impl ConstCx < ' _ , ' tcx > {
556
562
fn qualifs_in_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> PerQualif < bool > {
557
563
let mut qualifs = PerQualif :: default ( ) ;
558
564
qualifs[ HasMutInterior ] = HasMutInterior :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
559
565
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 ) ;
561
566
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 ) ;
562
569
qualifs
563
570
}
564
571
565
572
fn qualifs_in_local ( & self , local : Local ) -> PerQualif < bool > {
566
573
let mut qualifs = PerQualif :: default ( ) ;
567
574
qualifs[ HasMutInterior ] = HasMutInterior :: in_local ( self , local) ;
568
575
qualifs[ NeedsDrop ] = NeedsDrop :: in_local ( self , local) ;
569
- qualifs[ IsNotConst ] = IsNotConst :: in_local ( self , local) ;
570
576
qualifs[ IsNotPromotable ] = IsNotPromotable :: in_local ( self , local) ;
577
+ qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_local ( self , local) ;
571
578
qualifs
572
579
}
573
580
574
581
fn qualifs_in_value ( & self , source : ValueSource < ' _ , ' tcx > ) -> PerQualif < bool > {
575
582
let mut qualifs = PerQualif :: default ( ) ;
576
583
qualifs[ HasMutInterior ] = HasMutInterior :: in_value ( self , source) ;
577
584
qualifs[ NeedsDrop ] = NeedsDrop :: in_value ( self , source) ;
578
- qualifs[ IsNotConst ] = IsNotConst :: in_value ( self , source) ;
579
585
qualifs[ IsNotPromotable ] = IsNotPromotable :: in_value ( self , source) ;
586
+ qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_value ( self , source) ;
580
587
qualifs
581
588
}
582
589
}
@@ -631,26 +638,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
631
638
} ;
632
639
633
640
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) ;
641
646
}
642
- cx. per_local [ IsNotConst ] . insert ( local) ;
643
647
}
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) ) ;
654
656
}
655
657
}
656
658
@@ -698,11 +700,11 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
698
700
// the borrowed place is disallowed from being borrowed,
699
701
// due to either a mutable borrow (with some exceptions),
700
702
// or an shared borrow of a value with interior mutability.
701
- // Then `HasMutInterior` is replaced with `IsNotConst `,
703
+ // Then `HasMutInterior` is replaced with `IsNotPromotable `,
702
704
// to avoid duplicate errors (e.g. from reborrowing).
703
705
if qualifs[ HasMutInterior ] {
704
706
qualifs[ HasMutInterior ] = false ;
705
- qualifs[ IsNotConst ] = true ;
707
+ qualifs[ IsNotPromotable ] = true ;
706
708
707
709
if self . mode != Mode :: Fn {
708
710
if let BorrowKind :: Mut { .. } = kind {
@@ -817,15 +819,15 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
817
819
}
818
820
}
819
821
820
- // Ensure the `IsNotConst ` qualification is preserved.
822
+ // Ensure the `IsNotPromotable ` qualification is preserved.
821
823
// NOTE(eddyb) this is actually unnecessary right now, as
822
824
// we never replace the local's qualif, but we might in
823
825
// the future, and so it serves to catch changes that unset
824
826
// important bits (in which case, asserting `contains` could
825
827
// be replaced with calling `insert` to re-set the bit).
826
828
if kind == LocalKind :: Temp {
827
829
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) ) ;
829
831
}
830
832
}
831
833
}
@@ -911,7 +913,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
911
913
912
914
// Account for errors in consts by using the
913
915
// conservative type qualification instead.
914
- if qualifs[ IsNotConst ] {
916
+ if qualifs[ IsNotPromotable ] {
915
917
qualifs = self . qualifs_in_any_value_of_ty ( mir. return_ty ( ) ) ;
916
918
}
917
919
@@ -1326,7 +1328,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1326
1328
// which happens even without the user requesting it.
1327
1329
// We can error out with a hard error if the argument is not
1328
1330
// constant here.
1329
- if !IsNotConst :: in_operand ( self , arg) {
1331
+ if !IsNotPromotable :: in_operand ( self , arg) {
1330
1332
debug ! ( "visit_terminator_kind: candidate={:?}" , candidate) ;
1331
1333
self . promotion_candidates . push ( candidate) ;
1332
1334
} else {
@@ -1444,7 +1446,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1444
1446
1445
1447
if mir. return_ty ( ) . references_error ( ) {
1446
1448
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 ) ) ) ;
1448
1450
}
1449
1451
1450
1452
Checker :: new ( tcx, def_id, mir, Mode :: Const ) . check_const ( )
0 commit comments