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;
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 let s: &str = &**self;
38 s.hash_stable(hcx, hasher);
42 impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
43 type KeyType = InternedString;
46 fn to_stable_hash_key(&self,
47 _: &StableHashingContext<'a>)
53 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
55 fn hash_stable<W: StableHasherResult>(&self,
56 hcx: &mut StableHashingContext<'a>,
57 hasher: &mut StableHasher<W>) {
58 self.as_str().hash_stable(hcx, hasher);
62 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
63 type KeyType = InternedString;
66 fn to_stable_hash_key(&self,
67 _: &StableHashingContext<'a>)
73 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
78 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
85 impl_stable_hash_for!(enum ::syntax::abi::Abi {
106 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
107 impl_stable_hash_for!(struct ::syntax::attr::Stability {
114 impl<'a> HashStable<StableHashingContext<'a>>
115 for ::syntax::attr::StabilityLevel {
116 fn hash_stable<W: StableHasherResult>(&self,
117 hcx: &mut StableHashingContext<'a>,
118 hasher: &mut StableHasher<W>) {
119 mem::discriminant(self).hash_stable(hcx, hasher);
121 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
122 reason.hash_stable(hcx, hasher);
123 issue.hash_stable(hcx, hasher);
125 ::syntax::attr::StabilityLevel::Stable { ref since } => {
126 since.hash_stable(hcx, hasher);
132 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
133 impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
136 impl_stable_hash_for!(enum ::syntax::attr::IntType {
141 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
147 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
148 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
153 Int(value, lit_int_type),
154 Float(value, float_ty),
155 FloatUnsuffixed(value),
159 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
160 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
161 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
162 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
163 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
164 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
165 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
166 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
167 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
169 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
170 fn hash_stable<W: StableHasherResult>(&self,
171 hcx: &mut StableHashingContext<'a>,
172 hasher: &mut StableHasher<W>) {
174 self.len().hash_stable(hcx, hasher);
178 // Some attributes are always ignored during hashing.
179 let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
182 !attr.is_sugared_doc &&
183 attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
187 filtered.len().hash_stable(hcx, hasher);
188 for attr in filtered {
189 attr.hash_stable(hcx, hasher);
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>) {
198 // Make sure that these have been filtered out.
199 debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
200 debug_assert!(!self.is_sugared_doc);
211 style.hash_stable(hcx, hasher);
212 path.segments.len().hash_stable(hcx, hasher);
213 for segment in &path.segments {
214 segment.ident.name.hash_stable(hcx, hasher);
216 for tt in tokens.trees() {
217 tt.hash_stable(hcx, hasher);
219 span.hash_stable(hcx, hasher);
223 impl<'a> HashStable<StableHashingContext<'a>>
224 for tokenstream::TokenTree {
225 fn hash_stable<W: StableHasherResult>(&self,
226 hcx: &mut StableHashingContext<'a>,
227 hasher: &mut StableHasher<W>) {
228 mem::discriminant(self).hash_stable(hcx, hasher);
230 tokenstream::TokenTree::Token(span, ref token) => {
231 span.hash_stable(hcx, hasher);
232 hash_token(token, hcx, hasher);
234 tokenstream::TokenTree::Delimited(span, ref delimited) => {
235 span.hash_stable(hcx, hasher);
236 std_hash::Hash::hash(&delimited.delim, hasher);
237 for sub_tt in delimited.stream().trees() {
238 sub_tt.hash_stable(hcx, hasher);
245 impl<'a> HashStable<StableHashingContext<'a>>
246 for tokenstream::TokenStream {
247 fn hash_stable<W: StableHasherResult>(&self,
248 hcx: &mut StableHashingContext<'a>,
249 hasher: &mut StableHasher<W>) {
250 for sub_tt in self.trees() {
251 sub_tt.hash_stable(hcx, hasher);
256 fn hash_token<'a, 'gcx, W: StableHasherResult>(
257 token: &token::Token,
258 hcx: &mut StableHashingContext<'a>,
259 hasher: &mut StableHasher<W>,
261 mem::discriminant(token).hash_stable(hcx, hasher);
270 token::Token::AndAnd |
273 token::Token::Tilde |
276 token::Token::DotDot |
277 token::Token::DotDotDot |
278 token::Token::DotDotEq |
279 token::Token::DotEq |
280 token::Token::Comma |
282 token::Token::Colon |
283 token::Token::ModSep |
284 token::Token::RArrow |
285 token::Token::LArrow |
286 token::Token::FatArrow |
287 token::Token::Pound |
288 token::Token::Dollar |
289 token::Token::Question |
290 token::Token::Whitespace |
291 token::Token::Comment |
292 token::Token::Eof => {}
294 token::Token::BinOp(bin_op_token) |
295 token::Token::BinOpEq(bin_op_token) => {
296 std_hash::Hash::hash(&bin_op_token, hasher);
299 token::Token::OpenDelim(delim_token) |
300 token::Token::CloseDelim(delim_token) => {
301 std_hash::Hash::hash(&delim_token, hasher);
303 token::Token::Literal(ref lit, ref opt_name) => {
304 mem::discriminant(lit).hash_stable(hcx, hasher);
306 token::Lit::Byte(val) |
307 token::Lit::Char(val) |
308 token::Lit::Integer(val) |
309 token::Lit::Float(val) |
310 token::Lit::Str_(val) |
311 token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
312 token::Lit::StrRaw(val, n) |
313 token::Lit::ByteStrRaw(val, n) => {
314 val.hash_stable(hcx, hasher);
315 n.hash_stable(hcx, hasher);
318 opt_name.hash_stable(hcx, hasher);
321 token::Token::Ident(ident, is_raw) => {
322 ident.name.hash_stable(hcx, hasher);
323 is_raw.hash_stable(hcx, hasher);
325 token::Token::Lifetime(ident) => ident.name.hash_stable(hcx, hasher),
327 token::Token::Interpolated(_) => {
328 bug!("interpolated tokens should not be present in the HIR")
331 token::Token::DocComment(val) |
332 token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
336 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
338 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
343 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
349 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
355 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
360 impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
362 allow_internal_unstable,
363 allow_internal_unsafe,
367 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
370 CompilerDesugaring(kind)
373 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
378 impl_stable_hash_for!(enum ::syntax_pos::FileName {
389 impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
390 fn hash_stable<W: StableHasherResult>(&self,
391 hcx: &mut StableHashingContext<'a>,
392 hasher: &mut StableHasher<W>) {
394 name: _, // We hash the smaller name_hash instead of this
399 // Do not hash the source as it is not encoded
407 ref non_narrow_chars,
410 (name_hash as u64).hash_stable(hcx, hasher);
411 name_was_remapped.hash_stable(hcx, hasher);
414 krate: CrateNum::from_u32(crate_of_origin),
415 index: CRATE_DEF_INDEX,
416 }.hash_stable(hcx, hasher);
418 src_hash.hash_stable(hcx, hasher);
420 // We only hash the relative position within this filemap
421 lines.with_lock(|lines| {
422 lines.len().hash_stable(hcx, hasher);
423 for &line in lines.iter() {
424 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
428 // We only hash the relative position within this filemap
429 multibyte_chars.with_lock(|multibyte_chars| {
430 multibyte_chars.len().hash_stable(hcx, hasher);
431 for &char_pos in multibyte_chars.iter() {
432 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
436 non_narrow_chars.with_lock(|non_narrow_chars| {
437 non_narrow_chars.len().hash_stable(hcx, hasher);
438 for &char_pos in non_narrow_chars.iter() {
439 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
445 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
446 filemap_start: ::syntax_pos::BytePos)
448 pos.0 - filemap_start.0
451 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
452 filemap_start: ::syntax_pos::BytePos)
454 let ::syntax_pos::MultiByteChar {
459 (pos.0 - filemap_start.0, bytes as u32)
462 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
463 filemap_start: ::syntax_pos::BytePos)
466 let width = swc.width();
468 (pos.0 - filemap_start.0, width as u32)
473 impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
474 fn hash_stable<W: StableHasherResult>(&self,
475 hcx: &mut StableHashingContext<'gcx>,
476 hasher: &mut StableHasher<W>) {
477 // Unfortunately we cannot exhaustively list fields here, since the
478 // struct is macro generated.
479 self.declared_stable_lang_features.hash_stable(hcx, hasher);
480 self.declared_lib_features.hash_stable(hcx, hasher);
482 self.walk_feature_fields(|feature_name, value| {
483 feature_name.hash_stable(hcx, hasher);
484 value.hash_stable(hcx, hasher);