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::tokenstream;
22 use syntax_pos::{Span, FileMap};
24 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
26 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
28 use rustc_data_structures::accumulate_vec::AccumulateVec;
30 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::symbol::InternedString {
32 fn hash_stable<W: StableHasherResult>(&self,
33 hcx: &mut StableHashingContext<'a, 'tcx>,
34 hasher: &mut StableHasher<W>) {
35 let s: &str = &**self;
36 s.hash_stable(hcx, hasher);
40 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Name {
42 fn hash_stable<W: StableHasherResult>(&self,
43 hcx: &mut StableHashingContext<'a, 'tcx>,
44 hasher: &mut StableHasher<W>) {
45 self.as_str().hash_stable(hcx, hasher);
49 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
54 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
61 impl_stable_hash_for!(enum ::syntax::abi::Abi {
81 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
82 impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
84 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::attr::StabilityLevel {
85 fn hash_stable<W: StableHasherResult>(&self,
86 hcx: &mut StableHashingContext<'a, 'tcx>,
87 hasher: &mut StableHasher<W>) {
88 mem::discriminant(self).hash_stable(hcx, hasher);
90 ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
91 reason.hash_stable(hcx, hasher);
92 issue.hash_stable(hcx, hasher);
94 ::syntax::attr::StabilityLevel::Stable { ref since } => {
95 since.hash_stable(hcx, hasher);
101 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
104 impl_stable_hash_for!(enum ::syntax::attr::IntType {
109 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
115 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
116 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
121 Int(value, lit_int_type),
122 Float(value, float_ty),
123 FloatUnsuffixed(value),
127 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
128 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
129 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
130 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
131 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
132 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
133 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
134 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
135 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
137 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for [ast::Attribute] {
138 fn hash_stable<W: StableHasherResult>(&self,
139 hcx: &mut StableHashingContext<'a, 'tcx>,
140 hasher: &mut StableHasher<W>) {
141 // Some attributes are always ignored during hashing.
142 let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
145 !attr.is_sugared_doc &&
146 attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
150 filtered.len().hash_stable(hcx, hasher);
151 for attr in filtered {
152 attr.hash_stable(hcx, hasher);
157 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Attribute {
158 fn hash_stable<W: StableHasherResult>(&self,
159 hcx: &mut StableHashingContext<'a, 'tcx>,
160 hasher: &mut StableHasher<W>) {
161 // Make sure that these have been filtered out.
162 debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
163 debug_assert!(!self.is_sugared_doc);
174 style.hash_stable(hcx, hasher);
175 path.segments.len().hash_stable(hcx, hasher);
176 for segment in &path.segments {
177 segment.identifier.name.hash_stable(hcx, hasher);
179 for tt in tokens.trees() {
180 tt.hash_stable(hcx, hasher);
182 span.hash_stable(hcx, hasher);
186 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenTree {
187 fn hash_stable<W: StableHasherResult>(&self,
188 hcx: &mut StableHashingContext<'a, 'tcx>,
189 hasher: &mut StableHasher<W>) {
190 mem::discriminant(self).hash_stable(hcx, hasher);
192 tokenstream::TokenTree::Token(span, ref token) => {
193 span.hash_stable(hcx, hasher);
194 hash_token(token, hcx, hasher, span);
196 tokenstream::TokenTree::Delimited(span, ref delimited) => {
197 span.hash_stable(hcx, hasher);
198 std_hash::Hash::hash(&delimited.delim, hasher);
199 for sub_tt in delimited.stream().trees() {
200 sub_tt.hash_stable(hcx, hasher);
207 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenStream {
208 fn hash_stable<W: StableHasherResult>(&self,
209 hcx: &mut StableHashingContext<'a, 'tcx>,
210 hasher: &mut StableHasher<W>) {
211 for sub_tt in self.trees() {
212 sub_tt.hash_stable(hcx, hasher);
217 fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
218 hcx: &mut StableHashingContext<'a, 'tcx>,
219 hasher: &mut StableHasher<W>,
220 error_reporting_span: Span) {
221 mem::discriminant(token).hash_stable(hcx, hasher);
230 token::Token::AndAnd |
233 token::Token::Tilde |
236 token::Token::DotDot |
237 token::Token::DotDotDot |
238 token::Token::Comma |
240 token::Token::Colon |
241 token::Token::ModSep |
242 token::Token::RArrow |
243 token::Token::LArrow |
244 token::Token::FatArrow |
245 token::Token::Pound |
246 token::Token::Dollar |
247 token::Token::Question |
248 token::Token::Underscore |
249 token::Token::Whitespace |
250 token::Token::Comment |
251 token::Token::Eof => {}
253 token::Token::BinOp(bin_op_token) |
254 token::Token::BinOpEq(bin_op_token) => {
255 std_hash::Hash::hash(&bin_op_token, hasher);
258 token::Token::OpenDelim(delim_token) |
259 token::Token::CloseDelim(delim_token) => {
260 std_hash::Hash::hash(&delim_token, hasher);
262 token::Token::Literal(ref lit, ref opt_name) => {
263 mem::discriminant(lit).hash_stable(hcx, hasher);
265 token::Lit::Byte(val) |
266 token::Lit::Char(val) |
267 token::Lit::Integer(val) |
268 token::Lit::Float(val) |
269 token::Lit::Str_(val) |
270 token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
271 token::Lit::StrRaw(val, n) |
272 token::Lit::ByteStrRaw(val, n) => {
273 val.hash_stable(hcx, hasher);
274 n.hash_stable(hcx, hasher);
277 opt_name.hash_stable(hcx, hasher);
280 token::Token::Ident(ident) |
281 token::Token::Lifetime(ident) |
282 token::Token::SubstNt(ident) => ident.name.hash_stable(hcx, hasher),
284 token::Token::Interpolated(ref non_terminal) => {
285 // FIXME(mw): This could be implemented properly. It's just a
286 // lot of work, since we would need to hash the AST
287 // in a stable way, in addition to the HIR.
288 // Since this is hardly used anywhere, just emit a
290 if hcx.tcx().sess.opts.debugging_opts.incremental.is_some() {
291 let msg = format!("Quasi-quoting might make incremental \
292 compilation very inefficient: {:?}",
294 hcx.tcx().sess.span_warn(error_reporting_span, &msg[..]);
297 std_hash::Hash::hash(non_terminal, hasher);
300 token::Token::DocComment(val) |
301 token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
305 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
307 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
312 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
318 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
324 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for FileMap {
325 fn hash_stable<W: StableHasherResult>(&self,
326 hcx: &mut StableHashingContext<'a, 'tcx>,
327 hasher: &mut StableHasher<W>) {
332 // Do not hash the source as it is not encoded
340 name.hash_stable(hcx, hasher);
341 name_was_remapped.hash_stable(hcx, hasher);
344 krate: CrateNum::from_u32(crate_of_origin),
345 index: CRATE_DEF_INDEX,
346 }.hash_stable(hcx, hasher);
348 // We only hash the relative position within this filemap
349 let lines = lines.borrow();
350 lines.len().hash_stable(hcx, hasher);
351 for &line in lines.iter() {
352 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
355 // We only hash the relative position within this filemap
356 let multibyte_chars = multibyte_chars.borrow();
357 multibyte_chars.len().hash_stable(hcx, hasher);
358 for &char_pos in multibyte_chars.iter() {
359 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
364 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
365 filemap_start: ::syntax_pos::BytePos)
367 pos.0 - filemap_start.0
370 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
371 filemap_start: ::syntax_pos::BytePos)
373 let ::syntax_pos::MultiByteChar {
378 (pos.0 - filemap_start.0, bytes as u32)