Skip to main content

rustc_middle/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_ast as ast;
5use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6use rustc_hir as hir;
7use rustc_span::{SourceFile, Symbol, sym};
8use smallvec::SmallVec;
9
10use super::StableHashingContext;
11
12impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
13    #[inline]
14    fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
15        {
    ::core::panicking::panic_fmt(format_args!("Node IDs should not appear in incremental state"));
};panic!("Node IDs should not appear in incremental state");
16    }
17}
18
19impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] {
20    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
21        if self.is_empty() {
22            self.len().hash_stable(hcx, hasher);
23            return;
24        }
25
26        // Some attributes are always ignored during hashing.
27        let filtered: SmallVec<[&hir::Attribute; 8]> = self
28            .iter()
29            .filter(|attr| {
30                attr.is_doc_comment().is_none()
31                    // FIXME(jdonszelmann) have a better way to handle ignored attrs
32                    && !attr.name().is_some_and(|ident| is_ignored_attr(ident))
33            })
34            .collect();
35
36        filtered.len().hash_stable(hcx, hasher);
37        for attr in filtered {
38            attr.hash_stable(hcx, hasher);
39        }
40    }
41}
42
43#[inline]
44fn is_ignored_attr(name: Symbol) -> bool {
45    const IGNORED_ATTRIBUTES: &[Symbol] = &[
46        sym::cfg_trace, // FIXME(#138844) should this really be ignored?
47        sym::rustc_if_this_changed,
48        sym::rustc_then_this_would_need,
49        sym::rustc_clean,
50        sym::rustc_partition_reused,
51        sym::rustc_partition_codegened,
52        sym::rustc_expected_cgu_reuse,
53    ];
54    IGNORED_ATTRIBUTES.contains(&name)
55}
56
57impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
58    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
59        let SourceFile {
60            name: _, // We hash the smaller stable_id instead of this
61            stable_id,
62            cnum,
63            // Do not hash the source as it is not encoded
64            src: _,
65            ref src_hash,
66            // Already includes src_hash, this is redundant
67            checksum_hash: _,
68            external_src: _,
69            start_pos: _,
70            normalized_source_len: _,
71            unnormalized_source_len: _,
72            lines: _,
73            ref multibyte_chars,
74            ref normalized_pos,
75        } = *self;
76
77        stable_id.hash_stable(hcx, hasher);
78
79        src_hash.hash_stable(hcx, hasher);
80
81        {
82            // We are always in `Lines` form by the time we reach here.
83            if !self.lines.read().is_lines() {
    ::core::panicking::panic("assertion failed: self.lines.read().is_lines()")
};assert!(self.lines.read().is_lines());
84            let lines = self.lines();
85            // We only hash the relative position within this source_file
86            lines.len().hash_stable(hcx, hasher);
87            for &line in lines.iter() {
88                line.hash_stable(hcx, hasher);
89            }
90        }
91
92        // We only hash the relative position within this source_file
93        multibyte_chars.len().hash_stable(hcx, hasher);
94        for &char_pos in multibyte_chars.iter() {
95            char_pos.hash_stable(hcx, hasher);
96        }
97
98        normalized_pos.len().hash_stable(hcx, hasher);
99        for &char_pos in normalized_pos.iter() {
100            char_pos.hash_stable(hcx, hasher);
101        }
102
103        cnum.hash_stable(hcx, hasher);
104    }
105}
106
107impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
108    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
109        // Unfortunately we cannot exhaustively list fields here, since the
110        // struct has private fields (to ensure its invariant is maintained)
111        self.enabled_lang_features().hash_stable(hcx, hasher);
112        self.enabled_lib_features().hash_stable(hcx, hasher);
113    }
114}
115
116impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLangFeature {
117    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
118        let rustc_feature::EnabledLangFeature { gate_name, attr_sp, stable_since } = self;
119        gate_name.hash_stable(hcx, hasher);
120        attr_sp.hash_stable(hcx, hasher);
121        stable_since.hash_stable(hcx, hasher);
122    }
123}
124
125impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLibFeature {
126    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
127        let rustc_feature::EnabledLibFeature { gate_name, attr_sp } = self;
128        gate_name.hash_stable(hcx, hasher);
129        attr_sp.hash_stable(hcx, hasher);
130    }
131}