about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs143
1 files changed, 12 insertions, 131 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 73471bab016..44d96ef1084 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -6,7 +6,6 @@
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_target::spec::abi::Abi;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -20,7 +19,6 @@ use rustc::mir::traversal::ReversePostorder;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::middle::lang_items;
 use rustc::session::config::nightly_options;
-use syntax::ast::LitKind;
 use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::symbol::sym;
 use syntax_pos::{Span, DUMMY_SP};
@@ -678,7 +676,6 @@ struct Checker<'a, 'tcx> {
     rpo: ReversePostorder<'a, 'tcx>,
 
     temp_promotion_state: IndexVec<Local, TempState>,
-    promotion_candidates: Vec<Candidate>,
     unchecked_promotion_candidates: Vec<Candidate>,
 
     /// If `true`, do not emit errors to the user, merely collect them in `errors`.
@@ -748,7 +745,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
             def_id,
             rpo,
             temp_promotion_state: temps,
-            promotion_candidates: vec![],
             unchecked_promotion_candidates,
             errors: vec![],
             suppress_errors: false,
@@ -794,7 +790,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
         let mut qualifs = self.qualifs_in_value(source);
 
         match source {
-            ValueSource::Rvalue(&Rvalue::Ref(_, kind, ref place)) => {
+            ValueSource::Rvalue(&Rvalue::Ref(_, kind, _)) => {
                 // Getting `true` from `HasMutInterior::in_rvalue` means
                 // the borrowed place is disallowed from being borrowed,
                 // due to either a mutable borrow (with some exceptions),
@@ -833,57 +829,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                             }
                         }
                     }
-                } else if let BorrowKind::Mut { .. } | BorrowKind::Shared = kind {
-                    // Don't promote BorrowKind::Shallow borrows, as they don't
-                    // reach codegen.
-                    // FIXME(eddyb) the two other kinds of borrow (`Shallow` and `Unique`)
-                    // aren't promoted here but *could* be promoted as part of a larger
-                    // value because `IsNotPromotable` isn't being set for them,
-                    // need to figure out what is the intended behavior.
-
-                    // We might have a candidate for promotion.
-                    let candidate = Candidate::Ref(location);
-                    // Start by traversing to the "base", with non-deref projections removed.
-                    let deref_proj =
-                        place.projection.iter().rev().find(|&elem| *elem == ProjectionElem::Deref);
-
-                    debug!(
-                        "qualify_consts: promotion candidate: place={:?} {:?}",
-                        place.base, deref_proj
-                    );
-                    // We can only promote interior borrows of promotable temps (non-temps
-                    // don't get promoted anyway).
-                    // (If we bailed out of the loop due to a `Deref` above, we will definitely
-                    // not enter the conditional here.)
-                    if let (PlaceBase::Local(local), None) = (&place.base, deref_proj) {
-                        if self.body.local_kind(*local) == LocalKind::Temp {
-                            debug!("qualify_consts: promotion candidate: local={:?}", local);
-                            // The borrowed place doesn't have `HasMutInterior`
-                            // (from `in_rvalue`), so we can safely ignore
-                            // `HasMutInterior` from the local's qualifications.
-                            // This allows borrowing fields which don't have
-                            // `HasMutInterior`, from a type that does, e.g.:
-                            // `let _: &'static _ = &(Cell::new(1), 2).1;`
-                            let mut local_qualifs = self.qualifs_in_local(*local);
-                            // Any qualifications, except HasMutInterior (see above), disqualify
-                            // from promotion.
-                            // This is, in particular, the "implicit promotion" version of
-                            // the check making sure that we don't run drop glue during const-eval.
-                            local_qualifs[HasMutInterior] = false;
-                            if !local_qualifs.0.iter().any(|&qualif| qualif) {
-                                debug!("qualify_consts: promotion candidate: {:?}", candidate);
-                                self.promotion_candidates.push(candidate);
-                            }
-                        }
-                    }
-                }
-            },
-            ValueSource::Rvalue(&Rvalue::Repeat(ref operand, _)) => {
-                debug!("assign: self.cx.mode={:?} self.def_id={:?} location={:?} operand={:?}",
-                       self.cx.mode, self.def_id, location, operand);
-                if self.should_promote_repeat_expression(operand) &&
-                        self.tcx.features().const_in_array_repeat_expressions {
-                    self.promotion_candidates.push(Candidate::Repeat(location));
                 }
             },
             _ => {},
