rustc_query_system/ich/
impls_syntax.rs

1//! This module contains `HashStable` implementations for various data types
2//! from various crates in no particular order.
3
4use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5use rustc_hir as hir;
6use rustc_span::SourceFile;
7use smallvec::SmallVec;
8
9use crate::ich::StableHashingContext;
10
11impl<'ctx> rustc_abi::HashStableContext for StableHashingContext<'ctx> {}
12impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {}
13
14impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] {
15    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
16        if self.is_empty() {
17            self.len().hash_stable(hcx, hasher);
18            return;
19        }
20
21        // Some attributes are always ignored during hashing.
22        let filtered: SmallVec<[&hir::Attribute; 8]> = self
23            .iter()
24            .filter(|attr| {
25                !attr.is_doc_comment()
26                    && !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name))
27            })
28            .collect();
29
30        filtered.len().hash_stable(hcx, hasher);
31        for attr in filtered {
32            attr.hash_stable(hcx, hasher);
33        }
34    }
35}
36
37impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
38    fn hash_attr(&mut self, attr: &hir::Attribute, hasher: &mut StableHasher) {
39        // Make sure that these have been filtered out.
40        debug_assert!(!attr.ident().is_some_and(|ident| self.is_ignored_attr(ident.name)));
41        debug_assert!(!attr.is_doc_comment());
42
43        let hir::Attribute { kind, id: _, style, span } = attr;
44        if let hir::AttrKind::Normal(item) = kind {
45            item.hash_stable(self, hasher);
46            style.hash_stable(self, hasher);
47            span.hash_stable(self, hasher);
48        } else {
49            unreachable!();
50        }
51    }
52}
53
54impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
55    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
56        let SourceFile {
57            name: _, // We hash the smaller stable_id instead of this
58            stable_id,
59            cnum,
60            // Do not hash the source as it is not encoded
61            src: _,
62            ref src_hash,
63            // Already includes src_hash, this is redundant
64            checksum_hash: _,
65            external_src: _,
66            start_pos: _,
67            source_len: _,
68            lines: _,
69            ref multibyte_chars,
70            ref normalized_pos,
71        } = *self;
72
73        stable_id.hash_stable(hcx, hasher);
74
75        src_hash.hash_stable(hcx, hasher);
76
77        {
78            // We are always in `Lines` form by the time we reach here.
79            assert!(self.lines.read().is_lines());
80            let lines = self.lines();
81            // We only hash the relative position within this source_file
82            lines.len().hash_stable(hcx, hasher);
83            for &line in lines.iter() {
84                line.hash_stable(hcx, hasher);
85            }
86        }
87
88        // We only hash the relative position within this source_file
89        multibyte_chars.len().hash_stable(hcx, hasher);
90        for &char_pos in multibyte_chars.iter() {
91            char_pos.hash_stable(hcx, hasher);
92        }
93
94        normalized_pos.len().hash_stable(hcx, hasher);
95        for &char_pos in normalized_pos.iter() {
96            char_pos.hash_stable(hcx, hasher);
97        }
98
99        cnum.hash_stable(hcx, hasher);
100    }
101}
102
103impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
104    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
105        // Unfortunately we cannot exhaustively list fields here, since the
106        // struct has private fields (to ensure its invariant is maintained)
107        self.enabled_lang_features().hash_stable(hcx, hasher);
108        self.enabled_lib_features().hash_stable(hcx, hasher);
109    }
110}
111
112impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLangFeature {
113    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
114        let rustc_feature::EnabledLangFeature { gate_name, attr_sp, stable_since } = self;
115        gate_name.hash_stable(hcx, hasher);
116        attr_sp.hash_stable(hcx, hasher);
117        stable_since.hash_stable(hcx, hasher);
118    }
119}
120
121impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLibFeature {
122    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
123        let rustc_feature::EnabledLibFeature { gate_name, attr_sp } = self;
124        gate_name.hash_stable(hcx, hasher);
125        attr_sp.hash_stable(hcx, hasher);
126    }
127}