]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ich/hcx.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / compiler / rustc_middle / src / ich / hcx.rs
CommitLineData
ba9703b0 1use crate::ich;
9fa01778 2use crate::middle::cstore::CrateStore;
dfeec247 3use crate::ty::{fast_reject, TyCtxt};
cc61c64b 4
3dfed10e 5use rustc_ast as ast;
dfeec247 6use rustc_data_structures::fx::{FxHashMap, FxHashSet};
ba9703b0 7use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
60c5eb7d 8use rustc_data_structures::sync::Lrc;
dfeec247 9use rustc_hir as hir;
ba9703b0
XL
10use rustc_hir::def_id::{DefId, LocalDefId};
11use rustc_hir::definitions::{DefPathHash, Definitions};
12use rustc_session::Session;
dfeec247
XL
13use rustc_span::source_map::SourceMap;
14use rustc_span::symbol::Symbol;
5869c6ff 15use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
dfeec247 16
3dfed10e 17use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX};
b7449926 18use smallvec::SmallVec;
dfeec247 19use std::cmp::Ord;
5869c6ff 20use std::thread::LocalKey;
ea8adc8c 21
b7449926 22fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
74b04a01
XL
23 debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty());
24 ich::IGNORED_ATTRIBUTES.iter().copied().collect()
2c00a5a8 25}
cc61c64b
XL
26
27/// This is the context state available during incr. comp. hashing. It contains
e1599b0c
XL
28/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
29/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
30/// things (e.g., each `DefId`/`DefPath` is only hashed once).
ea8adc8c 31#[derive(Clone)]
0531ce1d
XL
32pub struct StableHashingContext<'a> {
33 sess: &'a Session,
34 definitions: &'a Definitions,
35 cstore: &'a dyn CrateStore,
dfeec247 36 pub(super) body_resolver: BodyResolver<'a>,
cc61c64b
XL
37 hash_spans: bool,
38 hash_bodies: bool,
dfeec247 39 pub(super) node_id_hashing_mode: NodeIdHashingMode,
ea8adc8c
XL
40
41 // Very often, we are hashing something that does not need the
e1599b0c 42 // `CachingSourceMapView`, so we initialize it lazily.
b7449926
XL
43 raw_source_map: &'a SourceMap,
44 caching_source_map: Option<CachingSourceMapView<'a>>,
cc61c64b
XL
45}
46
47#[derive(PartialEq, Eq, Clone, Copy)]
48pub enum NodeIdHashingMode {
49 Ignore,
50 HashDefPath,
cc61c64b
XL
51}
52
e1599b0c
XL
53/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`.
54/// We could also just store a plain reference to the `hir::Crate` but we want
ea8adc8c
XL
55/// to avoid that the crate is used to get untracked access to all of the HIR.
56#[derive(Clone, Copy)]
dfeec247 57pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>);
ea8adc8c 58
dc9dc135 59impl<'tcx> BodyResolver<'tcx> {
e1599b0c
XL
60 /// Returns a reference to the `hir::Body` with the given `BodyId`.
61 /// **Does not do any tracking**; use carefully.
dfeec247 62 pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> {
ea8adc8c
XL
63 self.0.body(id)
64 }
65}
cc61c64b 66
0531ce1d 67impl<'a> StableHashingContext<'a> {
e1599b0c
XL
68 /// The `krate` here is only used for mapping `BodyId`s to `Body`s.
69 /// Don't use it for anything else or you'll run the risk of
70 /// leaking data out of the tracking system.
0731742a 71 #[inline]
f035d41b 72 fn new_with_or_without_spans(
dfeec247
XL
73 sess: &'a Session,
74 krate: &'a hir::Crate<'a>,
75 definitions: &'a Definitions,
76 cstore: &'a dyn CrateStore,
f035d41b 77 always_ignore_spans: bool,
dfeec247 78 ) -> Self {
f035d41b
XL
79 let hash_spans_initial =
80 !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
ea8adc8c 81
cc61c64b 82 StableHashingContext {
ea8adc8c
XL
83 sess,
84 body_resolver: BodyResolver(krate),
85 definitions,
86 cstore,
b7449926
XL
87 caching_source_map: None,
88 raw_source_map: sess.source_map(),
cc61c64b
XL
89 hash_spans: hash_spans_initial,
90 hash_bodies: true,
cc61c64b 91 node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
cc61c64b
XL
92 }
93 }
94
f035d41b
XL
95 #[inline]
96 pub fn new(
97 sess: &'a Session,
98 krate: &'a hir::Crate<'a>,
99 definitions: &'a Definitions,
100 cstore: &'a dyn CrateStore,
101 ) -> Self {
102 Self::new_with_or_without_spans(
103 sess,
104 krate,
105 definitions,
106 cstore,
107 /*always_ignore_spans=*/ false,
108 )
109 }
110
111 #[inline]
112 pub fn ignore_spans(
113 sess: &'a Session,
114 krate: &'a hir::Crate<'a>,
115 definitions: &'a Definitions,
116 cstore: &'a dyn CrateStore,
117 ) -> Self {
118 let always_ignore_spans = true;
119 Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans)
120 }
121
ea8adc8c 122 #[inline]
0531ce1d 123 pub fn sess(&self) -> &'a Session {
ea8adc8c
XL
124 self.sess
125 }
126
cc61c64b 127 #[inline]
dfeec247 128 pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, f: F) {
cc61c64b
XL
129 let prev_hash_bodies = self.hash_bodies;
130 self.hash_bodies = hash_bodies;
131 f(self);
132 self.hash_bodies = prev_hash_bodies;
133 }
134
135 #[inline]
dfeec247 136 pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
cc61c64b
XL
137 let prev_hash_spans = self.hash_spans;
138 self.hash_spans = hash_spans;
139 f(self);
140 self.hash_spans = prev_hash_spans;
141 }
142
143 #[inline]
dfeec247
XL
144 pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(
145 &mut self,
146 mode: NodeIdHashingMode,
147 f: F,
148 ) {
cc61c64b
XL
149 let prev = self.node_id_hashing_mode;
150 self.node_id_hashing_mode = mode;
151 f(self);
152 self.node_id_hashing_mode = prev;
153 }
154
155 #[inline]
ea8adc8c 156 pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
ba9703b0
XL
157 if let Some(def_id) = def_id.as_local() {
158 self.local_def_path_hash(def_id)
ea8adc8c
XL
159 } else {
160 self.cstore.def_path_hash(def_id)
161 }
162 }
163
164 #[inline]
ba9703b0
XL
165 pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
166 self.definitions.def_path_hash(def_id)
cc61c64b
XL
167 }
168
cc61c64b
XL
169 #[inline]
170 pub fn hash_bodies(&self) -> bool {
171 self.hash_bodies
172 }
173
174 #[inline]
b7449926
XL
175 pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> {
176 match self.caching_source_map {
74b04a01 177 Some(ref mut sm) => sm,
ea8adc8c 178 ref mut none => {
b7449926 179 *none = Some(CachingSourceMapView::new(self.raw_source_map));
ea8adc8c
XL
180 none.as_mut().unwrap()
181 }
182 }
cc61c64b
XL
183 }
184
185 #[inline]
186 pub fn is_ignored_attr(&self, name: Symbol) -> bool {
b7449926
XL
187 thread_local! {
188 static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names();
189 }
190 IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
cc61c64b 191 }
cc61c64b
XL
192}
193
0531ce1d
XL
194/// Something that can provide a stable hashing context.
195pub trait StableHashingContextProvider<'a> {
196 fn get_stable_hashing_context(&self) -> StableHashingContext<'a>;
197}
198
dfeec247 199impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b T {
0531ce1d
XL
200 fn get_stable_hashing_context(&self) -> StableHashingContext<'a> {
201 (**self).get_stable_hashing_context()
202 }
203}
204
dfeec247 205impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b mut T {
0531ce1d
XL
206 fn get_stable_hashing_context(&self) -> StableHashingContext<'a> {
207 (**self).get_stable_hashing_context()
ea8adc8c
XL
208 }
209}
210
dc9dc135
XL
211impl StableHashingContextProvider<'tcx> for TyCtxt<'tcx> {
212 fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> {
0531ce1d
XL
213 (*self).create_stable_hashing_context()
214 }
215}
ea8adc8c 216
0531ce1d
XL
217impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> {
218 fn get_stable_hashing_context(&self) -> StableHashingContext<'a> {
ea8adc8c
XL
219 self.clone()
220 }
221}
222
0531ce1d 223impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
74b04a01
XL
224 fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
225 panic!("Node IDs should not appear in incremental state");
ea8adc8c
XL
226 }
227}
228
dfeec247 229impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
60c5eb7d
XL
230 fn hash_spans(&self) -> bool {
231 self.hash_spans
cc61c64b 232 }
cc61c64b 233
3dfed10e
XL
234 #[inline]
235 fn hash_crate_num(&mut self, cnum: CrateNum, hasher: &mut StableHasher) {
236 let hcx = self;
237 hcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
238 }
239
74b04a01
XL
240 #[inline]
241 fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
242 let hcx = self;
243 hcx.def_path_hash(def_id).hash_stable(hcx, hasher);
244 }
245
5869c6ff
XL
246 fn expn_id_cache() -> &'static LocalKey<rustc_span::ExpnIdCache> {
247 thread_local! {
248 static CACHE: rustc_span::ExpnIdCache = Default::default();
249 }
250 &CACHE
251 }
252
5869c6ff
XL
253 fn span_data_to_lines_and_cols(
254 &mut self,
255 span: &SpanData,
256 ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
257 self.source_map().span_data_to_lines_and_cols(span)
258 }
b7449926
XL
259}
260
e74abb32 261pub fn hash_stable_trait_impls<'a>(
0531ce1d 262 hcx: &mut StableHashingContext<'a>,
e74abb32 263 hasher: &mut StableHasher,
8faf50e0 264 blanket_impls: &[DefId],
dc9dc135 265 non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>,
e74abb32 266) {
ea8adc8c 267 {
dfeec247
XL
268 let mut blanket_impls: SmallVec<[_; 8]> =
269 blanket_impls.iter().map(|&def_id| hcx.def_path_hash(def_id)).collect();
cc61c64b 270
ea8adc8c
XL
271 if blanket_impls.len() > 1 {
272 blanket_impls.sort_unstable();
273 }
7cac9316 274
ea8adc8c
XL
275 blanket_impls.hash_stable(hcx, hasher);
276 }
3b2f2976 277
ea8adc8c 278 {
b7449926 279 let mut keys: SmallVec<[_; 8]> =
dfeec247 280 non_blanket_impls.keys().map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))).collect();
ea8adc8c
XL
281 keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2));
282 keys.len().hash_stable(hcx, hasher);
283 for (key, ref stable_key) in keys {
284 stable_key.hash_stable(hcx, hasher);
dfeec247
XL
285 let mut impls: SmallVec<[_; 8]> =
286 non_blanket_impls[key].iter().map(|&impl_id| hcx.def_path_hash(impl_id)).collect();
ea8adc8c
XL
287
288 if impls.len() > 1 {
289 impls.sort_unstable();
290 }
7cac9316 291
ea8adc8c
XL
292 impls.hash_stable(hcx, hasher);
293 }
7cac9316
XL
294 }
295}