rustc_query_system/ich/
hcx.rs

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