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