]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use crate::ich; |
3dfed10e | 2 | use rustc_ast as ast; |
c295e0f8 | 3 | use rustc_data_structures::fx::FxHashSet; |
3c0e092e | 4 | use rustc_data_structures::sorted_map::SortedMap; |
ba9703b0 | 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
5099ac24 | 6 | use rustc_data_structures::stable_hasher::{HashingControls, NodeIdHashingMode}; |
60c5eb7d | 7 | use rustc_data_structures::sync::Lrc; |
dfeec247 | 8 | use rustc_hir as hir; |
ba9703b0 XL |
9 | use rustc_hir::def_id::{DefId, LocalDefId}; |
10 | use rustc_hir::definitions::{DefPathHash, Definitions}; | |
c295e0f8 | 11 | use rustc_session::cstore::CrateStore; |
ba9703b0 | 12 | use rustc_session::Session; |
dfeec247 XL |
13 | use rustc_span::source_map::SourceMap; |
14 | use rustc_span::symbol::Symbol; | |
c295e0f8 | 15 | use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData}; |
ea8adc8c | 16 | |
b7449926 | 17 | fn compute_ignored_attr_names() -> FxHashSet<Symbol> { |
74b04a01 XL |
18 | debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); |
19 | ich::IGNORED_ATTRIBUTES.iter().copied().collect() | |
2c00a5a8 | 20 | } |
cc61c64b XL |
21 | |
22 | /// This is the context state available during incr. comp. hashing. It contains | |
e1599b0c XL |
23 | /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., |
24 | /// a reference to the `TyCtxt`) and it holds a few caches for speeding up various | |
25 | /// things (e.g., each `DefId`/`DefPath` is only hashed once). | |
ea8adc8c | 26 | #[derive(Clone)] |
0531ce1d | 27 | pub struct StableHashingContext<'a> { |
0531ce1d XL |
28 | definitions: &'a Definitions, |
29 | cstore: &'a dyn CrateStore, | |
5099ac24 FG |
30 | // The value of `-Z incremental-ignore-spans`. |
31 | // This field should only be used by `debug_opts_incremental_ignore_span` | |
32 | incremental_ignore_spans: bool, | |
dfeec247 | 33 | pub(super) body_resolver: BodyResolver<'a>, |
ea8adc8c | 34 | // Very often, we are hashing something that does not need the |
e1599b0c | 35 | // `CachingSourceMapView`, so we initialize it lazily. |
b7449926 XL |
36 | raw_source_map: &'a SourceMap, |
37 | caching_source_map: Option<CachingSourceMapView<'a>>, | |
5099ac24 | 38 | pub(super) hashing_controls: HashingControls, |
cc61c64b XL |
39 | } |
40 | ||
e1599b0c XL |
41 | /// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. |
42 | /// We could also just store a plain reference to the `hir::Crate` but we want | |
ea8adc8c XL |
43 | /// to avoid that the crate is used to get untracked access to all of the HIR. |
44 | #[derive(Clone, Copy)] | |
3c0e092e XL |
45 | pub(super) enum BodyResolver<'tcx> { |
46 | Forbidden, | |
47 | Traverse { | |
48 | hash_bodies: bool, | |
49 | owner: LocalDefId, | |
50 | bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>, | |
51 | }, | |
ea8adc8c | 52 | } |
cc61c64b | 53 | |
0531ce1d | 54 | impl<'a> StableHashingContext<'a> { |
0731742a | 55 | #[inline] |
f035d41b | 56 | fn new_with_or_without_spans( |
dfeec247 | 57 | sess: &'a Session, |
dfeec247 XL |
58 | definitions: &'a Definitions, |
59 | cstore: &'a dyn CrateStore, | |
f035d41b | 60 | always_ignore_spans: bool, |
dfeec247 | 61 | ) -> Self { |
f035d41b XL |
62 | let hash_spans_initial = |
63 | !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; | |
ea8adc8c | 64 | |
cc61c64b | 65 | StableHashingContext { |
3c0e092e | 66 | body_resolver: BodyResolver::Forbidden, |
ea8adc8c XL |
67 | definitions, |
68 | cstore, | |
5099ac24 | 69 | incremental_ignore_spans: sess.opts.debugging_opts.incremental_ignore_spans, |
b7449926 XL |
70 | caching_source_map: None, |
71 | raw_source_map: sess.source_map(), | |
5099ac24 FG |
72 | hashing_controls: HashingControls { |
73 | hash_spans: hash_spans_initial, | |
74 | node_id_hashing_mode: NodeIdHashingMode::HashDefPath, | |
75 | }, | |
cc61c64b XL |
76 | } |
77 | } | |
78 | ||
f035d41b XL |
79 | #[inline] |
80 | pub fn new( | |
81 | sess: &'a Session, | |
f035d41b XL |
82 | definitions: &'a Definitions, |
83 | cstore: &'a dyn CrateStore, | |
84 | ) -> Self { | |
85 | Self::new_with_or_without_spans( | |
86 | sess, | |
f035d41b XL |
87 | definitions, |
88 | cstore, | |
89 | /*always_ignore_spans=*/ false, | |
90 | ) | |
91 | } | |
92 | ||
93 | #[inline] | |
94 | pub fn ignore_spans( | |
95 | sess: &'a Session, | |
f035d41b XL |
96 | definitions: &'a Definitions, |
97 | cstore: &'a dyn CrateStore, | |
98 | ) -> Self { | |
99 | let always_ignore_spans = true; | |
3c0e092e | 100 | Self::new_with_or_without_spans(sess, definitions, cstore, always_ignore_spans) |
f035d41b XL |
101 | } |
102 | ||
3c0e092e | 103 | /// Allow hashing |
cc61c64b | 104 | #[inline] |
3c0e092e XL |
105 | pub fn while_hashing_hir_bodies(&mut self, hb: bool, f: impl FnOnce(&mut Self)) { |
106 | let prev = match &mut self.body_resolver { | |
107 | BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."), | |
108 | BodyResolver::Traverse { ref mut hash_bodies, .. } => { | |
109 | std::mem::replace(hash_bodies, hb) | |
110 | } | |
111 | }; | |
cc61c64b | 112 | f(self); |
3c0e092e XL |
113 | match &mut self.body_resolver { |
114 | BodyResolver::Forbidden => unreachable!(), | |
115 | BodyResolver::Traverse { ref mut hash_bodies, .. } => *hash_bodies = prev, | |
116 | } | |
117 | } | |
118 | ||
119 | #[inline] | |
120 | pub fn with_hir_bodies( | |
121 | &mut self, | |
122 | hash_bodies: bool, | |
123 | owner: LocalDefId, | |
124 | bodies: &'a SortedMap<hir::ItemLocalId, &'a hir::Body<'a>>, | |
125 | f: impl FnOnce(&mut Self), | |
126 | ) { | |
127 | let prev = self.body_resolver; | |
128 | self.body_resolver = BodyResolver::Traverse { hash_bodies, owner, bodies }; | |
129 | f(self); | |
130 | self.body_resolver = prev; | |
cc61c64b XL |
131 | } |
132 | ||
133 | #[inline] | |
dfeec247 | 134 | pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) { |
5099ac24 FG |
135 | let prev_hash_spans = self.hashing_controls.hash_spans; |
136 | self.hashing_controls.hash_spans = hash_spans; | |
cc61c64b | 137 | f(self); |
5099ac24 | 138 | self.hashing_controls.hash_spans = prev_hash_spans; |
cc61c64b XL |
139 | } |
140 | ||
141 | #[inline] | |
dfeec247 XL |
142 | pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>( |
143 | &mut self, | |
144 | mode: NodeIdHashingMode, | |
145 | f: F, | |
146 | ) { | |
5099ac24 FG |
147 | let prev = self.hashing_controls.node_id_hashing_mode; |
148 | self.hashing_controls.node_id_hashing_mode = mode; | |
cc61c64b | 149 | f(self); |
5099ac24 | 150 | self.hashing_controls.node_id_hashing_mode = prev; |
cc61c64b XL |
151 | } |
152 | ||
153 | #[inline] | |
ea8adc8c | 154 | pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { |
ba9703b0 XL |
155 | if let Some(def_id) = def_id.as_local() { |
156 | self.local_def_path_hash(def_id) | |
ea8adc8c XL |
157 | } else { |
158 | self.cstore.def_path_hash(def_id) | |
159 | } | |
160 | } | |
161 | ||
162 | #[inline] | |
ba9703b0 XL |
163 | pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { |
164 | self.definitions.def_path_hash(def_id) | |
cc61c64b XL |
165 | } |
166 | ||
cc61c64b | 167 | #[inline] |
b7449926 XL |
168 | pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { |
169 | match self.caching_source_map { | |
74b04a01 | 170 | Some(ref mut sm) => sm, |
ea8adc8c | 171 | ref mut none => { |
b7449926 | 172 | *none = Some(CachingSourceMapView::new(self.raw_source_map)); |
ea8adc8c XL |
173 | none.as_mut().unwrap() |
174 | } | |
175 | } | |
cc61c64b XL |
176 | } |
177 | ||
178 | #[inline] | |
179 | pub fn is_ignored_attr(&self, name: Symbol) -> bool { | |
b7449926 XL |
180 | thread_local! { |
181 | static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names(); | |
182 | } | |
183 | IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) | |
cc61c64b | 184 | } |
5099ac24 FG |
185 | |
186 | #[inline] | |
187 | pub fn hashing_controls(&self) -> HashingControls { | |
188 | self.hashing_controls.clone() | |
189 | } | |
cc61c64b XL |
190 | } |
191 | ||
0531ce1d | 192 | impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId { |
c295e0f8 | 193 | #[inline] |
74b04a01 XL |
194 | fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { |
195 | panic!("Node IDs should not appear in incremental state"); | |
ea8adc8c XL |
196 | } |
197 | } | |
198 | ||
dfeec247 | 199 | impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { |
c295e0f8 | 200 | #[inline] |
60c5eb7d | 201 | fn hash_spans(&self) -> bool { |
5099ac24 FG |
202 | self.hashing_controls.hash_spans |
203 | } | |
204 | ||
205 | #[inline] | |
206 | fn debug_opts_incremental_ignore_spans(&self) -> bool { | |
207 | self.incremental_ignore_spans | |
cc61c64b | 208 | } |
cc61c64b | 209 | |
3dfed10e | 210 | #[inline] |
136023e0 XL |
211 | fn def_path_hash(&self, def_id: DefId) -> DefPathHash { |
212 | self.def_path_hash(def_id) | |
5869c6ff XL |
213 | } |
214 | ||
c295e0f8 XL |
215 | #[inline] |
216 | fn def_span(&self, def_id: LocalDefId) -> Span { | |
217 | self.definitions.def_span(def_id) | |
218 | } | |
219 | ||
220 | #[inline] | |
5869c6ff XL |
221 | fn span_data_to_lines_and_cols( |
222 | &mut self, | |
223 | span: &SpanData, | |
224 | ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> { | |
225 | self.source_map().span_data_to_lines_and_cols(span) | |
226 | } | |
5099ac24 FG |
227 | |
228 | #[inline] | |
229 | fn hashing_controls(&self) -> HashingControls { | |
230 | self.hashing_controls.clone() | |
231 | } | |
b7449926 XL |
232 | } |
233 | ||
c295e0f8 | 234 | impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} |