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