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