@@ -69,7 +69,7 @@ impl fmt::Display for Mode {
69
69
}
70
70
}
71
71
72
- const QUALIF_COUNT : usize = 4 ;
72
+ const QUALIF_COUNT : usize = 2 ;
73
73
74
74
// FIXME(eddyb) once we can use const generics, replace this array with
75
75
// something like `IndexVec` but for fixed-size arrays (`IndexArray`?).
@@ -78,20 +78,20 @@ struct PerQualif<T>([T; QUALIF_COUNT]);
78
78
79
79
impl < T : Clone > PerQualif < T > {
80
80
fn new ( x : T ) -> Self {
81
- PerQualif ( [ x. clone ( ) , x. clone ( ) , x . clone ( ) , x ] )
81
+ PerQualif ( [ x. clone ( ) , x] )
82
82
}
83
83
}
84
84
85
85
impl < T > PerQualif < T > {
86
86
fn as_mut ( & mut self ) -> PerQualif < & mut T > {
87
- let [ x0, x1, x2 , x3 ] = & mut self . 0 ;
88
- PerQualif ( [ x0, x1, x2 , x3 ] )
87
+ let [ x0, x1] = & mut self . 0 ;
88
+ PerQualif ( [ x0, x1] )
89
89
}
90
90
91
91
fn zip < U > ( self , other : PerQualif < U > ) -> PerQualif < ( T , U ) > {
92
- let [ x0, x1, x2 , x3 ] = self . 0 ;
93
- let [ y0, y1, y2 , y3 ] = other. 0 ;
94
- PerQualif ( [ ( x0, y0) , ( x1, y1) , ( x2 , y2 ) , ( x3 , y3 ) ] )
92
+ let [ x0, x1] = self . 0 ;
93
+ let [ y0, y1] = other. 0 ;
94
+ PerQualif ( [ ( x0, y0) , ( x1, y1) ] )
95
95
}
96
96
}
97
97
@@ -427,195 +427,6 @@ impl Qualif for NeedsDrop {
427
427
}
428
428
}
429
429
430
- /// Not promotable at all - non-`const fn` calls, `asm!`,
431
- /// pointer comparisons, ptr-to-int casts, etc.
432
- /// Inside a const context all constness rules apply, so promotion simply has to follow the regular
433
- /// constant rules (modulo interior mutability or `Drop` rules which are handled `HasMutInterior`
434
- /// and `NeedsDrop` respectively). Basically this duplicates the checks that the const-checking
435
- /// visitor enforces by emitting errors when working in const context.
436
- struct IsNotPromotable ;
437
-
438
- impl Qualif for IsNotPromotable {
439
- const IDX : usize = 2 ;
440
-
441
- fn in_static ( cx : & ConstCx < ' _ , ' tcx > , static_ : & Static < ' tcx > ) -> bool {
442
- match static_. kind {
443
- StaticKind :: Promoted ( _, _) => unreachable ! ( ) ,
444
- StaticKind :: Static => {
445
- // Only allow statics (not consts) to refer to other statics.
446
- // FIXME(eddyb) does this matter at all for promotion?
447
- let allowed = cx. mode == Mode :: Static || cx. mode == Mode :: StaticMut ;
448
-
449
- !allowed ||
450
- cx. tcx . get_attrs ( static_. def_id ) . iter ( ) . any (
451
- |attr| attr. check_name ( sym:: thread_local)
452
- )
453
- }
454
- }
455
- }
456
-
457
- fn in_projection (
458
- cx : & ConstCx < ' _ , ' tcx > ,
459
- place : PlaceRef < ' _ , ' tcx > ,
460
- ) -> bool {
461
- if let [ proj_base @ .., elem] = place. projection {
462
- match elem {
463
- ProjectionElem :: Deref |
464
- ProjectionElem :: Downcast ( ..) => return true ,
465
-
466
- ProjectionElem :: ConstantIndex { ..} |
467
- ProjectionElem :: Subslice { ..} |
468
- ProjectionElem :: Index ( _) => { }
469
-
470
- ProjectionElem :: Field ( ..) => {
471
- if cx. mode == Mode :: NonConstFn {
472
- let base_ty = Place :: ty_from ( place. base , proj_base, cx. body , cx. tcx ) . ty ;
473
- if let Some ( def) = base_ty. ty_adt_def ( ) {
474
- // No promotion of union field accesses.
475
- if def. is_union ( ) {
476
- return true ;
477
- }
478
- }
479
- }
480
- }
481
- }
482
-
483
- Self :: in_projection_structurally ( cx, place)
484
- } else {
485
- bug ! ( "This should be called if projection is not empty" ) ;
486
- }
487
- }
488
-
489
- fn in_rvalue ( cx : & ConstCx < ' _ , ' tcx > , rvalue : & Rvalue < ' tcx > ) -> bool {
490
- match * rvalue {
491
- Rvalue :: Cast ( CastKind :: Misc , ref operand, cast_ty) if cx. mode == Mode :: NonConstFn => {
492
- let operand_ty = operand. ty ( cx. body , cx. tcx ) ;
493
- let cast_in = CastTy :: from_ty ( operand_ty) . expect ( "bad input type for cast" ) ;
494
- let cast_out = CastTy :: from_ty ( cast_ty) . expect ( "bad output type for cast" ) ;
495
- match ( cast_in, cast_out) {
496
- ( CastTy :: Ptr ( _) , CastTy :: Int ( _) ) |
497
- ( CastTy :: FnPtr , CastTy :: Int ( _) ) => {
498
- // in normal functions, mark such casts as not promotable
499
- return true ;
500
- }
501
- _ => { }
502
- }
503
- }
504
-
505
- Rvalue :: BinaryOp ( op, ref lhs, _) if cx. mode == Mode :: NonConstFn => {
506
- if let ty:: RawPtr ( _) | ty:: FnPtr ( ..) = lhs. ty ( cx. body , cx. tcx ) . kind {
507
- assert ! ( op == BinOp :: Eq || op == BinOp :: Ne ||
508
- op == BinOp :: Le || op == BinOp :: Lt ||
509
- op == BinOp :: Ge || op == BinOp :: Gt ||
510
- op == BinOp :: Offset ) ;
511
-
512
- // raw pointer operations are not allowed inside promoteds
513
- return true ;
514
- }
515
- }
516
-
517
- Rvalue :: NullaryOp ( NullOp :: Box , _) => return true ,
518
-
519
- _ => { }
520
- }
521
-
522
- Self :: in_rvalue_structurally ( cx, rvalue)
523
- }
524
-
525
- fn in_call (
526
- cx : & ConstCx < ' _ , ' tcx > ,
527
- callee : & Operand < ' tcx > ,
528
- args : & [ Operand < ' tcx > ] ,
529
- _return_ty : Ty < ' tcx > ,
530
- ) -> bool {
531
- let fn_ty = callee. ty ( cx. body , cx. tcx ) ;
532
- match fn_ty. kind {
533
- ty:: FnDef ( def_id, _) => {
534
- match cx. tcx . fn_sig ( def_id) . abi ( ) {
535
- Abi :: RustIntrinsic |
536
- Abi :: PlatformIntrinsic => {
537
- assert ! ( !cx. tcx. is_const_fn( def_id) ) ;
538
- match & * cx. tcx . item_name ( def_id) . as_str ( ) {
539
- | "size_of"
540
- | "min_align_of"
541
- | "needs_drop"
542
- | "type_id"
543
- | "bswap"
544
- | "bitreverse"
545
- | "ctpop"
546
- | "cttz"
547
- | "cttz_nonzero"
548
- | "ctlz"
549
- | "ctlz_nonzero"
550
- | "wrapping_add"
551
- | "wrapping_sub"
552
- | "wrapping_mul"
553
- | "unchecked_shl"
554
- | "unchecked_shr"
555
- | "rotate_left"
556
- | "rotate_right"
557
- | "add_with_overflow"
558
- | "sub_with_overflow"
559
- | "mul_with_overflow"
560
- | "saturating_add"
561
- | "saturating_sub"
562
- | "transmute"
563
- | "simd_insert"
564
- | "simd_extract"
565
- | "ptr_offset_from"
566
- => return true ,
567
-
568
- _ => { }
569
- }
570
- }
571
- _ => {
572
- let is_const_fn =
573
- cx. tcx . is_const_fn ( def_id) ||
574
- cx. tcx . is_unstable_const_fn ( def_id) . is_some ( ) ||
575
- cx. is_const_panic_fn ( def_id) ;
576
- if !is_const_fn {
577
- return true ;
578
- }
579
- }
580
- }
581
- }
582
- _ => return true ,
583
- }
584
-
585
- Self :: in_operand ( cx, callee) || args. iter ( ) . any ( |arg| Self :: in_operand ( cx, arg) )
586
- }
587
- }
588
-
589
- /// Refers to temporaries which cannot be promoted *implicitly*.
590
- /// Explicit promotion happens e.g. for constant arguments declared via `rustc_args_required_const`.
591
- /// Implicit promotion has almost the same rules, except that disallows `const fn` except for
592
- /// those marked `#[rustc_promotable]`. This is to avoid changing a legitimate run-time operation
593
- /// into a failing compile-time operation e.g. due to addresses being compared inside the function.
594
- struct IsNotImplicitlyPromotable ;
595
-
596
- impl Qualif for IsNotImplicitlyPromotable {
597
- const IDX : usize = 3 ;
598
-
599
- fn in_call (
600
- cx : & ConstCx < ' _ , ' tcx > ,
601
- callee : & Operand < ' tcx > ,
602
- args : & [ Operand < ' tcx > ] ,
603
- _return_ty : Ty < ' tcx > ,
604
- ) -> bool {
605
- if cx. mode == Mode :: NonConstFn {
606
- if let ty:: FnDef ( def_id, _) = callee. ty ( cx. body , cx. tcx ) . kind {
607
- // Never promote runtime `const fn` calls of
608
- // functions without `#[rustc_promotable]`.
609
- if !cx. tcx . is_promotable_const_fn ( def_id) {
610
- return true ;
611
- }
612
- }
613
- }
614
-
615
- Self :: in_operand ( cx, callee) || args. iter ( ) . any ( |arg| Self :: in_operand ( cx, arg) )
616
- }
617
- }
618
-
619
430
// Ensure the `IDX` values are sequential (`0..QUALIF_COUNT`).
620
431
macro_rules! static_assert_seq_qualifs {
621
432
( $i: expr => $first: ident $( , $rest: ident) * ) => {
@@ -630,35 +441,28 @@ macro_rules! static_assert_seq_qualifs {
630
441
} ;
631
442
}
632
443
static_assert_seq_qualifs ! (
633
- 0 => HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
444
+ 0 => HasMutInterior , NeedsDrop
634
445
) ;
635
446
636
447
impl ConstCx < ' _ , ' tcx > {
637
448
fn qualifs_in_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> PerQualif < bool > {
638
449
let mut qualifs = PerQualif :: default ( ) ;
639
450
qualifs[ HasMutInterior ] = HasMutInterior :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
640
451
qualifs[ NeedsDrop ] = NeedsDrop :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
641
- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
642
- qualifs[ IsNotImplicitlyPromotable ] =
643
- IsNotImplicitlyPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
644
452
qualifs
645
453
}
646
454
647
455
fn qualifs_in_local ( & self , local : Local ) -> PerQualif < bool > {
648
456
let mut qualifs = PerQualif :: default ( ) ;
649
457
qualifs[ HasMutInterior ] = HasMutInterior :: in_local ( self , local) ;
650
458
qualifs[ NeedsDrop ] = NeedsDrop :: in_local ( self , local) ;
651
- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_local ( self , local) ;
652
- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_local ( self , local) ;
653
459
qualifs
654
460
}
655
461
656
462
fn qualifs_in_value ( & self , source : ValueSource < ' _ , ' tcx > ) -> PerQualif < bool > {
657
463
let mut qualifs = PerQualif :: default ( ) ;
658
464
qualifs[ HasMutInterior ] = HasMutInterior :: in_value ( self , source) ;
659
465
qualifs[ NeedsDrop ] = NeedsDrop :: in_value ( self , source) ;
660
- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_value ( self , source) ;
661
- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_value ( self , source) ;
662
466
qualifs
663
467
}
664
468
}
@@ -729,14 +533,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
729
533
}
730
534
}
731
535
}
732
- if !temps[ local] . is_promotable ( ) {
733
- cx. per_local [ IsNotPromotable ] . insert ( local) ;
734
- }
735
- if let LocalKind :: Var = body. local_kind ( local) {
736
- // Sanity check to prevent implicit and explicit promotion of
737
- // named locals
738
- assert ! ( cx. per_local[ IsNotPromotable ] . contains( local) ) ;
739
- }
740
536
}
741
537
742
538
Checker {
@@ -795,11 +591,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
795
591
// the borrowed place is disallowed from being borrowed,
796
592
// due to either a mutable borrow (with some exceptions),
797
593
// or an shared borrow of a value with interior mutability.
798
- // Then `HasMutInterior` is replaced with `IsNotPromotable`,
594
+ // Then `HasMutInterior` is cleared
799
595
// to avoid duplicate errors (e.g. from reborrowing).
800
596
if qualifs[ HasMutInterior ] {
801
597
qualifs[ HasMutInterior ] = false ;
802
- qualifs[ IsNotPromotable ] = true ;
803
598
804
599
debug ! ( "suppress_errors: {}" , self . suppress_errors) ;
805
600
if self . mode . requires_const_checking ( ) && !self . suppress_errors {
@@ -884,18 +679,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
884
679
per_local. insert ( index) ;
885
680
}
886
681
}
887
-
888
- // Ensure the `IsNotPromotable` qualification is preserved.
889
- // NOTE(eddyb) this is actually unnecessary right now, as
890
- // we never replace the local's qualif, but we might in
891
- // the future, and so it serves to catch changes that unset
892
- // important bits (in which case, asserting `contains` could
893
- // be replaced with calling `insert` to re-set the bit).
894
- if kind == LocalKind :: Temp {
895
- if !self . temp_promotion_state [ index] . is_promotable ( ) {
896
- assert ! ( self . cx. per_local[ IsNotPromotable ] . contains( index) ) ;
897
- }
898
- }
899
682
}
900
683
901
684
/// Check a whole const, static initializer or const fn.
@@ -1041,14 +824,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
1041
824
}
1042
825
}
1043
826
1044
- let mut qualifs = self . qualifs_in_local ( RETURN_PLACE ) ;
1045
-
1046
- // Account for errors in consts by using the
1047
- // conservative type qualification instead.
1048
- if qualifs[ IsNotPromotable ] {
1049
- qualifs = self . qualifs_in_any_value_of_ty ( body. return_ty ( ) ) ;
1050
- }
1051
-
827
+ let qualifs = self . qualifs_in_local ( RETURN_PLACE ) ;
1052
828
( qualifs. encode_to_bits ( ) , self . tcx . arena . alloc ( promoted_temps) )
1053
829
}
1054
830
}
@@ -1577,7 +1353,7 @@ pub fn provide(providers: &mut Providers<'_>) {
1577
1353
1578
1354
// FIXME(eddyb) this is only left around for the validation logic
1579
1355
// in `promote_consts`, see the comment in `validate_operand`.
1580
- pub ( super ) const QUALIF_ERROR_BIT : u8 = 1 << IsNotPromotable :: IDX ;
1356
+ pub ( super ) const QUALIF_ERROR_BIT : u8 = 1 << 2 ;
1581
1357
1582
1358
fn mir_const_qualif ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> ( u8 , & BitSet < Local > ) {
1583
1359
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value
0 commit comments