diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/query.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/query.rs | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index ec90590ad..642900d3a 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -15,6 +15,7 @@ use crate::mir::interpret::{ }; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; +use crate::query::Key; use crate::thir; use crate::traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, @@ -27,6 +28,7 @@ use crate::traits::query::{ }; use crate::traits::specialization_graph; use crate::traits::{self, ImplSource}; +use crate::ty::context::TyCtxtFeed; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::TyAndLayout; use crate::ty::subst::{GenericArg, SubstsRef}; @@ -121,10 +123,10 @@ macro_rules! query_helper_param_ty { macro_rules! query_storage { ([][$K:ty, $V:ty]) => { - <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache + <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache }; ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => { - <ArenaCacheSelector<'tcx> as CacheSelector<$K, $V>>::Cache + <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache }; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { query_storage!([$($modifiers)*][$($args)*]) @@ -275,13 +277,16 @@ macro_rules! define_callbacks { impl Default for Providers { fn default() -> Self { + use crate::query::Key; + Providers { $($name: |_, key| bug!( - "`tcx.{}({:?})` is not supported for external or local crate;\n - hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported (likely the local crate).\n + "`tcx.{}({:?})` is not supported for {} crate;\n + hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n If that's not the case, {} was likely never assigned to a provider function.\n", stringify!($name), key, + if key.query_crate_is_local() { "local" } else { "external" }, stringify!($name), ),)* } @@ -323,6 +328,56 @@ macro_rules! define_callbacks { }; } +macro_rules! hash_result { + ([]) => {{ + Some(dep_graph::hash_result) + }}; + ([(no_hash) $($rest:tt)*]) => {{ + None + }}; + ([$other:tt $($modifiers:tt)*]) => { + hash_result!([$($modifiers)*]) + }; +} + +macro_rules! define_feedable { + ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { + $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(#[$attr])* + #[inline(always)] + pub fn $name(self, value: $V) -> query_stored::$name<'tcx> { + let key = self.key().into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + + let tcx = self.tcx; + let cache = &tcx.query_caches.$name; + + let cached = try_get_cached(tcx, cache, &key, copy); + + match cached { + Ok(old) => { + bug!( + "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}", + stringify!($name), + ); + } + Err(()) => (), + } + + let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); + let dep_node_index = tcx.dep_graph.with_feed_task( + dep_node, + tcx, + key, + &value, + hash_result!([$($modifiers)*]), + ); + cache.complete(key, value, dep_node_index) + } + })* + } +} + // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way @@ -336,6 +391,7 @@ macro_rules! define_callbacks { // as they will raise an fatal error on query cycles instead. rustc_query_append! { define_callbacks! } +rustc_feedable_queries! { define_feedable! } mod sealed { use super::{DefId, LocalDefId, OwnerId}; |