From 47b8d26eff2993486f97f00b4e5d48fa5687ba0a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 19 Jun 2022 09:44:23 +0200 Subject: [PATCH] Use `ensure` for `UnusedBrokenConst`. --- compiler/rustc_lint/src/builtin.rs | 6 ++-- .../rustc_middle/src/mir/interpret/queries.rs | 35 ++++++++++++++++++- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7cf447a1419..8266f1566c4 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1610,13 +1610,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst { hir::ItemKind::Const(_, body_id) => { let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id(); // trigger the query once for all constants since that will already report the errors - // FIXME: Use ensure here - let _ = cx.tcx.const_eval_poly(def_id); + cx.tcx.ensure().const_eval_poly(def_id); } hir::ItemKind::Static(_, _, body_id) => { let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id(); - // FIXME: Use ensure here - let _ = cx.tcx.eval_static_initializer(def_id); + cx.tcx.ensure().eval_static_initializer(def_id); } _ => {} } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 5f32f0d5e89..4895b53bb26 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -3,7 +3,7 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId} use crate::mir; use crate::ty::fold::TypeFoldable; use crate::ty::subst::InternalSubsts; -use crate::ty::{self, query::TyCtxtAt, TyCtxt}; +use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; @@ -171,6 +171,39 @@ impl<'tcx> TyCtxtAt<'tcx> { } } +impl<'tcx> TyCtxtEnsure<'tcx> { + /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts + /// that can't take any generic arguments like statics, const items or enum discriminants. If a + /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned. + #[instrument(skip(self), level = "debug")] + pub fn const_eval_poly(self, def_id: DefId) { + // In some situations def_id will have substitutions within scope, but they aren't allowed + // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions + // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are + // encountered. + let substs = InternalSubsts::identity_for_item(self.tcx, def_id); + let instance = ty::Instance::new(def_id, substs); + let cid = GlobalId { instance, promoted: None }; + let param_env = + self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); + // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should + // improve caching of queries. + let inputs = self.tcx.erase_regions(param_env.and(cid)); + self.eval_to_const_value_raw(inputs) + } + + /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + pub fn eval_static_initializer(self, def_id: DefId) { + trace!("eval_static_initializer: Need to compute {:?}", def_id); + assert!(self.tcx.is_static(def_id)); + let instance = ty::Instance::mono(self.tcx, def_id); + let gid = GlobalId { instance, promoted: None }; + let param_env = ty::ParamEnv::reveal_all().with_const(); + trace!("eval_to_allocation: Need to compute {:?}", gid); + self.eval_to_allocation_raw(param_env.and(gid)) + } +} + impl<'tcx> TyCtxt<'tcx> { /// Destructure a type-level constant ADT or array into its variant index and its field values. /// Panics if the destructuring fails, use `try_destructure_const` for fallible version.