66
77use rustc_index:: bit_set:: BitSet ;
88use rustc_index:: vec:: IndexVec ;
9- use rustc_data_structures:: fx:: FxHashSet ;
109use rustc_target:: spec:: abi:: Abi ;
1110use rustc:: hir;
1211use rustc:: hir:: def_id:: DefId ;
@@ -20,7 +19,6 @@ use rustc::mir::traversal::ReversePostorder;
2019use rustc:: mir:: visit:: { PlaceContext , Visitor , MutatingUseContext , NonMutatingUseContext } ;
2120use rustc:: middle:: lang_items;
2221use rustc:: session:: config:: nightly_options;
23- use syntax:: ast:: LitKind ;
2422use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
2523use syntax:: symbol:: sym;
2624use syntax_pos:: { Span , DUMMY_SP } ;
@@ -678,7 +676,6 @@ struct Checker<'a, 'tcx> {
678676 rpo : ReversePostorder < ' a , ' tcx > ,
679677
680678 temp_promotion_state : IndexVec < Local , TempState > ,
681- promotion_candidates : Vec < Candidate > ,
682679 unchecked_promotion_candidates : Vec < Candidate > ,
683680
684681 /// If `true`, do not emit errors to the user, merely collect them in `errors`.
@@ -748,7 +745,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
748745 def_id,
749746 rpo,
750747 temp_promotion_state : temps,
751- promotion_candidates : vec ! [ ] ,
752748 unchecked_promotion_candidates,
753749 errors : vec ! [ ] ,
754750 suppress_errors : false ,
@@ -794,7 +790,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
794790 let mut qualifs = self . qualifs_in_value ( source) ;
795791
796792 match source {
797- ValueSource :: Rvalue ( & Rvalue :: Ref ( _, kind, ref place ) ) => {
793+ ValueSource :: Rvalue ( & Rvalue :: Ref ( _, kind, _ ) ) => {
798794 // Getting `true` from `HasMutInterior::in_rvalue` means
799795 // the borrowed place is disallowed from being borrowed,
800796 // due to either a mutable borrow (with some exceptions),
@@ -833,57 +829,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
833829 }
834830 }
835831 }
836- } else if let BorrowKind :: Mut { .. } | BorrowKind :: Shared = kind {
837- // Don't promote BorrowKind::Shallow borrows, as they don't
838- // reach codegen.
839- // FIXME(eddyb) the two other kinds of borrow (`Shallow` and `Unique`)
840- // aren't promoted here but *could* be promoted as part of a larger
841- // value because `IsNotPromotable` isn't being set for them,
842- // need to figure out what is the intended behavior.
843-
844- // We might have a candidate for promotion.
845- let candidate = Candidate :: Ref ( location) ;
846- // Start by traversing to the "base", with non-deref projections removed.
847- let deref_proj =
848- place. projection . iter ( ) . rev ( ) . find ( |& elem| * elem == ProjectionElem :: Deref ) ;
849-
850- debug ! (
851- "qualify_consts: promotion candidate: place={:?} {:?}" ,
852- place. base, deref_proj
853- ) ;
854- // We can only promote interior borrows of promotable temps (non-temps
855- // don't get promoted anyway).
856- // (If we bailed out of the loop due to a `Deref` above, we will definitely
857- // not enter the conditional here.)
858- if let ( PlaceBase :: Local ( local) , None ) = ( & place. base , deref_proj) {
859- if self . body . local_kind ( * local) == LocalKind :: Temp {
860- debug ! ( "qualify_consts: promotion candidate: local={:?}" , local) ;
861- // The borrowed place doesn't have `HasMutInterior`
862- // (from `in_rvalue`), so we can safely ignore
863- // `HasMutInterior` from the local's qualifications.
864- // This allows borrowing fields which don't have
865- // `HasMutInterior`, from a type that does, e.g.:
866- // `let _: &'static _ = &(Cell::new(1), 2).1;`
867- let mut local_qualifs = self . qualifs_in_local ( * local) ;
868- // Any qualifications, except HasMutInterior (see above), disqualify
869- // from promotion.
870- // This is, in particular, the "implicit promotion" version of
871- // the check making sure that we don't run drop glue during const-eval.
872- local_qualifs[ HasMutInterior ] = false ;
873- if !local_qualifs. 0 . iter ( ) . any ( |& qualif| qualif) {
874- debug ! ( "qualify_consts: promotion candidate: {:?}" , candidate) ;
875- self . promotion_candidates . push ( candidate) ;
876- }
877- }
878- }
879- }
880- } ,
881- ValueSource :: Rvalue ( & Rvalue :: Repeat ( ref operand, _) ) => {
882- debug ! ( "assign: self.cx.mode={:?} self.def_id={:?} location={:?} operand={:?}" ,
883- self . cx. mode, self . def_id, location, operand) ;
884- if self . should_promote_repeat_expression ( operand) &&
885- self . tcx . features ( ) . const_in_array_repeat_expressions {
886- self . promotion_candidates . push ( Candidate :: Repeat ( location) ) ;
887832 }
888833 } ,
889834 _ => { } ,
@@ -1047,22 +992,17 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
1047992 // Collect all the temps we need to promote.
1048993 let mut promoted_temps = BitSet :: new_empty ( self . temp_promotion_state . len ( ) ) ;
1049994
1050- // HACK(eddyb) don't try to validate promotion candidates if any
1051- // parts of the control-flow graph were skipped due to an error.
1052- let promotion_candidates = if has_controlflow_error {
1053- let unleash_miri = self
1054- . tcx
1055- . sess
1056- . opts
1057- . debugging_opts
1058- . unleash_the_miri_inside_of_you ;
1059- if !unleash_miri {
1060- self . tcx . sess . delay_span_bug (
1061- body. span ,
1062- "check_const: expected control-flow error(s)" ,
1063- ) ;
1064- }
1065- self . promotion_candidates . clone ( )
995+ // HACK: if parts of the control-flow graph were skipped due to an error, don't try to
996+ // promote anything, since that can cause errors in a `const` if e.g. rvalue static
997+ // promotion is attempted within a loop body.
998+ let unleash_miri = self . tcx . sess . opts . debugging_opts . unleash_the_miri_inside_of_you ;
999+ let promotion_candidates = if has_controlflow_error && !unleash_miri {
1000+ self . tcx . sess . delay_span_bug (
1001+ body. span ,
1002+ "check_const: expected control-flow error(s)" ,
1003+ ) ;
1004+
1005+ vec ! [ ]
10661006 } else {
10671007 promote_consts:: validate_candidates (
10681008 self . tcx ,
@@ -1111,15 +1051,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
11111051
11121052 ( qualifs. encode_to_bits ( ) , self . tcx . arena . alloc ( promoted_temps) )
11131053 }
1114-
1115- /// Returns `true` if the operand of a repeat expression is promotable.
1116- fn should_promote_repeat_expression ( & self , operand : & Operand < ' tcx > ) -> bool {
1117- let not_promotable = IsNotImplicitlyPromotable :: in_operand ( self , operand) ||
1118- IsNotPromotable :: in_operand ( self , operand) ;
1119- debug ! ( "should_promote_repeat_expression: operand={:?} not_promotable={:?}" ,
1120- operand, not_promotable) ;
1121- !not_promotable
1122- }
11231054}
11241055
11251056impl < ' a , ' tcx > Visitor < ' tcx > for Checker < ' a , ' tcx > {
@@ -1431,11 +1362,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
14311362 }
14321363
14331364 let fn_ty = func. ty ( self . body , self . tcx ) ;
1434- let mut callee_def_id = None ;
1435- let mut is_shuffle = false ;
14361365 match fn_ty. kind {
14371366 ty:: FnDef ( def_id, _) => {
1438- callee_def_id = Some ( def_id) ;
14391367 match self . tcx . fn_sig ( def_id) . abi ( ) {
14401368 Abi :: RustIntrinsic |
14411369 Abi :: PlatformIntrinsic => {
@@ -1459,10 +1387,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
14591387 }
14601388 }
14611389
1462- name if name. starts_with ( "simd_shuffle" ) => {
1463- is_shuffle = true ;
1464- }
1465-
14661390 // no need to check feature gates, intrinsics are only callable
14671391 // from the libstd or with forever unstable feature gates
14681392 _ => { }
@@ -1550,36 +1474,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
15501474 }
15511475 }
15521476
1553- // No need to do anything in constants and statics, as everything is "constant" anyway
1554- // so promotion would be useless.
1555- if self . mode != Mode :: Static && self . mode != Mode :: Const {
1556- let constant_args = callee_def_id. and_then ( |id| {
1557- args_required_const ( self . tcx , id)
1558- } ) . unwrap_or_default ( ) ;
1559- for ( i, arg) in args. iter ( ) . enumerate ( ) {
1560- if !( is_shuffle && i == 2 || constant_args. contains ( & i) ) {
1561- continue ;
1562- }
1563-
1564- let candidate = Candidate :: Argument { bb : location. block , index : i } ;
1565- // Since the argument is required to be constant,
1566- // we care about constness, not promotability.
1567- // If we checked for promotability, we'd miss out on
1568- // the results of function calls (which are never promoted
1569- // in runtime code).
1570- // This is not a problem, because the argument explicitly
1571- // requests constness, in contrast to regular promotion
1572- // which happens even without the user requesting it.
1573- //
1574- // `promote_consts` is responsible for emitting the error if
1575- // the argument is not promotable.
1576- if !IsNotPromotable :: in_operand ( self , arg) {
1577- debug ! ( "visit_terminator_kind: candidate={:?}" , candidate) ;
1578- self . promotion_candidates . push ( candidate) ;
1579- }
1580- }
1581- }
1582-
15831477 // Check callee and argument operands.
15841478 self . visit_operand ( func, location) ;
15851479 for arg in args {
@@ -1887,19 +1781,6 @@ fn check_static_is_sync(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, hir_id: HirId)
18871781 } ) ;
18881782}
18891783
1890- fn args_required_const ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Option < FxHashSet < usize > > {
1891- let attrs = tcx. get_attrs ( def_id) ;
1892- let attr = attrs. iter ( ) . find ( |a| a. check_name ( sym:: rustc_args_required_const) ) ?;
1893- let mut ret = FxHashSet :: default ( ) ;
1894- for meta in attr. meta_item_list ( ) ? {
1895- match meta. literal ( ) ?. kind {
1896- LitKind :: Int ( a, _) => { ret. insert ( a as usize ) ; }
1897- _ => return None ,
1898- }
1899- }
1900- Some ( ret)
1901- }
1902-
19031784fn validator_mismatch (
19041785 tcx : TyCtxt < ' tcx > ,
19051786 body : & Body < ' tcx > ,
0 commit comments