1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This module contains `HashStable` implementations for various data types
12 //! from libsyntax in no particular order.
14 use ich::StableHashingContext;
16 use std::hash as std_hash;
20 use syntax::feature_gate;
21 use syntax::parse::token;
22 use syntax::symbol::{InternedString, LocalInternedString};
23 use syntax::tokenstream;
24 use syntax_pos::FileMap;
26 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
28 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
29 StableHasher, StableHasherResult};
30 use rustc_data_structures::accumulate_vec::AccumulateVec;
32 impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
34 fn hash_stable<W: StableHasherResult>(&self,
35 hcx: &mut StableHashingContext<'a>,
36 hasher: &mut StableHasher<W>) {
37 self.with(|s| s.hash_stable(hcx, hasher))
41 impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
42 type KeyType = InternedString;
45 fn to_stable_hash_key(&self,
46 _: &StableHashingContext<'a>)
52 impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
54 fn hash_stable<W: StableHasherResult>(&self,
55 hcx: &mut StableHashingContext<'a>,
56 hasher: &mut StableHasher<W>) {
57 let s: &str = &**self;
58 s.hash_stable(hcx, hasher);
62 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
63 type KeyType = LocalInternedString;
66 fn to_stable_hash_key(&self,
67 _: &StableHashingContext<'a>)
68 -> LocalInternedString {
73 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
75 fn hash_stable<W: StableHasherResult>(&self,
76 hcx: &mut StableHashingContext<'a>,
77 hasher: &mut StableHasher<W>) {
78 self.as_str().hash_stable(hcx, hasher);
82 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
83 type KeyType = InternedString;
86 fn to_stable_hash_key(&self,
87 _: &StableHashingContext<'a>)
89 self.as_interned_str()
93 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
98 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
105 impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
126 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
127 impl_stable_hash_for!(struct ::syntax::attr::Stability {
134 impl<'a> HashStable<StableHashingContext<'a>>
135 for ::syntax::edition::Edition {
136 fn hash_stable<W: StableHasherResult>(&self,
137 hcx: &mut StableHashingContext<'a>,
138 hasher: &mut StableHasher<W>) {
139 mem::discriminant(self).hash_stable(hcx, hasher);
143 impl<'a> HashStable<StableHashingContext<'a>>
144 for ::syntax::attr::StabilityLevel {
145 fn hash_stable<W: StableHasherResult>(&self,
146 hcx: &mut StableHashingContext<'a>,
147 hasher: &mut StableHasher<W>) {
148 mem::discriminant(self).hash_stable(hcx, hasher);
150 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
151 reason.hash_stable(hcx, hasher);
152 issue.hash_stable(hcx, hasher);
154 ::syntax::attr::StabilityLevel::Stable { ref since } => {
155 since.hash_stable(hcx, hasher);
161 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
162 impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
165 impl_stable_hash_for!(enum ::syntax::attr::IntType {
170 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
176 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
177 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
182 Int(value, lit_int_type),
183 Float(value, float_ty),
184 FloatUnsuffixed(value),
188 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
189 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
190 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
191 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
192 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
193 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
194 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
195 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
196 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
198 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
199 fn hash_stable<W: StableHasherResult>(&self,
200 hcx: &mut StableHashingContext<'a>,
201 hasher: &mut StableHasher<W>) {
203 self.len().hash_stable(hcx, hasher);
207 // Some attributes are always ignored during hashing.
208 let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
211 !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
215 filtered.len().hash_stable(hcx, hasher);
216 for attr in filtered {
217 attr.hash_stable(hcx, hasher);
222 impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
223 fn hash_stable<W: StableHasherResult>(&self,
224 hcx: &mut StableHashingContext<'a>,
225 hasher: &mut StableHasher<W>) {
226 self.segments.len().hash_stable(hcx, hasher);
227 for segment in &self.segments {
228 segment.ident.name.hash_stable(hcx, hasher);
233 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
234 fn hash_stable<W: StableHasherResult>(&self,
235 hcx: &mut StableHashingContext<'a>,
236 hasher: &mut StableHasher<W>) {
237 // Make sure that these have been filtered out.
238 debug_assert!(!hcx.is_ignored_attr(self.name()));
239 debug_assert!(!self.is_sugared_doc);
250 style.hash_stable(hcx, hasher);
251 path.hash_stable(hcx, hasher);
252 for tt in tokens.trees() {
253 tt.hash_stable(hcx, hasher);
255 span.hash_stable(hcx, hasher);
259 impl<'a> HashStable<StableHashingContext<'a>>
260 for tokenstream::TokenTree {
261 fn hash_stable<W: StableHasherResult>(&self,
262 hcx: &mut StableHashingContext<'a>,
263 hasher: &mut StableHasher<W>) {
264 mem::discriminant(self).hash_stable(hcx, hasher);
266 tokenstream::TokenTree::Token(span, ref token) => {
267 span.hash_stable(hcx, hasher);
268 hash_token(token, hcx, hasher);
270 tokenstream::TokenTree::Delimited(span, ref delimited) => {
271 span.hash_stable(hcx, hasher);
272 std_hash::Hash::hash(&delimited.delim, hasher);
273 for sub_tt in delimited.stream().trees() {
274 sub_tt.hash_stable(hcx, hasher);
281 impl<'a> HashStable<StableHashingContext<'a>>
282 for tokenstream::TokenStream {
283 fn hash_stable<W: StableHasherResult>(&self,
284 hcx: &mut StableHashingContext<'a>,
285 hasher: &mut StableHasher<W>) {
286 for sub_tt in self.trees() {
287 sub_tt.hash_stable(hcx, hasher);
292 fn hash_token<'a, 'gcx, W: StableHasherResult>(
293 token: &token::Token,
294 hcx: &mut StableHashingContext<'a>,
295 hasher: &mut StableHasher<W>,
297 mem::discriminant(token).hash_stable(hcx, hasher);
306 token::Token::AndAnd |
309 token::Token::Tilde |
312 token::Token::DotDot |
313 token::Token::DotDotDot |
314 token::Token::DotDotEq |
315 token::Token::DotEq |
316 token::Token::Comma |
318 token::Token::Colon |
319 token::Token::ModSep |
320 token::Token::RArrow |
321 token::Token::LArrow |
322 token::Token::FatArrow |
323 token::Token::Pound |
324 token::Token::Dollar |
325 token::Token::Question |
326 token::Token::SingleQuote |
327 token::Token::Whitespace |
328 token::Token::Comment |
329 token::Token::Eof => {}
331 token::Token::BinOp(bin_op_token) |
332 token::Token::BinOpEq(bin_op_token) => {
333 std_hash::Hash::hash(&bin_op_token, hasher);
336 token::Token::OpenDelim(delim_token) |
337 token::Token::CloseDelim(delim_token) => {
338 std_hash::Hash::hash(&delim_token, hasher);
340 token::Token::Literal(ref lit, ref opt_name) => {
341 mem::discriminant(lit).hash_stable(hcx, hasher);
343 token::Lit::Byte(val) |
344 token::Lit::Char(val) |
345 token::Lit::Integer(val) |
346 token::Lit::Float(val) |
347 token::Lit::Str_(val) |
348 token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
349 token::Lit::StrRaw(val, n) |
350 token::Lit::ByteStrRaw(val, n) => {
351 val.hash_stable(hcx, hasher);
352 n.hash_stable(hcx, hasher);
355 opt_name.hash_stable(hcx, hasher);
358 token::Token::Ident(ident, is_raw) => {
359 ident.name.hash_stable(hcx, hasher);
360 is_raw.hash_stable(hcx, hasher);
362 token::Token::Lifetime(ident) => ident.name.hash_stable(hcx, hasher),
364 token::Token::Interpolated(_) => {
365 bug!("interpolated tokens should not be present in the HIR")
368 token::Token::DocComment(val) |
369 token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
373 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
375 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
380 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
386 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
392 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
397 impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
399 allow_internal_unstable,
400 allow_internal_unsafe,
405 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
408 CompilerDesugaring(kind)
411 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
414 ExistentialReturnType,
418 impl_stable_hash_for!(enum ::syntax_pos::FileName {
429 impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
430 fn hash_stable<W: StableHasherResult>(&self,
431 hcx: &mut StableHashingContext<'a>,
432 hasher: &mut StableHasher<W>) {
434 name: _, // We hash the smaller name_hash instead of this
439 // Do not hash the source as it is not encoded
447 ref non_narrow_chars,
450 (name_hash as u64).hash_stable(hcx, hasher);
451 name_was_remapped.hash_stable(hcx, hasher);
454 krate: CrateNum::from_u32(crate_of_origin),
455 index: CRATE_DEF_INDEX,
456 }.hash_stable(hcx, hasher);
458 src_hash.hash_stable(hcx, hasher);
460 // We only hash the relative position within this filemap
461 lines.with_lock(|lines| {
462 lines.len().hash_stable(hcx, hasher);
463 for &line in lines.iter() {
464 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
468 // We only hash the relative position within this filemap
469 multibyte_chars.with_lock(|multibyte_chars| {
470 multibyte_chars.len().hash_stable(hcx, hasher);
471 for &char_pos in multibyte_chars.iter() {
472 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
476 non_narrow_chars.with_lock(|non_narrow_chars| {
477 non_narrow_chars.len().hash_stable(hcx, hasher);
478 for &char_pos in non_narrow_chars.iter() {
479 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
485 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
486 filemap_start: ::syntax_pos::BytePos)
488 pos.0 - filemap_start.0
491 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
492 filemap_start: ::syntax_pos::BytePos)
494 let ::syntax_pos::MultiByteChar {
499 (pos.0 - filemap_start.0, bytes as u32)
502 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
503 filemap_start: ::syntax_pos::BytePos)
506 let width = swc.width();
508 (pos.0 - filemap_start.0, width as u32)
513 impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
514 fn hash_stable<W: StableHasherResult>(&self,
515 hcx: &mut StableHashingContext<'gcx>,
516 hasher: &mut StableHasher<W>) {
517 // Unfortunately we cannot exhaustively list fields here, since the
518 // struct is macro generated.
519 self.declared_stable_lang_features.hash_stable(hcx, hasher);
520 self.declared_lib_features.hash_stable(hcx, hasher);
522 self.walk_feature_fields(|feature_name, value| {
523 feature_name.hash_stable(hcx, hasher);
524 value.hash_stable(hcx, hasher);