@@ -69,7 +69,7 @@ impl fmt::Display for Mode {
6969 }
7070}
7171
72- const QUALIF_COUNT : usize = 4 ;
72+ const QUALIF_COUNT : usize = 2 ;
7373
7474// FIXME(eddyb) once we can use const generics, replace this array with
7575// something like `IndexVec` but for fixed-size arrays (`IndexArray`?).
@@ -78,20 +78,20 @@ struct PerQualif<T>([T; QUALIF_COUNT]);
7878
7979impl < T : Clone > PerQualif < T > {
8080 fn new ( x : T ) -> Self {
81- PerQualif ( [ x. clone ( ) , x. clone ( ) , x . clone ( ) , x ] )
81+ PerQualif ( [ x. clone ( ) , x] )
8282 }
8383}
8484
8585impl < T > PerQualif < T > {
8686 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] )
8989 }
9090
9191 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) ] )
9595 }
9696}
9797
@@ -427,195 +427,6 @@ impl Qualif for NeedsDrop {
427427 }
428428}
429429
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-
619430// Ensure the `IDX` values are sequential (`0..QUALIF_COUNT`).
620431macro_rules! static_assert_seq_qualifs {
621432 ( $i: expr => $first: ident $( , $rest: ident) * ) => {
@@ -630,35 +441,28 @@ macro_rules! static_assert_seq_qualifs {
630441 } ;
631442}
632443static_assert_seq_qualifs ! (
633- 0 => HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
444+ 0 => HasMutInterior , NeedsDrop
634445) ;
635446
636447impl ConstCx < ' _ , ' tcx > {
637448 fn qualifs_in_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> PerQualif < bool > {
638449 let mut qualifs = PerQualif :: default ( ) ;
639450 qualifs[ HasMutInterior ] = HasMutInterior :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
640451 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 ) ;
644452 qualifs
645453 }
646454
647455 fn qualifs_in_local ( & self , local : Local ) -> PerQualif < bool > {
648456 let mut qualifs = PerQualif :: default ( ) ;
649457 qualifs[ HasMutInterior ] = HasMutInterior :: in_local ( self , local) ;
650458 qualifs[ NeedsDrop ] = NeedsDrop :: in_local ( self , local) ;
651- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_local ( self , local) ;
652- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_local ( self , local) ;
653459 qualifs
654460 }
655461
656462 fn qualifs_in_value ( & self , source : ValueSource < ' _ , ' tcx > ) -> PerQualif < bool > {
657463 let mut qualifs = PerQualif :: default ( ) ;
658464 qualifs[ HasMutInterior ] = HasMutInterior :: in_value ( self , source) ;
659465 qualifs[ NeedsDrop ] = NeedsDrop :: in_value ( self , source) ;
660- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_value ( self , source) ;
661- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_value ( self , source) ;
662466 qualifs
663467 }
664468}
@@ -729,14 +533,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
729533 }
730534 }
731535 }
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- }
740536 }
741537
742538 Checker {
@@ -795,11 +591,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
795591 // the borrowed place is disallowed from being borrowed,
796592 // due to either a mutable borrow (with some exceptions),
797593 // or an shared borrow of a value with interior mutability.
798- // Then `HasMutInterior` is replaced with `IsNotPromotable`,
594+ // Then `HasMutInterior` is cleared
799595 // to avoid duplicate errors (e.g. from reborrowing).
800596 if qualifs[ HasMutInterior ] {
801597 qualifs[ HasMutInterior ] = false ;
802- qualifs[ IsNotPromotable ] = true ;
803598
804599 debug ! ( "suppress_errors: {}" , self . suppress_errors) ;
805600 if self . mode . requires_const_checking ( ) && !self . suppress_errors {
@@ -884,18 +679,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
884679 per_local. insert ( index) ;
885680 }
886681 }
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- }
899682 }
900683
901684 /// Check a whole const, static initializer or const fn.
@@ -1041,14 +824,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
1041824 }
1042825 }
1043826
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 ) ;
1052828 ( qualifs. encode_to_bits ( ) , self . tcx . arena . alloc ( promoted_temps) )
1053829 }
1054830}
@@ -1577,7 +1353,7 @@ pub fn provide(providers: &mut Providers<'_>) {
15771353
15781354// FIXME(eddyb) this is only left around for the validation logic
15791355// 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 ;
15811357
15821358fn mir_const_qualif ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> ( u8 , & BitSet < Local > ) {
15831359 // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
0 commit comments