rustc_query_system/ich/
hcx.rs

1use rustc_ast as ast;
2use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
3use rustc_hir::def_id::{DefId, LocalDefId};
4use rustc_hir::definitions::DefPathHash;
5use rustc_session::Session;
6use rustc_session::cstore::Untracked;
7use rustc_span::source_map::SourceMap;
8use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData, Symbol};
9
10use crate::ich;
11
12/// This is the context state available during incr. comp. hashing. It contains
13/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
14/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
15/// things (e.g., each `DefId`/`DefPath` is only hashed once).
16#[derive(Clone)]
17pub struct StableHashingContext<'a> {
18    untracked: &'a Untracked,
19    // The value of `-Z incremental-ignore-spans`.
20    // This field should only be used by `unstable_opts_incremental_ignore_span`
21    incremental_ignore_spans: bool,
22    // Very often, we are hashing something that does not need the
23    // `CachingSourceMapView`, so we initialize it lazily.
24    raw_source_map: &'a SourceMap,
25    caching_source_map: Option<CachingSourceMapView<'a>>,
26    hashing_controls: HashingControls,
27}
28
29impl<'a> StableHashingContext<'a> {
30    #[inline]
31    pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self {
32        let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
33
34        StableHashingContext {
35            untracked,
36            incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
37            caching_source_map: None,
38            raw_source_map: sess.source_map(),
39            hashing_controls: HashingControls { hash_spans: hash_spans_initial },
40        }
41    }
42
43    #[inline]
44    pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
45        let prev_hash_spans = self.hashing_controls.hash_spans;
46        self.hashing_controls.hash_spans = hash_spans;
47        f(self);
48        self.hashing_controls.hash_spans = prev_hash_spans;
49    }
50
51    #[inline]
52    pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
53        if let Some(def_id) = def_id.as_local() {
54            self.local_def_path_hash(def_id)
55        } else {
56            self.untracked.cstore.read().def_path_hash(def_id)
57        }
58    }
59
60    #[inline]
61    pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
62        self.untracked.definitions.read().def_path_hash(def_id)
63    }
64
65    #[inline]
66    pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> {
67        match self.caching_source_map {
68            Some(ref mut sm) => sm,
69            ref mut none => {
70                *none = Some(CachingSourceMapView::new(self.raw_source_map));
71                none.as_mut().unwrap()
72            }
73        }
74    }
75
76    #[inline]
77    pub fn is_ignored_attr(&self, name: Symbol) -> bool {
78        ich::IGNORED_ATTRIBUTES.contains(&name)
79    }
80
81    #[inline]
82    pub fn hashing_controls(&self) -> HashingControls {
83        self.hashing_controls.clone()
84    }
85}
86
87impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
88    #[inline]
89    fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
90        panic!("Node IDs should not appear in incremental state");
91    }
92}
93
94impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
95    #[inline]
96    fn hash_spans(&self) -> bool {
97        self.hashing_controls.hash_spans
98    }
99
100    #[inline]
101    fn unstable_opts_incremental_ignore_spans(&self) -> bool {
102        self.incremental_ignore_spans
103    }
104
105    #[inline]
106    fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
107        self.def_path_hash(def_id)
108    }
109
110    #[inline]
111    fn def_span(&self, def_id: LocalDefId) -> Span {
112        self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
113    }
114
115    #[inline]
116    fn span_data_to_lines_and_cols(
117        &mut self,
118        span: &SpanData,
119    ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)> {
120        self.source_map().span_data_to_lines_and_cols(span)
121    }
122
123    #[inline]
124    fn hashing_controls(&self) -> HashingControls {
125        self.hashing_controls.clone()
126    }
127}
128
129impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}