]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_query_system/src/ich/hcx.rs
Rollup merge of #88137 - joshtriplett:osx-strip-symbols-no-option, r=michaelwoerister
[rust.git] / compiler / rustc_query_system / src / ich / hcx.rs
1 use crate::ich;
2 use rustc_ast as ast;
3 use rustc_data_structures::fx::FxHashSet;
4 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5 use rustc_data_structures::sync::Lrc;
6 use rustc_hir as hir;
7 use rustc_hir::def_id::{DefId, LocalDefId};
8 use rustc_hir::definitions::{DefPathHash, Definitions};
9 use rustc_session::cstore::CrateStore;
10 use rustc_session::Session;
11 use rustc_span::source_map::SourceMap;
12 use rustc_span::symbol::Symbol;
13 use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
14
15 fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
16     debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty());
17     ich::IGNORED_ATTRIBUTES.iter().copied().collect()
18 }
19
20 /// This is the context state available during incr. comp. hashing. It contains
21 /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
22 /// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
23 /// things (e.g., each `DefId`/`DefPath` is only hashed once).
24 #[derive(Clone)]
25 pub struct StableHashingContext<'a> {
26     definitions: &'a Definitions,
27     cstore: &'a dyn CrateStore,
28     pub(super) body_resolver: BodyResolver<'a>,
29     hash_spans: bool,
30     hash_bodies: bool,
31     pub(super) node_id_hashing_mode: NodeIdHashingMode,
32
33     // Very often, we are hashing something that does not need the
34     // `CachingSourceMapView`, so we initialize it lazily.
35     raw_source_map: &'a SourceMap,
36     caching_source_map: Option<CachingSourceMapView<'a>>,
37 }
38
39 #[derive(PartialEq, Eq, Clone, Copy)]
40 pub enum NodeIdHashingMode {
41     Ignore,
42     HashDefPath,
43 }
44
45 /// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`.
46 /// We could also just store a plain reference to the `hir::Crate` but we want
47 /// to avoid that the crate is used to get untracked access to all of the HIR.
48 #[derive(Clone, Copy)]
49 pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>);
50
51 impl<'tcx> BodyResolver<'tcx> {
52     /// Returns a reference to the `hir::Body` with the given `BodyId`.
53     /// **Does not do any tracking**; use carefully.
54     pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> {
55         self.0.body(id)
56     }
57 }
58
59 impl<'a> StableHashingContext<'a> {
60     /// The `krate` here is only used for mapping `BodyId`s to `Body`s.
61     /// Don't use it for anything else or you'll run the risk of
62     /// leaking data out of the tracking system.
63     #[inline]
64     fn new_with_or_without_spans(
65         sess: &'a Session,
66         krate: &'a hir::Crate<'a>,
67         definitions: &'a Definitions,
68         cstore: &'a dyn CrateStore,
69         always_ignore_spans: bool,
70     ) -> Self {
71         let hash_spans_initial =
72             !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
73
74         StableHashingContext {
75             body_resolver: BodyResolver(krate),
76             definitions,
77             cstore,
78             caching_source_map: None,
79             raw_source_map: sess.source_map(),
80             hash_spans: hash_spans_initial,
81             hash_bodies: true,
82             node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
83         }
84     }
85
86     #[inline]
87     pub fn new(
88         sess: &'a Session,
89         krate: &'a hir::Crate<'a>,
90         definitions: &'a Definitions,
91         cstore: &'a dyn CrateStore,
92     ) -> Self {
93         Self::new_with_or_without_spans(
94             sess,
95             krate,
96             definitions,
97             cstore,
98             /*always_ignore_spans=*/ false,
99         )
100     }
101
102     #[inline]
103     pub fn ignore_spans(
104         sess: &'a Session,
105         krate: &'a hir::Crate<'a>,
106         definitions: &'a Definitions,
107         cstore: &'a dyn CrateStore,
108     ) -> Self {
109         let always_ignore_spans = true;
110         Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans)
111     }
112
113     #[inline]
114     pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, f: F) {
115         let prev_hash_bodies = self.hash_bodies;
116         self.hash_bodies = hash_bodies;
117         f(self);
118         self.hash_bodies = prev_hash_bodies;
119     }
120
121     #[inline]
122     pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
123         let prev_hash_spans = self.hash_spans;
124         self.hash_spans = hash_spans;
125         f(self);
126         self.hash_spans = prev_hash_spans;
127     }
128
129     #[inline]
130     pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(
131         &mut self,
132         mode: NodeIdHashingMode,
133         f: F,
134     ) {
135         let prev = self.node_id_hashing_mode;
136         self.node_id_hashing_mode = mode;
137         f(self);
138         self.node_id_hashing_mode = prev;
139     }
140
141     #[inline]
142     pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
143         if let Some(def_id) = def_id.as_local() {
144             self.local_def_path_hash(def_id)
145         } else {
146             self.cstore.def_path_hash(def_id)
147         }
148     }
149
150     #[inline]
151     pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
152         self.definitions.def_path_hash(def_id)
153     }
154
155     #[inline]
156     pub fn hash_bodies(&self) -> bool {
157         self.hash_bodies
158     }
159
160     #[inline]
161     pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> {
162         match self.caching_source_map {
163             Some(ref mut sm) => sm,
164             ref mut none => {
165                 *none = Some(CachingSourceMapView::new(self.raw_source_map));
166                 none.as_mut().unwrap()
167             }
168         }
169     }
170
171     #[inline]
172     pub fn is_ignored_attr(&self, name: Symbol) -> bool {
173         thread_local! {
174             static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names();
175         }
176         IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
177     }
178 }
179
180 impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
181     #[inline]
182     fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
183         panic!("Node IDs should not appear in incremental state");
184     }
185 }
186
187 impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
188     #[inline]
189     fn hash_spans(&self) -> bool {
190         self.hash_spans
191     }
192
193     #[inline]
194     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
195         self.def_path_hash(def_id)
196     }
197
198     #[inline]
199     fn def_span(&self, def_id: LocalDefId) -> Span {
200         self.definitions.def_span(def_id)
201     }
202
203     #[inline]
204     fn span_data_to_lines_and_cols(
205         &mut self,
206         span: &SpanData,
207     ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
208         self.source_map().span_data_to_lines_and_cols(span)
209     }
210 }
211
212 impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}