1 //! Support for serializing the dep-graph and reloading it.
2
3 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
4 // this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
5 #![feature(const_mut_refs)]
6 #![feature(const_refs_to_cell)]
7 #![feature(min_specialization)]
8 #![feature(never_type)]
9 #![feature(rustc_attrs)]
10 #![recursion_limit = "256"]
11 #![allow(rustc::potential_query_instability, unused_parens)]
12 #![deny(rustc::untranslatable_diagnostic)]
13 #![deny(rustc::diagnostic_outside_of_impl)]
14
15 #[macro_use]
16 extern crate rustc_middle;
17
18 use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
19 use field_offset::offset_of;
20 use rustc_data_structures::stable_hasher::HashStable;
21 use rustc_data_structures::sync::AtomicU64;
22 use rustc_middle::arena::Arena;
23 use rustc_middle::dep_graph::DepNodeIndex;
24 use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
25 use rustc_middle::query::erase::{erase, restore, Erase};
26 use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
27 use rustc_middle::query::plumbing::{
28 DynamicQuery, QueryKeyStringCache, QuerySystem, QuerySystemFns,
29 };
30 use rustc_middle::query::AsLocalKey;
31 use rustc_middle::query::{
32 queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
33 };
34 use rustc_middle::ty::TyCtxt;
35 use rustc_query_system::dep_graph::SerializedDepNodeIndex;
36 use rustc_query_system::ich::StableHashingContext;
37 use rustc_query_system::query::{
38 get_query_incr, get_query_non_incr, HashResult, QueryCache, QueryConfig, QueryInfo, QueryMap,
39 QueryMode, QueryState,
40 };
41 use rustc_query_system::HandleCycleError;
42 use rustc_query_system::Value;
43 use rustc_span::Span;
44
45 #[macro_use]
46 mod plumbing;
47 pub use crate::plumbing::QueryCtxt;
48
49 mod profiling_support;
50 pub use self::profiling_support::alloc_self_profile_query_strings;
51
52 struct DynamicConfig<
53 'tcx,
54 C: QueryCache,
55 const ANON: bool,
56 const DEPTH_LIMIT: bool,
57 const FEEDABLE: bool,
58 > {
59 dynamic: &'tcx DynamicQuery<'tcx, C>,
60 }
61
62 impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
63 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
64 {
65 }
66 impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
67 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
68 {
clone(&self) -> Self69 fn clone(&self) -> Self {
70 DynamicConfig { dynamic: self.dynamic }
71 }
72 }
73
74 impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
75 QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
76 where
77 for<'a> C::Key: HashStable<StableHashingContext<'a>>,
78 {
79 type Key = C::Key;
80 type Value = C::Value;
81 type Cache = C;
82
83 #[inline(always)]
name(self) -> &'static str84 fn name(self) -> &'static str {
85 self.dynamic.name
86 }
87
88 #[inline(always)]
cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool89 fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
90 (self.dynamic.cache_on_disk)(tcx, key)
91 }
92
93 #[inline(always)]
query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, DepKind> where QueryCtxt<'tcx>: 'a,94 fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, DepKind>
95 where
96 QueryCtxt<'tcx>: 'a,
97 {
98 self.dynamic.query_state.apply(&qcx.tcx.query_system.states)
99 }
100
101 #[inline(always)]
query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache where 'tcx: 'a,102 fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
103 where
104 'tcx: 'a,
105 {
106 self.dynamic.query_cache.apply(&qcx.tcx.query_system.caches)
107 }
108
109 #[inline(always)]
execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value110 fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
111 (self.dynamic.execute_query)(tcx, key)
112 }
113
114 #[inline(always)]
compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value115 fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
116 (self.dynamic.compute)(qcx.tcx, key)
117 }
118
119 #[inline(always)]
try_load_from_disk( self, qcx: QueryCtxt<'tcx>, key: &Self::Key, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option<Self::Value>120 fn try_load_from_disk(
121 self,
122 qcx: QueryCtxt<'tcx>,
123 key: &Self::Key,
124 prev_index: SerializedDepNodeIndex,
125 index: DepNodeIndex,
126 ) -> Option<Self::Value> {
127 if self.dynamic.can_load_from_disk {
128 (self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
129 } else {
130 None
131 }
132 }
133
134 #[inline]
loadable_from_disk( self, qcx: QueryCtxt<'tcx>, key: &Self::Key, index: SerializedDepNodeIndex, ) -> bool135 fn loadable_from_disk(
136 self,
137 qcx: QueryCtxt<'tcx>,
138 key: &Self::Key,
139 index: SerializedDepNodeIndex,
140 ) -> bool {
141 (self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
142 }
143
value_from_cycle_error( self, tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>], ) -> Self::Value144 fn value_from_cycle_error(
145 self,
146 tcx: TyCtxt<'tcx>,
147 cycle: &[QueryInfo<DepKind>],
148 ) -> Self::Value {
149 (self.dynamic.value_from_cycle_error)(tcx, cycle)
150 }
151
152 #[inline(always)]
format_value(self) -> fn(&Self::Value) -> String153 fn format_value(self) -> fn(&Self::Value) -> String {
154 self.dynamic.format_value
155 }
156
157 #[inline(always)]
anon(self) -> bool158 fn anon(self) -> bool {
159 ANON
160 }
161
162 #[inline(always)]
eval_always(self) -> bool163 fn eval_always(self) -> bool {
164 self.dynamic.eval_always
165 }
166
167 #[inline(always)]
depth_limit(self) -> bool168 fn depth_limit(self) -> bool {
169 DEPTH_LIMIT
170 }
171
172 #[inline(always)]
feedable(self) -> bool173 fn feedable(self) -> bool {
174 FEEDABLE
175 }
176
177 #[inline(always)]
dep_kind(self) -> DepKind178 fn dep_kind(self) -> DepKind {
179 self.dynamic.dep_kind
180 }
181
182 #[inline(always)]
handle_cycle_error(self) -> HandleCycleError183 fn handle_cycle_error(self) -> HandleCycleError {
184 self.dynamic.handle_cycle_error
185 }
186
187 #[inline(always)]
hash_result(self) -> HashResult<Self::Value>188 fn hash_result(self) -> HashResult<Self::Value> {
189 self.dynamic.hash_result
190 }
191 }
192
193 /// This is implemented per query. It allows restoring query values from their erased state
194 /// and constructing a QueryConfig.
195 trait QueryConfigRestored<'tcx> {
196 type RestoredValue;
197 type Config: QueryConfig<QueryCtxt<'tcx>>;
198
config(tcx: TyCtxt<'tcx>) -> Self::Config199 fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue200 fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
201 -> Self::RestoredValue;
202 }
203
query_system<'tcx>( local_providers: Providers, extern_providers: ExternProviders, on_disk_cache: Option<OnDiskCache<'tcx>>, incremental: bool, ) -> QuerySystem<'tcx>204 pub fn query_system<'tcx>(
205 local_providers: Providers,
206 extern_providers: ExternProviders,
207 on_disk_cache: Option<OnDiskCache<'tcx>>,
208 incremental: bool,
209 ) -> QuerySystem<'tcx> {
210 QuerySystem {
211 states: Default::default(),
212 arenas: Default::default(),
213 caches: Default::default(),
214 dynamic_queries: dynamic_queries(),
215 on_disk_cache,
216 fns: QuerySystemFns {
217 engine: engine(incremental),
218 local_providers,
219 extern_providers,
220 encode_query_results: encode_all_query_results,
221 try_mark_green: try_mark_green,
222 },
223 jobs: AtomicU64::new(1),
224 }
225 }
226
227 rustc_query_append! { define_queries! }
228