]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ich/impls_syntax.rs
Rollup merge of #85174 - GuillaumeGomez:doc-code-block-border-radius, r=jsha
[rust.git] / compiler / rustc_middle / 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
10 use smallvec::SmallVec;
11
12 impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
13
14 impl<'a> HashStable<StableHashingContext<'a>> for [ast::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<[&ast::Attribute; 8]> = self
23             .iter()
24             .filter(|attr| {
25                 !attr.is_doc_comment()
26                     && !attr.ident().map_or(false, |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
37 impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
38     fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
39         // Make sure that these have been filtered out.
40         debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name)));
41         debug_assert!(!attr.is_doc_comment());
42
43         let ast::Attribute { kind, id: _, style, span } = attr;
44         if let ast::AttrKind::Normal(item, tokens) = kind {
45             item.hash_stable(self, hasher);
46             style.hash_stable(self, hasher);
47             span.hash_stable(self, hasher);
48             assert_matches!(
49                 tokens.as_ref(),
50                 None,
51                 "Tokens should have been removed during lowering!"
52             );
53         } else {
54             unreachable!();
55         }
56     }
57 }
58
59 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
60     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
61         let SourceFile {
62             name: _, // We hash the smaller name_hash instead of this
63             name_hash,
64             cnum,
65             // Do not hash the source as it is not encoded
66             src: _,
67             ref src_hash,
68             external_src: _,
69             start_pos,
70             end_pos: _,
71             ref lines,
72             ref multibyte_chars,
73             ref non_narrow_chars,
74             ref normalized_pos,
75         } = *self;
76
77         (name_hash as u64).hash_stable(hcx, hasher);
78
79         src_hash.hash_stable(hcx, hasher);
80
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             stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
85         }
86
87         // We only hash the relative position within this source_file
88         multibyte_chars.len().hash_stable(hcx, hasher);
89         for &char_pos in multibyte_chars.iter() {
90             stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
91         }
92
93         non_narrow_chars.len().hash_stable(hcx, hasher);
94         for &char_pos in non_narrow_chars.iter() {
95             stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
96         }
97
98         normalized_pos.len().hash_stable(hcx, hasher);
99         for &char_pos in normalized_pos.iter() {
100             stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
101         }
102
103         cnum.hash_stable(hcx, hasher);
104     }
105 }
106
107 fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 {
108     pos.0 - source_file_start.0
109 }
110
111 fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) {
112     let rustc_span::MultiByteChar { pos, bytes } = mbc;
113
114     (pos.0 - source_file_start.0, bytes as u32)
115 }
116
117 fn stable_non_narrow_char(
118     swc: rustc_span::NonNarrowChar,
119     source_file_start: BytePos,
120 ) -> (u32, u32) {
121     let pos = swc.pos();
122     let width = swc.width();
123
124     (pos.0 - source_file_start.0, width as u32)
125 }
126
127 fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) {
128     let NormalizedPos { pos, diff } = np;
129
130     (pos.0 - source_file_start.0, diff)
131 }
132
133 impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
134     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
135         // Unfortunately we cannot exhaustively list fields here, since the
136         // struct is macro generated.
137         self.declared_lang_features.hash_stable(hcx, hasher);
138         self.declared_lib_features.hash_stable(hcx, hasher);
139
140         self.walk_feature_fields(|feature_name, value| {
141             feature_name.hash_stable(hcx, hasher);
142             value.hash_stable(hcx, hasher);
143         });
144     }
145 }