1 //! This module contains `HashStable` implementations for various data types
2 //! from libsyntax in no particular order.
4 use crate::ich::StableHashingContext;
6 use std::hash as std_hash;
10 use syntax::feature_gate;
12 use syntax::tokenstream;
13 use syntax_pos::symbol::SymbolStr;
14 use syntax_pos::SourceFile;
16 use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
18 use smallvec::SmallVec;
19 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
21 impl<'a> HashStable<StableHashingContext<'a>> for SymbolStr {
23 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
24 let str = self as &str;
25 str.hash_stable(hcx, hasher)
29 impl<'a> ToStableHashKey<StableHashingContext<'a>> for SymbolStr {
30 type KeyType = SymbolStr;
33 fn to_stable_hash_key(&self,
34 _: &StableHashingContext<'a>)
40 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
42 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
43 self.as_str().hash_stable(hcx, hasher);
47 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
48 type KeyType = SymbolStr;
51 fn to_stable_hash_key(&self,
52 _: &StableHashingContext<'a>)
58 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
63 impl_stable_hash_for!(enum ::syntax_pos::hygiene::MacroKind {
70 impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
93 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
94 impl_stable_hash_for!(struct ::syntax::attr::Stability {
103 impl_stable_hash_for!(enum ::syntax::edition::Edition {
108 impl<'a> HashStable<StableHashingContext<'a>>
109 for ::syntax::attr::StabilityLevel {
110 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
111 mem::discriminant(self).hash_stable(hcx, hasher);
113 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
114 reason.hash_stable(hcx, hasher);
115 issue.hash_stable(hcx, hasher);
116 is_soft.hash_stable(hcx, hasher);
118 ::syntax::attr::StabilityLevel::Stable { ref since } => {
119 since.hash_stable(hcx, hasher);
125 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
127 impl_stable_hash_for!(enum ::syntax::attr::IntType {
132 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
138 impl_stable_hash_for!(enum ::syntax::ast::LitFloatType {
143 impl_stable_hash_for!(struct ::syntax::ast::Lit {
149 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
154 Int(value, lit_int_type),
155 Float(value, lit_float_type),
160 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
162 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
163 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
164 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
165 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
166 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
167 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
168 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
169 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
170 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
171 impl_stable_hash_for!(enum ::syntax::ast::Movability { Static, Movable });
172 impl_stable_hash_for!(enum ::syntax::ast::CaptureBy { Value, Ref });
173 impl_stable_hash_for!(enum ::syntax::ast::IsAuto { Yes, No });
174 impl_stable_hash_for!(enum ::syntax::ast::ImplPolarity { Positive, Negative });
176 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
177 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
179 self.len().hash_stable(hcx, hasher);
183 // Some attributes are always ignored during hashing.
184 let filtered: SmallVec<[&ast::Attribute; 8]> = self
187 !attr.is_doc_comment() &&
188 !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
192 filtered.len().hash_stable(hcx, hasher);
193 for attr in filtered {
194 attr.hash_stable(hcx, hasher);
199 impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
200 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
201 self.segments.len().hash_stable(hcx, hasher);
202 for segment in &self.segments {
203 segment.ident.name.hash_stable(hcx, hasher);
208 impl_stable_hash_for!(struct ::syntax::ast::AttrItem {
213 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
214 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
215 // Make sure that these have been filtered out.
216 debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
217 debug_assert!(!self.is_doc_comment());
219 let ast::Attribute { kind, id: _, style, span } = self;
220 if let ast::AttrKind::Normal(item) = kind {
221 item.hash_stable(hcx, hasher);
222 style.hash_stable(hcx, hasher);
223 span.hash_stable(hcx, hasher);
230 impl<'a> HashStable<StableHashingContext<'a>>
231 for tokenstream::TokenTree {
232 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
233 mem::discriminant(self).hash_stable(hcx, hasher);
235 tokenstream::TokenTree::Token(ref token) => {
236 token.hash_stable(hcx, hasher);
238 tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
239 span.hash_stable(hcx, hasher);
240 std_hash::Hash::hash(&delim, hasher);
241 for sub_tt in tts.trees() {
242 sub_tt.hash_stable(hcx, hasher);
249 impl<'a> HashStable<StableHashingContext<'a>>
250 for tokenstream::TokenStream {
251 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
252 for sub_tt in self.trees() {
253 sub_tt.hash_stable(hcx, hasher);
258 impl_stable_hash_for!(enum token::LitKind {
271 impl_stable_hash_for!(struct token::Lit {
277 impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
278 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
279 mem::discriminant(self).hash_stable(hcx, hasher);
312 token::BinOp(bin_op_token) |
313 token::BinOpEq(bin_op_token) => {
314 std_hash::Hash::hash(&bin_op_token, hasher);
317 token::OpenDelim(delim_token) |
318 token::CloseDelim(delim_token) => {
319 std_hash::Hash::hash(&delim_token, hasher);
321 token::Literal(lit) => lit.hash_stable(hcx, hasher),
323 token::Ident(name, is_raw) => {
324 name.hash_stable(hcx, hasher);
325 is_raw.hash_stable(hcx, hasher);
327 token::Lifetime(name) => name.hash_stable(hcx, hasher),
329 token::Interpolated(_) => {
330 bug!("interpolated tokens should not be present in the HIR")
333 token::DocComment(val) |
334 token::Shebang(val) |
335 token::Unknown(val) => val.hash_stable(hcx, hasher),
340 impl_stable_hash_for!(struct token::Token {
345 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
350 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
356 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
362 impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
368 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
373 allow_internal_unstable,
374 allow_internal_unsafe,
379 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
386 impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass {
393 impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
403 impl_stable_hash_for!(enum ::syntax_pos::FileName {
409 ProcMacroSourceCode(s),
416 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
417 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
419 name: _, // We hash the smaller name_hash instead of this
424 // Do not hash the source as it is not encoded
432 ref non_narrow_chars,
436 (name_hash as u64).hash_stable(hcx, hasher);
437 name_was_remapped.hash_stable(hcx, hasher);
440 krate: CrateNum::from_u32(crate_of_origin),
441 index: CRATE_DEF_INDEX,
442 }.hash_stable(hcx, hasher);
444 src_hash.hash_stable(hcx, hasher);
446 // We only hash the relative position within this source_file
447 lines.len().hash_stable(hcx, hasher);
448 for &line in lines.iter() {
449 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
452 // We only hash the relative position within this source_file
453 multibyte_chars.len().hash_stable(hcx, hasher);
454 for &char_pos in multibyte_chars.iter() {
455 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
458 non_narrow_chars.len().hash_stable(hcx, hasher);
459 for &char_pos in non_narrow_chars.iter() {
460 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
463 normalized_pos.len().hash_stable(hcx, hasher);
464 for &char_pos in normalized_pos.iter() {
465 stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
471 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
472 source_file_start: ::syntax_pos::BytePos)
474 pos.0 - source_file_start.0
477 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
478 source_file_start: ::syntax_pos::BytePos)
480 let ::syntax_pos::MultiByteChar {
485 (pos.0 - source_file_start.0, bytes as u32)
488 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
489 source_file_start: ::syntax_pos::BytePos)
492 let width = swc.width();
494 (pos.0 - source_file_start.0, width as u32)
497 fn stable_normalized_pos(np: ::syntax_pos::NormalizedPos,
498 source_file_start: ::syntax_pos::BytePos)
500 let ::syntax_pos::NormalizedPos {
505 (pos.0 - source_file_start.0, diff)
509 impl<'tcx> HashStable<StableHashingContext<'tcx>> for feature_gate::Features {
510 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
511 // Unfortunately we cannot exhaustively list fields here, since the
512 // struct is macro generated.
513 self.declared_lang_features.hash_stable(hcx, hasher);
514 self.declared_lib_features.hash_stable(hcx, hasher);
516 self.walk_feature_fields(|feature_name, value| {
517 feature_name.hash_stable(hcx, hasher);
518 value.hash_stable(hcx, hasher);