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::parse::token;
21 use syntax::symbol::InternedString;
22 use syntax::tokenstream;
23 use syntax_pos::FileMap;
25 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
27 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
28 StableHasher, StableHasherResult};
29 use rustc_data_structures::accumulate_vec::AccumulateVec;
31 impl<'gcx> HashStable<StableHashingContext<'gcx>> for InternedString {
33 fn hash_stable<W: StableHasherResult>(&self,
34 hcx: &mut StableHashingContext<'gcx>,
35 hasher: &mut StableHasher<W>) {
36 let s: &str = &**self;
37 s.hash_stable(hcx, hasher);
41 impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for InternedString {
42 type KeyType = InternedString;
45 fn to_stable_hash_key(&self,
46 _: &StableHashingContext<'gcx>)
52 impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Name {
54 fn hash_stable<W: StableHasherResult>(&self,
55 hcx: &mut StableHashingContext<'gcx>,
56 hasher: &mut StableHasher<W>) {
57 self.as_str().hash_stable(hcx, hasher);
61 impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for ast::Name {
62 type KeyType = InternedString;
65 fn to_stable_hash_key(&self,
66 _: &StableHashingContext<'gcx>)
72 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
77 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
84 impl_stable_hash_for!(enum ::syntax::abi::Abi {
105 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
106 impl_stable_hash_for!(struct ::syntax::attr::Stability {
113 impl<'gcx> HashStable<StableHashingContext<'gcx>>
114 for ::syntax::attr::StabilityLevel {
115 fn hash_stable<W: StableHasherResult>(&self,
116 hcx: &mut StableHashingContext<'gcx>,
117 hasher: &mut StableHasher<W>) {
118 mem::discriminant(self).hash_stable(hcx, hasher);
120 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
121 reason.hash_stable(hcx, hasher);
122 issue.hash_stable(hcx, hasher);
124 ::syntax::attr::StabilityLevel::Stable { ref since } => {
125 since.hash_stable(hcx, hasher);
131 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
132 impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
135 impl_stable_hash_for!(enum ::syntax::attr::IntType {
140 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
146 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
147 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
152 Int(value, lit_int_type),
153 Float(value, float_ty),
154 FloatUnsuffixed(value),
158 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
159 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
160 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
161 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
162 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
163 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
164 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
165 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
166 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
168 impl<'gcx> HashStable<StableHashingContext<'gcx>> for [ast::Attribute] {
169 fn hash_stable<W: StableHasherResult>(&self,
170 hcx: &mut StableHashingContext<'gcx>,
171 hasher: &mut StableHasher<W>) {
173 self.len().hash_stable(hcx, hasher);
177 // Some attributes are always ignored during hashing.
178 let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
181 !attr.is_sugared_doc &&
182 attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
186 filtered.len().hash_stable(hcx, hasher);
187 for attr in filtered {
188 attr.hash_stable(hcx, hasher);
193 impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
194 fn hash_stable<W: StableHasherResult>(&self,
195 hcx: &mut StableHashingContext<'gcx>,
196 hasher: &mut StableHasher<W>) {
197 // Make sure that these have been filtered out.
198 debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
199 debug_assert!(!self.is_sugared_doc);
210 style.hash_stable(hcx, hasher);
211 path.segments.len().hash_stable(hcx, hasher);
212 for segment in &path.segments {
213 segment.identifier.name.hash_stable(hcx, hasher);
215 for tt in tokens.trees() {
216 tt.hash_stable(hcx, hasher);
218 span.hash_stable(hcx, hasher);
222 impl<'gcx> HashStable<StableHashingContext<'gcx>>
223 for tokenstream::TokenTree {
224 fn hash_stable<W: StableHasherResult>(&self,
225 hcx: &mut StableHashingContext<'gcx>,
226 hasher: &mut StableHasher<W>) {
227 mem::discriminant(self).hash_stable(hcx, hasher);
229 tokenstream::TokenTree::Token(span, ref token) => {
230 span.hash_stable(hcx, hasher);
231 hash_token(token, hcx, hasher);
233 tokenstream::TokenTree::Delimited(span, ref delimited) => {
234 span.hash_stable(hcx, hasher);
235 std_hash::Hash::hash(&delimited.delim, hasher);
236 for sub_tt in delimited.stream().trees() {
237 sub_tt.hash_stable(hcx, hasher);
244 impl<'gcx> HashStable<StableHashingContext<'gcx>>
245 for tokenstream::TokenStream {
246 fn hash_stable<W: StableHasherResult>(&self,
247 hcx: &mut StableHashingContext<'gcx>,
248 hasher: &mut StableHasher<W>) {
249 for sub_tt in self.trees() {
250 sub_tt.hash_stable(hcx, hasher);
255 fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
256 hcx: &mut StableHashingContext<'gcx>,
257 hasher: &mut StableHasher<W>) {
258 mem::discriminant(token).hash_stable(hcx, hasher);
267 token::Token::AndAnd |
270 token::Token::Tilde |
273 token::Token::DotDot |
274 token::Token::DotDotDot |
275 token::Token::DotDotEq |
276 token::Token::DotEq |
277 token::Token::Comma |
279 token::Token::Colon |
280 token::Token::ModSep |
281 token::Token::RArrow |
282 token::Token::LArrow |
283 token::Token::FatArrow |
284 token::Token::Pound |
285 token::Token::Dollar |
286 token::Token::Question |
287 token::Token::Underscore |
288 token::Token::Whitespace |
289 token::Token::Comment |
290 token::Token::Eof => {}
292 token::Token::BinOp(bin_op_token) |
293 token::Token::BinOpEq(bin_op_token) => {
294 std_hash::Hash::hash(&bin_op_token, hasher);
297 token::Token::OpenDelim(delim_token) |
298 token::Token::CloseDelim(delim_token) => {
299 std_hash::Hash::hash(&delim_token, hasher);
301 token::Token::Literal(ref lit, ref opt_name) => {
302 mem::discriminant(lit).hash_stable(hcx, hasher);
304 token::Lit::Byte(val) |
305 token::Lit::Char(val) |
306 token::Lit::Integer(val) |
307 token::Lit::Float(val) |
308 token::Lit::Str_(val) |
309 token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
310 token::Lit::StrRaw(val, n) |
311 token::Lit::ByteStrRaw(val, n) => {
312 val.hash_stable(hcx, hasher);
313 n.hash_stable(hcx, hasher);
316 opt_name.hash_stable(hcx, hasher);
319 token::Token::Ident(ident) |
320 token::Token::Lifetime(ident) => ident.name.hash_stable(hcx, hasher),
322 token::Token::Interpolated(_) => {
323 bug!("interpolated tokens should not be present in the HIR")
326 token::Token::DocComment(val) |
327 token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
331 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
333 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
338 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
344 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
350 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
355 impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
357 allow_internal_unstable,
358 allow_internal_unsafe,
362 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
365 CompilerDesugaring(kind)
368 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
374 impl_stable_hash_for!(enum ::syntax_pos::FileName {
385 impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
386 fn hash_stable<W: StableHasherResult>(&self,
387 hcx: &mut StableHashingContext<'gcx>,
388 hasher: &mut StableHasher<W>) {
390 name: _, // We hash the smaller name_hash instead of this
395 // Do not hash the source as it is not encoded
403 ref non_narrow_chars,
406 (name_hash as u64).hash_stable(hcx, hasher);
407 name_was_remapped.hash_stable(hcx, hasher);
410 krate: CrateNum::from_u32(crate_of_origin),
411 index: CRATE_DEF_INDEX,
412 }.hash_stable(hcx, hasher);
414 src_hash.hash_stable(hcx, hasher);
416 // We only hash the relative position within this filemap
417 let lines = lines.borrow();
418 lines.len().hash_stable(hcx, hasher);
419 for &line in lines.iter() {
420 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
423 // We only hash the relative position within this filemap
424 let multibyte_chars = multibyte_chars.borrow();
425 multibyte_chars.len().hash_stable(hcx, hasher);
426 for &char_pos in multibyte_chars.iter() {
427 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
430 let non_narrow_chars = non_narrow_chars.borrow();
431 non_narrow_chars.len().hash_stable(hcx, hasher);
432 for &char_pos in non_narrow_chars.iter() {
433 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
438 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
439 filemap_start: ::syntax_pos::BytePos)
441 pos.0 - filemap_start.0
444 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
445 filemap_start: ::syntax_pos::BytePos)
447 let ::syntax_pos::MultiByteChar {
452 (pos.0 - filemap_start.0, bytes as u32)
455 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
456 filemap_start: ::syntax_pos::BytePos)
459 let width = swc.width();
461 (pos.0 - filemap_start.0, width as u32)