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
);