@@ -1047,22 +992,17 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
         // Collect all the temps we need to promote.
         let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len());
 
-        // HACK(eddyb) don't try to validate promotion candidates if any
-        // parts of the control-flow graph were skipped due to an error.
-        let promotion_candidates = if has_controlflow_error {
-            let unleash_miri = self
-                .tcx
-                .sess
-                .opts
-                .debugging_opts
-                .unleash_the_miri_inside_of_you;
-            if !unleash_miri {
-                self.tcx.sess.delay_span_bug(
-                    body.span,
-                    "check_const: expected control-flow error(s)",
-                );
-            }
-            self.promotion_candidates.clone()
+        // HACK: if parts of the control-flow graph were skipped due to an error, don't try to
+        // promote anything, since that can cause errors in a `const` if e.g. rvalue static
+        // promotion is attempted within a loop body.
+        let unleash_miri = self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
+        let promotion_candidates = if has_controlflow_error && !unleash_miri {
+            self.tcx.sess.delay_span_bug(
+                body.span,
+                "check_const: expected control-flow error(s)",
+            );
+
+            vec![]
         } else {
             promote_consts::validate_candidates(
                 self.tcx,
@@ -1111,15 +1051,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
 
         (qualifs.encode_to_bits(), self.tcx.arena.alloc(promoted_temps))
     }
-
-    /// Returns `true` if the operand of a repeat expression is promotable.
-    fn should_promote_repeat_expression(&self, operand: &Operand<'tcx>) -> bool {
-        let not_promotable = IsNotImplicitlyPromotable::in_operand(self, operand) ||
-                             IsNotPromotable::in_operand(self, operand);
-        debug!("should_promote_repeat_expression: operand={:?} not_promotable={:?}",
-               operand, not_promotable);
-        !not_promotable
-    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
@@ -1431,11 +1362,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
             }
 
             let fn_ty = func.ty(self.body, self.tcx);
-            let mut callee_def_id = None;
-            let mut is_shuffle = false;
             match fn_ty.kind {
                 ty::FnDef(def_id, _) => {
-                    callee_def_id = Some(def_id);
                     match self.tcx.fn_sig(def_id).abi() {
                         Abi::RustIntrinsic |
                         Abi::PlatformIntrinsic => {
@@ -1459,10 +1387,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                                     }
                                 }
 
-                                name if name.starts_with("simd_shuffle") => {
-                                    is_shuffle = true;
-                                }
-
                                 // no need to check feature gates, intrinsics are only callable
                                 // from the libstd or with forever unstable feature gates
                                 _ => {}
@@ -1550,36 +1474,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 }
             }
 
-            // No need to do anything in constants and statics, as everything is "constant" anyway
-            // so promotion would be useless.
-            if self.mode != Mode::Static && self.mode != Mode::Const {
-                let constant_args = callee_def_id.and_then(|id| {
-                    args_required_const(self.tcx, id)
-                }).unwrap_or_default();
-                for (i, arg) in args.iter().enumerate() {
-                    if !(is_shuffle && i == 2 || constant_args.contains(&i)) {
-                        continue;
-                    }
-
-                    let candidate = Candidate::Argument { bb: location.block, index: i };
-                    // Since the argument is required to be constant,
-                    // we care about constness, not promotability.
-                    // If we checked for promotability, we'd miss out on
-                    // the results of function calls (which are never promoted
-                    // in runtime code).
-                    // This is not a problem, because the argument explicitly
-                    // requests constness, in contrast to regular promotion
-                    // which happens even without the user requesting it.
-                    //
-                    // `promote_consts` is responsible for emitting the error if
-                    // the argument is not promotable.
-                    if !IsNotPromotable::in_operand(self, arg) {
-                        debug!("visit_terminator_kind: candidate={:?}", candidate);
-                        self.promotion_candidates.push(candidate);
-                    }
-                }
-            }
-
             // Check callee and argument operands.
             self.visit_operand(func, location);
             for arg in args {
@@ -1887,19 +1781,6 @@ fn check_static_is_sync(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, hir_id: HirId)
     });
 }
 
-fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<FxHashSet<usize>> {
-    let attrs = tcx.get_attrs(def_id);
-    let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?;
-    let mut ret = FxHashSet::default();
-    for meta in attr.meta_item_list()? {
-        match meta.literal()?.kind {
-            LitKind::Int(a, _) => { ret.insert(a as usize); }
-            _ => return None,
-        }
-    }
-    Some(ret)
-}
-
 fn validator_mismatch(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,