]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_query_system/src/ich/impls_syntax.rs
Merge commit '2bb3996244cf1b89878da9e39841e9f6bf061602' into sync_cg_clif-2022-12-14
[rust.git] / compiler / rustc_query_system / src / ich / impls_syntax.rs
1 //! This module contains `HashStable` implementations for various data types
2 //! from `rustc_ast` in no particular order.
3
4 use crate::ich::StableHashingContext;
5
6 use rustc_ast as ast;
7 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8 use rustc_span::{BytePos, NormalizedPos, SourceFile};
9 use std::assert_matches::assert_matches;
10
11 use smallvec::SmallVec;
12
13 impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
14
15 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
16     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
17         if self.is_empty() {
18             self.len().hash_stable(hcx, hasher);
19             return;
20         }
21
22         // Some attributes are always ignored during hashing.
23         let filtered: SmallVec<[&ast::Attribute; 8]> = self
24             .iter()
25             .filter(|attr| {
26                 !attr.is_doc_comment()
27                     && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
28             })
29             .collect();
30
31         filtered.len().hash_stable(hcx, hasher);
32         for attr in filtered {
33             attr.hash_stable(hcx, hasher);
34         }
35     }
36 }
37
38 impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
39     fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
40         // Make sure that these have been filtered out.
41         debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name)));
42         debug_assert!(!attr.is_doc_comment());
43
44         let ast::Attribute { kind, id: _, style, span } = attr;
45         if let ast::AttrKind::Normal(normal) = kind {
46             normal.item.hash_stable(self, hasher);
47             style.hash_stable(self, hasher);
48             span.hash_stable(self, hasher);
49             assert_matches!(
50                 normal.tokens.as_ref(),
51                 None,
52                 "Tokens should have been removed during lowering!"
53             );
54         } else {
55             unreachable!();
56         }
57     }
58 }
59
60 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
61     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
62         let SourceFile {
63             name: _, // We hash the smaller name_hash instead of this
64             name_hash,
65             cnum,
66             // Do not hash the source as it is not encoded
67             src: _,
68             ref src_hash,
69             external_src: _,
70             start_pos,
71             end_pos: _,
72             lines: _,
73             ref multibyte_chars,
74             ref non_narrow_chars,
75             ref normalized_pos,
76         } = *self;
77
78         (name_hash as u64).hash_stable(hcx, hasher);
79
80         src_hash.hash_stable(hcx, hasher);
81
82         // We are always in `Lines` form by the time we reach here.
83         assert!(self.lines.borrow().is_lines());
84         self.lines(|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                 stable_byte_pos(line, start_pos).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             stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
96         }
97
98         non_narrow_chars.len().hash_stable(hcx, hasher);
99         for &char_pos in non_narrow_chars.iter() {
100             stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
101         }
102
103         normalized_pos.len().hash_stable(hcx, hasher);
104         for &char_pos in normalized_pos.iter() {
105             stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
106         }
107
108         cnum.hash_stable(hcx, hasher);
109     }
110 }
111
112 fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 {
113     pos.0 - source_file_start.0
114 }
115
116 fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) {
117     let rustc_span::MultiByteChar { pos, bytes } = mbc;
118
119     (pos.0 - source_file_start.0, bytes as u32)
120 }
121
122 fn stable_non_narrow_char(
123     swc: rustc_span::NonNarrowChar,
124     source_file_start: BytePos,
125 ) -> (u32, u32) {
126     let pos = swc.pos();
127     let width = swc.width();
128
129     (pos.0 - source_file_start.0, width as u32)
130 }
131
132 fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) {
133     let NormalizedPos { pos, diff } = np;
134
135     (pos.0 - source_file_start.0, diff)
136 }
137
138 impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
139     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
140         // Unfortunately we cannot exhaustively list fields here, since the
141         // struct is macro generated.
142         self.declared_lang_features.hash_stable(hcx, hasher);
143         self.declared_lib_features.hash_stable(hcx, hasher);
144
145         self.walk_feature_fields(|feature_name, value| {
146             feature_name.hash_stable(hcx, hasher);
147             value.hash_stable(hcx, hasher);
148         });
149     }
150 }
151
152 impl<'ctx> rustc_type_ir::HashStableContext for StableHashingContext<'ctx> {}