1#![allow(internal_features)]
5#![feature(min_specialization)]
6#![feature(rustc_attrs)]
7use rustc_data_structures::stable_hasher::HashStable;
10use rustc_data_structures::sync::AtomicU64;
11use rustc_middle::arena::Arena;
12use rustc_middle::dep_graph::{self, DepKind, DepKindStruct, DepNodeIndex};
13use rustc_middle::query::erase::{Erase, erase, restore};
14use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
15use rustc_middle::query::plumbing::{DynamicQuery, QuerySystem, QuerySystemFns};
16use rustc_middle::query::{
17 AsLocalKey, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
18 queries,
19};
20use rustc_middle::ty::TyCtxt;
21use rustc_query_system::dep_graph::SerializedDepNodeIndex;
22use rustc_query_system::ich::StableHashingContext;
23use rustc_query_system::query::{
24 CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryStackDeferred,
25 QueryState, get_query_incr, get_query_non_incr,
26};
27use rustc_query_system::{HandleCycleError, Value};
28use rustc_span::{ErrorGuaranteed, Span};
29
30use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
31use crate::profiling_support::QueryKeyStringCache;
32
33#[macro_use]
34mod plumbing;
35pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all};
36
37mod profiling_support;
38pub use self::profiling_support::alloc_self_profile_query_strings;
39
40struct DynamicConfig<
41 'tcx,
42 C: QueryCache,
43 const ANON: bool,
44 const DEPTH_LIMIT: bool,
45 const FEEDABLE: bool,
46> {
47 dynamic: &'tcx DynamicQuery<'tcx, C>,
48}
49
50impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
51 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
52{
53}
54impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
55 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
56{
57 fn clone(&self) -> Self {
58 *self
59 }
60}
61
62impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
63 QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
64where
65 for<'a> C::Key: HashStable<StableHashingContext<'a>>,
66{
67 type Key = C::Key;
68 type Value = C::Value;
69 type Cache = C;
70
71 #[inline(always)]
72 fn name(self) -> &'static str {
73 self.dynamic.name
74 }
75
76 #[inline(always)]
77 fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
78 (self.dynamic.cache_on_disk)(tcx, key)
79 }
80
81 #[inline(always)]
82 fn query_state<'a>(
83 self,
84 qcx: QueryCtxt<'tcx>,
85 ) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>>
86 where
87 QueryCtxt<'tcx>: 'a,
88 {
89 unsafe {
92 &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
93 .byte_add(self.dynamic.query_state)
94 .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
95 }
96 }
97
98 #[inline(always)]
99 fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
100 where
101 'tcx: 'a,
102 {
103 unsafe {
106 &*(&qcx.tcx.query_system.caches as *const QueryCaches<'tcx>)
107 .byte_add(self.dynamic.query_cache)
108 .cast::<Self::Cache>()
109 }
110 }
111
112 #[inline(always)]
113 fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
114 (self.dynamic.execute_query)(tcx, key)
115 }
116
117 #[inline(always)]
118 fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
119 (self.dynamic.compute)(qcx.tcx, key)
120 }
121
122 #[inline(always)]
123 fn try_load_from_disk(
124 self,
125 qcx: QueryCtxt<'tcx>,
126 key: &Self::Key,
127 prev_index: SerializedDepNodeIndex,
128 index: DepNodeIndex,
129 ) -> Option<Self::Value> {
130 if self.dynamic.can_load_from_disk {
131 (self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
132 } else {
133 None
134 }
135 }
136
137 #[inline]
138 fn loadable_from_disk(
139 self,
140 qcx: QueryCtxt<'tcx>,
141 key: &Self::Key,
142 index: SerializedDepNodeIndex,
143 ) -> bool {
144 (self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
145 }
146
147 fn value_from_cycle_error(
148 self,
149 tcx: TyCtxt<'tcx>,
150 cycle_error: &CycleError,
151 guar: ErrorGuaranteed,
152 ) -> Self::Value {
153 (self.dynamic.value_from_cycle_error)(tcx, cycle_error, guar)
154 }
155
156 #[inline(always)]
157 fn format_value(self) -> fn(&Self::Value) -> String {
158 self.dynamic.format_value
159 }
160
161 #[inline(always)]
162 fn anon(self) -> bool {
163 ANON
164 }
165
166 #[inline(always)]
167 fn eval_always(self) -> bool {
168 self.dynamic.eval_always
169 }
170
171 #[inline(always)]
172 fn depth_limit(self) -> bool {
173 DEPTH_LIMIT
174 }
175
176 #[inline(always)]
177 fn feedable(self) -> bool {
178 FEEDABLE
179 }
180
181 #[inline(always)]
182 fn dep_kind(self) -> DepKind {
183 self.dynamic.dep_kind
184 }
185
186 #[inline(always)]
187 fn handle_cycle_error(self) -> HandleCycleError {
188 self.dynamic.handle_cycle_error
189 }
190
191 #[inline(always)]
192 fn hash_result(self) -> HashResult<Self::Value> {
193 self.dynamic.hash_result
194 }
195}
196
197trait QueryConfigRestored<'tcx> {
200 type RestoredValue;
201 type Config: QueryConfig<QueryCtxt<'tcx>>;
202
203 const NAME: &'static &'static str;
204
205 fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
206 fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
207 -> Self::RestoredValue;
208}
209
210pub fn query_system<'a>(
211 local_providers: Providers,
212 extern_providers: ExternProviders,
213 on_disk_cache: Option<OnDiskCache>,
214 incremental: bool,
215) -> QuerySystem<'a> {
216 QuerySystem {
217 states: Default::default(),
218 arenas: Default::default(),
219 caches: Default::default(),
220 dynamic_queries: dynamic_queries(),
221 on_disk_cache,
222 fns: QuerySystemFns {
223 engine: engine(incremental),
224 local_providers,
225 extern_providers,
226 encode_query_results: encode_all_query_results,
227 try_mark_green,
228 },
229 jobs: AtomicU64::new(1),
230 }
231}
232
233rustc_middle::rustc_with_all_queries! { define_queries! }
234
235pub fn provide(providers: &mut rustc_middle::util::Providers) {
236 providers.hooks.alloc_self_profile_query_strings = alloc_self_profile_query_strings;
237 providers.hooks.query_key_hash_verify_all = query_key_hash_verify_all;
238}