diff options
| author | Oli Scherer <github35764891676564198441@oli-obk.de> | 2021-03-30 14:26:40 +0000 |
|---|---|---|
| committer | Oli Scherer <github35764891676564198441@oli-obk.de> | 2021-03-31 10:40:42 +0000 |
| commit | dbacfbc3681622d634233bcf36504ec898f91818 (patch) | |
| tree | 5320c2401ab3f6f60766e029add981d33cb221a0 /compiler | |
| parent | c7c39ce6d07e4d33dc25e07c43f0139c0634b7eb (diff) | |
Add a new normalization query just for mir constants
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_infer/src/infer/resolve.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/type_foldable.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/erase_regions.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/fold.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/normalize_erasing_regions.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/subst.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/monomorphize/collector.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/util/pretty.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/src/keys.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/query/normalize.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_traits/src/normalize_erasing_regions.rs | 27 |
13 files changed, 114 insertions, 12 deletions
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index d72be0134fb..48b8ee17594 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,5 +1,6 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; +use rustc_middle::mir; use rustc_middle::ty::fold::{TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; @@ -46,6 +47,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { ct.super_fold_with(self) } } + + fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + constant.super_fold_with(self) + } } /// The opportunistic region resolver opportunistically resolves regions diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 807d6394800..5b637a39d17 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2410,7 +2410,8 @@ pub struct Constant<'tcx> { pub literal: ConstantKind<'tcx>, } -#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Lift)] pub enum ConstantKind<'tcx> { /// This constant came from the type system Ty(&'tcx ty::Const<'tcx>), @@ -2709,7 +2710,13 @@ impl<'tcx> Display for Constant<'tcx> { ty::FnDef(..) => {} _ => write!(fmt, "const ")?, } - match self.literal { + Display::fmt(&self.literal, fmt) + } +} + +impl<'tcx> Display for ConstantKind<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + match *self { ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index cb599277270..ceed4fd2467 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -348,6 +348,10 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + folder.fold_mir_const(self) + } + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { match self { ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fbd5af9d0a9..732df8bb6c5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1482,6 +1482,13 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } + /// Do not call this query directly: invoke `normalize_erasing_regions` instead. + query normalize_mir_const_after_erasing_regions( + goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + ) -> mir::ConstantKind<'tcx> { + desc { "normalizing `{}`", goal.value } + } + query implied_outlives_bounds( goal: CanonicalTyGoal<'tcx> ) -> Result< diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 4412ba9408c..468e433ecd6 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -1,3 +1,4 @@ +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::{self, Ty, TyCtxt, TypeFlags}; @@ -65,4 +66,8 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { _ => self.tcx.lifetimes.re_erased, } } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a6a1d1f73bb..029d3e1f237 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -30,6 +30,7 @@ //! //! These methods return true to indicate that the visitor has found what it is //! looking for, and does not need to visit anything else. +use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -179,6 +180,10 @@ pub trait TypeFolder<'tcx>: Sized { fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { c.super_fold_with(self) } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + bug!("most type folders should not be folding MIR datastructures: {:?}", c) + } } pub trait TypeVisitor<'tcx>: Sized { diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 9d97815a5f1..2a8502cab41 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -7,6 +7,7 @@ //! `normalize_generic_arg_after_erasing_regions` query for each type //! or constant found within. (This underlying query is what is cached.) +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; @@ -101,4 +102,9 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { let arg = self.param_env.and(c.into()); self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + let arg = self.param_env.and(c); + self.tcx.normalize_mir_const_after_erasing_regions(arg) + } } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 5d1b976ae97..becc09a4ce0 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -1,5 +1,6 @@ // Type substitutions. +use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; @@ -503,6 +504,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { c.super_fold_with(self) } } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } impl<'a, 'tcx> SubstFolder<'a, 'tcx> { diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 5cc1d7082d1..fd5dbfb186e 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -184,7 +184,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; @@ -193,6 +192,7 @@ use rustc_middle::mir::{self, Local, Location}; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; use rustc_session::config::EntryFnType; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use smallvec::SmallVec; @@ -638,6 +638,35 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.super_rvalue(rvalue, location); } + /// This does not walk the constant, as it has been handled entirely here and trying + /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily + /// work, as some constants cannot be represented in the type system. + fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) { + let literal = self.monomorphize(constant.literal); + let val = match literal { + mir::ConstantKind::Val(val, _) => val, + mir::ConstantKind::Ty(ct) => match ct.val { + ty::ConstKind::Value(val) => val, + ty::ConstKind::Unevaluated(ct) => { + let param_env = ty::ParamEnv::reveal_all(); + match self.tcx.const_eval_resolve(param_env, ct, None) { + // The `monomorphize` call should have evaluated that constant already. + Ok(val) => val, + Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => return, + Err(ErrorHandled::TooGeneric) => span_bug!( + self.body.source_info(location).span, + "collection encountered polymorphic constant: {:?}", + literal + ), + } + } + _ => return, + }, + }; + collect_const_value(self.tcx, val, self.output); + self.visit_ty(literal.ty(), TyContext::Location(location)); + } + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 8fa44e4ded3..3b88aec16b2 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -452,7 +452,11 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { match literal { ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), ConstantKind::Val(val, ty) => { - self.push(&format!("+ literal: {:?}, {}", val, ty)) + // To keep the diffs small, we render this almost like we render ty::Const + self.push(&format!( + "+ literal: Const {{ ty: {}, val: Value({:?}) }}", + ty, val + )) } } } diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index e467f419863..1fdb37398f9 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -255,6 +255,15 @@ impl<'tcx> Key for GenericArg<'tcx> { } } +impl<'tcx> Key for mir::ConstantKind<'tcx> { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for &'tcx ty::Const<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index c908e1418c1..eb7ea8715c2 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -10,6 +10,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; +use rustc_middle::mir; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -214,4 +215,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let constant = constant.super_fold_with(self); constant.eval(self.infcx.tcx, self.param_env) } + + fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + constant.super_fold_with(self) + } } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 1213e553908..5ad0684fe6e 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,24 +1,35 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable}; use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers) { - *p = Providers { normalize_generic_arg_after_erasing_regions, ..*p }; + *p = Providers { + normalize_generic_arg_after_erasing_regions: |tcx, goal| { + debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); + + tcx.sess + .perf_stats + .normalize_generic_arg_after_erasing_regions + .fetch_add(1, Ordering::Relaxed); + normalize_after_erasing_regions(tcx, goal) + }, + normalize_mir_const_after_erasing_regions: |tcx, goal| { + normalize_after_erasing_regions(tcx, goal) + }, + ..*p + }; } -fn normalize_generic_arg_after_erasing_regions<'tcx>( +#[instrument(level = "debug", skip(tcx))] +fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>, -) -> GenericArg<'tcx> { - debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); - + goal: ParamEnvAnd<'tcx, T>, +) -> T { let ParamEnvAnd { param_env, value } = goal; - tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).normalize(value) { |
