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;
11 use syntax::parse::token;
12 use syntax::symbol::InternedString;
13 use syntax::tokenstream;
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 InternedString {
23 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
24 self.with(|s| s.hash_stable(hcx, hasher))
28 impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
29 type KeyType = InternedString;
32 fn to_stable_hash_key(&self,
33 _: &StableHashingContext<'a>)
39 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
41 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
42 self.as_str().hash_stable(hcx, hasher);
46 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
47 type KeyType = InternedString;
50 fn to_stable_hash_key(&self,
51 _: &StableHashingContext<'a>)
53 self.as_interned_str()
57 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
62 impl_stable_hash_for!(enum ::syntax_expand::base::MacroKind {
69 impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
91 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
92 impl_stable_hash_for!(struct ::syntax::attr::Stability {
101 impl_stable_hash_for!(enum ::syntax::edition::Edition {
106 impl<'a> HashStable<StableHashingContext<'a>>
107 for ::syntax::attr::StabilityLevel {
108 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
109 mem::discriminant(self).hash_stable(hcx, hasher);
111 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
112 reason.hash_stable(hcx, hasher);
113 issue.hash_stable(hcx, hasher);
114 is_soft.hash_stable(hcx, hasher);
116 ::syntax::attr::StabilityLevel::Stable { ref since } => {
117 since.hash_stable(hcx, hasher);
123 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
126 impl_stable_hash_for!(enum ::syntax::attr::IntType {
131 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
137 impl_stable_hash_for!(struct ::syntax::ast::Lit {
143 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
148 Int(value, lit_int_type),
149 Float(value, float_ty),
150 FloatUnsuffixed(value),
155 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
157 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
158 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
159 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
160 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
161 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
162 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
163 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
164 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
165 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
167 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
168 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
170 self.len().hash_stable(hcx, hasher);
174 // Some attributes are always ignored during hashing.
175 let filtered: SmallVec<[&ast::Attribute; 8]> = self
178 !attr.is_sugared_doc &&
179 !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
183 filtered.len().hash_stable(hcx, hasher);
184 for attr in filtered {
185 attr.hash_stable(hcx, hasher);
190 impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
191 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
192 self.segments.len().hash_stable(hcx, hasher);
193 for segment in &self.segments {
194 segment.ident.name.hash_stable(hcx, hasher);
199 impl_stable_hash_for!(struct ::syntax::ast::AttrItem {
204 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
205 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
206 // Make sure that these have been filtered out.
207 debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
208 debug_assert!(!self.is_sugared_doc);
218 item.hash_stable(hcx, hasher);
219 style.hash_stable(hcx, hasher);
220 span.hash_stable(hcx, hasher);
224 impl<'a> HashStable<StableHashingContext<'a>>
225 for tokenstream::TokenTree {
226 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
227 mem::discriminant(self).hash_stable(hcx, hasher);
229 tokenstream::TokenTree::Token(ref token) => {
230 token.hash_stable(hcx, hasher);
232 tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
233 span.hash_stable(hcx, hasher);
234 std_hash::Hash::hash(&delim, hasher);
235 for sub_tt in tts.trees() {
236 sub_tt.hash_stable(hcx, hasher);
243 impl<'a> HashStable<StableHashingContext<'a>>
244 for tokenstream::TokenStream {
245 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
246 for sub_tt in self.trees() {
247 sub_tt.hash_stable(hcx, hasher);
252 impl_stable_hash_for!(enum token::LitKind {
265 impl_stable_hash_for!(struct token::Lit {
271 impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
272 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
273 mem::discriminant(self).hash_stable(hcx, hasher);
306 token::BinOp(bin_op_token) |
307 token::BinOpEq(bin_op_token) => {
308 std_hash::Hash::hash(&bin_op_token, hasher);
311 token::OpenDelim(delim_token) |
312 token::CloseDelim(delim_token) => {
313 std_hash::Hash::hash(&delim_token, hasher);
315 token::Literal(lit) => lit.hash_stable(hcx, hasher),
317 token::Ident(name, is_raw) => {
318 name.hash_stable(hcx, hasher);
319 is_raw.hash_stable(hcx, hasher);
321 token::Lifetime(name) => name.hash_stable(hcx, hasher),
323 token::Interpolated(_) => {
324 bug!("interpolated tokens should not be present in the HIR")
327 token::DocComment(val) |
328 token::Shebang(val) |
329 token::Unknown(val) => val.hash_stable(hcx, hasher),
334 impl_stable_hash_for!(struct token::Token {
339 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
344 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
350 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
356 impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
362 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
367 allow_internal_unstable,
368 allow_internal_unsafe,
373 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
380 impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass {
387 impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
397 impl_stable_hash_for!(enum ::syntax_pos::FileName {
403 ProcMacroSourceCode(s),
410 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
411 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
413 name: _, // We hash the smaller name_hash instead of this
418 // Do not hash the source as it is not encoded
426 ref non_narrow_chars,
429 (name_hash as u64).hash_stable(hcx, hasher);
430 name_was_remapped.hash_stable(hcx, hasher);
433 krate: CrateNum::from_u32(crate_of_origin),
434 index: CRATE_DEF_INDEX,
435 }.hash_stable(hcx, hasher);
437 src_hash.hash_stable(hcx, hasher);
439 // We only hash the relative position within this source_file
440 lines.len().hash_stable(hcx, hasher);
441 for &line in lines.iter() {
442 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
445 // We only hash the relative position within this source_file
446 multibyte_chars.len().hash_stable(hcx, hasher);
447 for &char_pos in multibyte_chars.iter() {
448 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
451 non_narrow_chars.len().hash_stable(hcx, hasher);
452 for &char_pos in non_narrow_chars.iter() {
453 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
458 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
459 source_file_start: ::syntax_pos::BytePos)
461 pos.0 - source_file_start.0
464 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
465 source_file_start: ::syntax_pos::BytePos)
467 let ::syntax_pos::MultiByteChar {
472 (pos.0 - source_file_start.0, bytes as u32)
475 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
476 source_file_start: ::syntax_pos::BytePos)
479 let width = swc.width();
481 (pos.0 - source_file_start.0, width as u32)
484 impl<'tcx> HashStable<StableHashingContext<'tcx>> for feature_gate::Features {
485 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
486 // Unfortunately we cannot exhaustively list fields here, since the
487 // struct is macro generated.
488 self.declared_lang_features.hash_stable(hcx, hasher);
489 self.declared_lib_features.hash_stable(hcx, hasher);
491 self.walk_feature_fields(|feature_name, value| {
492 feature_name.hash_stable(hcx, hasher);
493 value.hash_stable(hcx, hasher);