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, LocalInternedString};
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,
20 StableHasher, StableHasherResult};
22 impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
24 fn hash_stable<W: StableHasherResult>(&self,
25 hcx: &mut StableHashingContext<'a>,
26 hasher: &mut StableHasher<W>) {
27 self.with(|s| s.hash_stable(hcx, hasher))
31 impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
32 type KeyType = InternedString;
35 fn to_stable_hash_key(&self,
36 _: &StableHashingContext<'a>)
42 impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
44 fn hash_stable<W: StableHasherResult>(&self,
45 hcx: &mut StableHashingContext<'a>,
46 hasher: &mut StableHasher<W>) {
47 let s: &str = &**self;
48 s.hash_stable(hcx, hasher);
52 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
53 type KeyType = LocalInternedString;
56 fn to_stable_hash_key(&self,
57 _: &StableHashingContext<'a>)
58 -> LocalInternedString {
63 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
65 fn hash_stable<W: StableHasherResult>(&self,
66 hcx: &mut StableHashingContext<'a>,
67 hasher: &mut StableHasher<W>) {
68 self.as_str().hash_stable(hcx, hasher);
72 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
73 type KeyType = InternedString;
76 fn to_stable_hash_key(&self,
77 _: &StableHashingContext<'a>)
79 self.as_interned_str()
83 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
88 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
95 impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
117 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
118 impl_stable_hash_for!(struct ::syntax::attr::Stability {
127 impl_stable_hash_for!(enum ::syntax::edition::Edition {
132 impl<'a> HashStable<StableHashingContext<'a>>
133 for ::syntax::attr::StabilityLevel {
134 fn hash_stable<W: StableHasherResult>(&self,
135 hcx: &mut StableHashingContext<'a>,
136 hasher: &mut StableHasher<W>) {
137 mem::discriminant(self).hash_stable(hcx, hasher);
139 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
140 reason.hash_stable(hcx, hasher);
141 issue.hash_stable(hcx, hasher);
143 ::syntax::attr::StabilityLevel::Stable { ref since } => {
144 since.hash_stable(hcx, hasher);
150 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
153 impl_stable_hash_for!(enum ::syntax::attr::IntType {
158 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
164 impl_stable_hash_for!(struct ::syntax::ast::Lit {
170 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
175 Int(value, lit_int_type),
176 Float(value, float_ty),
177 FloatUnsuffixed(value),
182 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
184 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
185 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
186 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
187 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
188 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
189 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
190 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
191 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
192 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
194 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
195 fn hash_stable<W: StableHasherResult>(&self,
196 hcx: &mut StableHashingContext<'a>,
197 hasher: &mut StableHasher<W>) {
199 self.len().hash_stable(hcx, hasher);
203 // Some attributes are always ignored during hashing.
204 let filtered: SmallVec<[&ast::Attribute; 8]> = self
207 !attr.is_sugared_doc &&
208 !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
212 filtered.len().hash_stable(hcx, hasher);
213 for attr in filtered {
214 attr.hash_stable(hcx, hasher);
219 impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
220 fn hash_stable<W: StableHasherResult>(&self,
221 hcx: &mut StableHashingContext<'a>,
222 hasher: &mut StableHasher<W>) {
223 self.segments.len().hash_stable(hcx, hasher);
224 for segment in &self.segments {
225 segment.ident.name.hash_stable(hcx, hasher);
230 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
231 fn hash_stable<W: StableHasherResult>(&self,
232 hcx: &mut StableHashingContext<'a>,
233 hasher: &mut StableHasher<W>) {
234 // Make sure that these have been filtered out.
235 debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
236 debug_assert!(!self.is_sugared_doc);
247 style.hash_stable(hcx, hasher);
248 path.hash_stable(hcx, hasher);
249 for tt in tokens.trees() {
250 tt.hash_stable(hcx, hasher);
252 span.hash_stable(hcx, hasher);
256 impl<'a> HashStable<StableHashingContext<'a>>
257 for tokenstream::TokenTree {
258 fn hash_stable<W: StableHasherResult>(&self,
259 hcx: &mut StableHashingContext<'a>,
260 hasher: &mut StableHasher<W>) {
261 mem::discriminant(self).hash_stable(hcx, hasher);
263 tokenstream::TokenTree::Token(ref token) => {
264 token.hash_stable(hcx, hasher);
266 tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
267 span.hash_stable(hcx, hasher);
268 std_hash::Hash::hash(&delim, hasher);
269 for sub_tt in tts.trees() {
270 sub_tt.hash_stable(hcx, hasher);
277 impl<'a> HashStable<StableHashingContext<'a>>
278 for tokenstream::TokenStream {
279 fn hash_stable<W: StableHasherResult>(&self,
280 hcx: &mut StableHashingContext<'a>,
281 hasher: &mut StableHasher<W>) {
282 for sub_tt in self.trees() {
283 sub_tt.hash_stable(hcx, hasher);
288 impl_stable_hash_for!(enum token::LitKind {
301 impl_stable_hash_for!(struct token::Lit {
307 impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
308 fn hash_stable<W: StableHasherResult>(&self,
309 hcx: &mut StableHashingContext<'a>,
310 hasher: &mut StableHasher<W>) {
311 mem::discriminant(self).hash_stable(hcx, hasher);
344 token::BinOp(bin_op_token) |
345 token::BinOpEq(bin_op_token) => {
346 std_hash::Hash::hash(&bin_op_token, hasher);
349 token::OpenDelim(delim_token) |
350 token::CloseDelim(delim_token) => {
351 std_hash::Hash::hash(&delim_token, hasher);
353 token::Literal(lit) => lit.hash_stable(hcx, hasher),
355 token::Ident(name, is_raw) => {
356 name.hash_stable(hcx, hasher);
357 is_raw.hash_stable(hcx, hasher);
359 token::Lifetime(name) => name.hash_stable(hcx, hasher),
361 token::Interpolated(_) => {
362 bug!("interpolated tokens should not be present in the HIR")
365 token::DocComment(val) |
366 token::Shebang(val) |
367 token::Unknown(val) => val.hash_stable(hcx, hasher),
372 impl_stable_hash_for!(struct token::Token {
377 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
382 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
388 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
394 impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
400 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
404 default_transparency,
405 allow_internal_unstable,
406 allow_internal_unsafe,
411 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
417 impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
427 impl_stable_hash_for!(enum ::syntax_pos::FileName {
433 ProcMacroSourceCode(s),
440 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
441 fn hash_stable<W: StableHasherResult>(&self,
442 hcx: &mut StableHashingContext<'a>,
443 hasher: &mut StableHasher<W>) {
445 name: _, // We hash the smaller name_hash instead of this
450 // Do not hash the source as it is not encoded
458 ref non_narrow_chars,
461 (name_hash as u64).hash_stable(hcx, hasher);
462 name_was_remapped.hash_stable(hcx, hasher);
465 krate: CrateNum::from_u32(crate_of_origin),
466 index: CRATE_DEF_INDEX,
467 }.hash_stable(hcx, hasher);
469 src_hash.hash_stable(hcx, hasher);
471 // We only hash the relative position within this source_file
472 lines.len().hash_stable(hcx, hasher);
473 for &line in lines.iter() {
474 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
477 // We only hash the relative position within this source_file
478 multibyte_chars.len().hash_stable(hcx, hasher);
479 for &char_pos in multibyte_chars.iter() {
480 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
483 non_narrow_chars.len().hash_stable(hcx, hasher);
484 for &char_pos in non_narrow_chars.iter() {
485 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
490 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
491 source_file_start: ::syntax_pos::BytePos)
493 pos.0 - source_file_start.0
496 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
497 source_file_start: ::syntax_pos::BytePos)
499 let ::syntax_pos::MultiByteChar {
504 (pos.0 - source_file_start.0, bytes as u32)
507 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
508 source_file_start: ::syntax_pos::BytePos)
511 let width = swc.width();
513 (pos.0 - source_file_start.0, width as u32)
516 impl<'tcx> HashStable<StableHashingContext<'tcx>> for feature_gate::Features {
517 fn hash_stable<W: StableHasherResult>(
519 hcx: &mut StableHashingContext<'tcx>,
520 hasher: &mut StableHasher<W>,
522 // Unfortunately we cannot exhaustively list fields here, since the
523 // struct is macro generated.
524 self.declared_lang_features.hash_stable(hcx, hasher);
525 self.declared_lib_features.hash_stable(hcx, hasher);
527 self.walk_feature_fields(|feature_name, value| {
528 feature_name.hash_stable(hcx, hasher);
529 value.hash_stable(hcx, hasher);