diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 6dbba274360..478159147ac 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -58,6 +58,9 @@ enum QueryModifier { /// Use a separate query provider for local and extern crates SeparateProvideExtern(Ident), + + /// Always remap the ParamEnv's constness before hashing and passing to the query provider + RemapEnvConstness(Ident), } impl Parse for QueryModifier { @@ -123,6 +126,8 @@ impl Parse for QueryModifier { Ok(QueryModifier::EvalAlways(modifier)) } else if modifier == "separate_provide_extern" { Ok(QueryModifier::SeparateProvideExtern(modifier)) + } else if modifier == "remap_env_constness" { + Ok(QueryModifier::RemapEnvConstness(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -222,6 +227,9 @@ struct QueryModifiers { /// Use a separate query provider for local and extern crates separate_provide_extern: Option, + + /// Always remap the ParamEnv's constness before hashing. + remap_env_constness: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -236,6 +244,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut anon = None; let mut eval_always = None; let mut separate_provide_extern = None; + let mut remap_env_constness = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -335,6 +344,12 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } separate_provide_extern = Some(ident); } + QueryModifier::RemapEnvConstness(ident) => { + if remap_env_constness.is_some() { + panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name); + } + remap_env_constness = Some(ident) + } } } let desc = desc.unwrap_or_else(|| { @@ -351,6 +366,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { anon, eval_always, separate_provide_extern, + remap_env_constness, } } @@ -485,6 +501,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { attributes.push(quote! { (#separate_provide_extern) }); } + // Pass on the remap_env_constness modifier + if let Some(remap_env_constness) = &modifiers.remap_env_constness { + attributes.push(quote! { (#remap_env_constness) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8667a6bea11..61cbb79602c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -880,6 +880,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, ConstAlloc<'tcx>> ) -> Option> { desc { "destructure constant" } + remap_env_constness } /// Destructure a constant ADT or array into its variant index and its @@ -888,6 +889,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> mir::DestructuredConst<'tcx> { desc { "destructure constant" } + remap_env_constness } /// Dereference a constant reference or raw pointer and turn the result into a constant @@ -896,6 +898,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> &'tcx ty::Const<'tcx> { desc { "deref constant" } + remap_env_constness } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1100,26 +1103,32 @@ rustc_queries! { /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } + remap_env_constness } /// Query backing `TyS::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } + remap_env_constness } /// Query backing `TyS::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } + remap_env_constness } /// Query backing `TyS::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } + remap_env_constness } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } + remap_env_constness } /// Query backing `TyS::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } + remap_env_constness } /// Query backing `TyS::is_structural_eq_shallow`. @@ -1158,6 +1167,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result, ty::layout::LayoutError<'tcx>> { desc { "computing layout of `{}`", key.value } + remap_env_constness } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. @@ -1168,6 +1178,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } + remap_env_constness } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1179,6 +1190,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } + remap_env_constness } query dylib_dependency_formats(_: CrateNum) @@ -1463,6 +1475,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> ty::inhabitedness::DefIdForest { desc { "computing the inhabitedness of `{:?}`", key } + remap_env_constness } query dep_kind(_: CrateNum) -> CrateDepKind { @@ -1654,6 +1667,7 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> ) -> GenericArg<'tcx> { desc { "normalizing `{}`", goal.value } + remap_env_constness } /// Do not call this query directly: invoke `normalize_erasing_regions` instead. @@ -1661,6 +1675,7 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> mir::ConstantKind<'tcx> { desc { "normalizing `{}`", goal.value } + remap_env_constness } /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. @@ -1668,6 +1683,7 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. @@ -1675,6 +1691,7 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } query implied_outlives_bounds( @@ -1836,6 +1853,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> ) -> Result>, ErrorReported> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } + remap_env_constness } query resolve_instance_of_const_arg( @@ -1845,6 +1863,7 @@ rustc_queries! { "resolving instance of the const argument `{}`", ty::Instance::new(key.value.0.to_def_id(), key.value.2), } + remap_env_constness } query normalize_opaque_types(key: &'tcx ty::List>) -> &'tcx ty::List> { @@ -1859,6 +1878,7 @@ rustc_queries! { /// size, to account for partial initialisation. See #49298 for details.) query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "conservatively checking if {:?} is privately uninhabited", key } + remap_env_constness } query limits(key: ()) -> Limits { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8d277240e61..a6d083101a0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1435,6 +1435,12 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { (self.param_env, self.value) } + + #[inline] + pub fn without_const(mut self) -> Self { + self.param_env = self.param_env.without_const(); + self + } } impl<'a, 'tcx, T> HashStable> for ParamEnvAnd<'tcx, T> diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 34f80627197..f18517eee04 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -156,6 +156,16 @@ macro_rules! separate_provide_extern_default { }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -202,6 +212,8 @@ macro_rules! define_callbacks { #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); let lookup = match cached { @@ -229,6 +241,8 @@ macro_rules! define_callbacks { pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx> { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone); let lookup = match cached { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 81a36e0d59e..2854ba5158b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -231,6 +231,16 @@ macro_rules! get_provider { }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* @@ -247,6 +257,7 @@ macro_rules! define_queries { // Create an eponymous constructor for each query. $(#[allow(nonstandard_style)] $(#[$attr])* pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame { + opt_remap_env_constness!([$($modifiers)*][key]); let kind = dep_graph::DepKind::$name; let name = stringify!($name); // Disable visible paths printing for performance reasons. @@ -521,6 +532,7 @@ macro_rules! define_queries_struct { lookup: QueryLookup, mode: QueryMode, ) -> Option> { + opt_remap_env_constness!([$($modifiers)*][key]); let qcx = QueryCtxt { tcx, queries: self }; get_query::, _>(qcx, span, key, lookup, mode) })*