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;
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, DUMMY_SP};
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).
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,
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> {
46 bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>,
50 impl<'a> StableHashingContext<'a> {
54 definitions: &'a Definitions,
55 cstore: &'a dyn CrateStore,
56 source_span: &'a IndexVec<LocalDefId, Span>,
58 let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
60 StableHashingContext {
61 body_resolver: BodyResolver::Forbidden,
65 incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
66 caching_source_map: None,
67 raw_source_map: sess.source_map(),
68 hashing_controls: HashingControls { hash_spans: hash_spans_initial },
73 pub fn without_hir_bodies(&mut self, f: impl FnOnce(&mut StableHashingContext<'_>)) {
74 f(&mut StableHashingContext { body_resolver: BodyResolver::Ignore, ..self.clone() });
78 pub fn with_hir_bodies(
81 bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>,
82 f: impl FnOnce(&mut StableHashingContext<'_>),
84 f(&mut StableHashingContext {
85 body_resolver: BodyResolver::Traverse { owner, bodies },
91 pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
92 let prev_hash_spans = self.hashing_controls.hash_spans;
93 self.hashing_controls.hash_spans = hash_spans;
95 self.hashing_controls.hash_spans = prev_hash_spans;
99 pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
100 if let Some(def_id) = def_id.as_local() {
101 self.local_def_path_hash(def_id)
103 self.cstore.def_path_hash(def_id)
108 pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
109 self.definitions.def_path_hash(def_id)
113 pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> {
114 match self.caching_source_map {
115 Some(ref mut sm) => sm,
117 *none = Some(CachingSourceMapView::new(self.raw_source_map));
118 none.as_mut().unwrap()
124 pub fn is_ignored_attr(&self, name: Symbol) -> bool {
125 ich::IGNORED_ATTRIBUTES.contains(&name)
129 pub fn hashing_controls(&self) -> HashingControls {
130 self.hashing_controls.clone()
134 impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
136 fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
137 panic!("Node IDs should not appear in incremental state");
141 impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
143 fn hash_spans(&self) -> bool {
144 self.hashing_controls.hash_spans
148 fn unstable_opts_incremental_ignore_spans(&self) -> bool {
149 self.incremental_ignore_spans
153 fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
154 self.def_path_hash(def_id)
158 fn def_span(&self, def_id: LocalDefId) -> Span {
159 *self.source_span.get(def_id).unwrap_or(&DUMMY_SP)
163 fn span_data_to_lines_and_cols(
166 ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
167 self.source_map().span_data_to_lines_and_cols(span)
171 fn hashing_controls(&self) -> HashingControls {
172 self.hashing_controls.clone()
176 impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}