1 //! This module contains `HashStable` implementations for various data types
2 //! from libsyntax in no particular order.
4 use crate::ich
::StableHashingContext
;
6 use std
::hash
as std_hash
;
10 use syntax
::feature_gate
;
11 use syntax
::parse
::token
;
12 use syntax
::symbol
::{InternedString, LocalInternedString}
;
13 use syntax
::tokenstream
;
14 use syntax_pos
::SourceFile
;
16 use crate::hir
::def_id
::{DefId, CrateNum, CRATE_DEF_INDEX}
;
18 use smallvec
::SmallVec
;
19 use rustc_data_structures
::stable_hasher
::{HashStable
, ToStableHashKey
,
20 StableHasher
, StableHasherResult
};
22 impl<'a
> HashStable
<StableHashingContext
<'a
>> for InternedString
{
24 fn hash_stable
<W
: StableHasherResult
>(&self,
25 hcx
: &mut StableHashingContext
<'a
>,
26 hasher
: &mut StableHasher
<W
>) {
27 self.with(|s
| s
.hash_stable(hcx
, hasher
))
31 impl<'a
> ToStableHashKey
<StableHashingContext
<'a
>> for InternedString
{
32 type KeyType
= InternedString
;
35 fn to_stable_hash_key(&self,
36 _
: &StableHashingContext
<'a
>)
42 impl<'a
> HashStable
<StableHashingContext
<'a
>> for LocalInternedString
{
44 fn hash_stable
<W
: StableHasherResult
>(&self,
45 hcx
: &mut StableHashingContext
<'a
>,
46 hasher
: &mut StableHasher
<W
>) {
47 let s
: &str = &**self;
48 s
.hash_stable(hcx
, hasher
);
52 impl<'a
> ToStableHashKey
<StableHashingContext
<'a
>> for LocalInternedString
{
53 type KeyType
= LocalInternedString
;
56 fn to_stable_hash_key(&self,
57 _
: &StableHashingContext
<'a
>)
58 -> LocalInternedString
{
63 impl<'a
> HashStable
<StableHashingContext
<'a
>> for ast
::Name
{
65 fn hash_stable
<W
: StableHasherResult
>(&self,
66 hcx
: &mut StableHashingContext
<'a
>,
67 hasher
: &mut StableHasher
<W
>) {
68 self.as_str().hash_stable(hcx
, hasher
);
72 impl<'a
> ToStableHashKey
<StableHashingContext
<'a
>> for ast
::Name
{
73 type KeyType
= InternedString
;
76 fn to_stable_hash_key(&self,
77 _
: &StableHashingContext
<'a
>)
79 self.as_interned_str()
83 impl_stable_hash_for
!(enum ::syntax
::ast
::AsmDialect
{
88 impl_stable_hash_for
!(enum ::syntax
::ext
::base
::MacroKind
{
96 impl_stable_hash_for
!(enum ::rustc_target
::spec
::abi
::Abi
{
118 impl_stable_hash_for
!(struct ::syntax
::attr
::Deprecation { since, note }
);
119 impl_stable_hash_for
!(struct ::syntax
::attr
::Stability
{
127 impl_stable_hash_for
!(enum ::syntax
::edition
::Edition
{
132 impl<'a
> HashStable
<StableHashingContext
<'a
>>
133 for ::syntax
::attr
::StabilityLevel
{
134 fn hash_stable
<W
: StableHasherResult
>(&self,
135 hcx
: &mut StableHashingContext
<'a
>,
136 hasher
: &mut StableHasher
<W
>) {
137 mem
::discriminant(self).hash_stable(hcx
, hasher
);
139 ::syntax
::attr
::StabilityLevel
::Unstable { ref reason, ref issue }
=> {
140 reason
.hash_stable(hcx
, hasher
);
141 issue
.hash_stable(hcx
, hasher
);
143 ::syntax
::attr
::StabilityLevel
::Stable { ref since }
=> {
144 since
.hash_stable(hcx
, hasher
);
150 impl_stable_hash_for
!(struct ::syntax
::attr
::RustcDeprecation { since, reason, suggestion }
);
153 impl_stable_hash_for
!(enum ::syntax
::attr
::IntType
{
158 impl_stable_hash_for
!(enum ::syntax
::ast
::LitIntType
{
164 impl_stable_hash_for_spanned
!(::syntax
::ast
::LitKind
);
165 impl_stable_hash_for
!(enum ::syntax
::ast
::LitKind
{
171 Int(value
, lit_int_type
),
172 Float(value
, float_ty
),
173 FloatUnsuffixed(value
),
177 impl_stable_hash_for
!(enum ::syntax
::ast
::IntTy { Isize, I8, I16, I32, I64, I128 }
);
178 impl_stable_hash_for
!(enum ::syntax
::ast
::UintTy { Usize, U8, U16, U32, U64, U128 }
);
179 impl_stable_hash_for
!(enum ::syntax
::ast
::FloatTy { F32, F64 }
);
180 impl_stable_hash_for
!(enum ::syntax
::ast
::Unsafety { Unsafe, Normal }
);
181 impl_stable_hash_for
!(enum ::syntax
::ast
::Constness { Const, NotConst }
);
182 impl_stable_hash_for
!(enum ::syntax
::ast
::Defaultness { Default, Final }
);
183 impl_stable_hash_for
!(struct ::syntax
::ast
::Lifetime { id, ident }
);
184 impl_stable_hash_for
!(enum ::syntax
::ast
::StrStyle { Cooked, Raw(pounds) }
);
185 impl_stable_hash_for
!(enum ::syntax
::ast
::AttrStyle { Outer, Inner }
);
187 impl<'a
> HashStable
<StableHashingContext
<'a
>> for [ast
::Attribute
] {
188 fn hash_stable
<W
: StableHasherResult
>(&self,
189 hcx
: &mut StableHashingContext
<'a
>,
190 hasher
: &mut StableHasher
<W
>) {
192 self.len().hash_stable(hcx
, hasher
);
196 // Some attributes are always ignored during hashing.
197 let filtered
: SmallVec
<[&ast
::Attribute
; 8]> = self
200 !attr
.is_sugared_doc
&&
201 !attr
.ident().map_or(false, |ident
| hcx
.is_ignored_attr(ident
.name
))
205 filtered
.len().hash_stable(hcx
, hasher
);
206 for attr
in filtered
{
207 attr
.hash_stable(hcx
, hasher
);
212 impl<'a
> HashStable
<StableHashingContext
<'a
>> for ast
::Path
{
213 fn hash_stable
<W
: StableHasherResult
>(&self,
214 hcx
: &mut StableHashingContext
<'a
>,
215 hasher
: &mut StableHasher
<W
>) {
216 self.segments
.len().hash_stable(hcx
, hasher
);
217 for segment
in &self.segments
{
218 segment
.ident
.name
.hash_stable(hcx
, hasher
);
223 impl<'a
> HashStable
<StableHashingContext
<'a
>> for ast
::Attribute
{
224 fn hash_stable
<W
: StableHasherResult
>(&self,
225 hcx
: &mut StableHashingContext
<'a
>,
226 hasher
: &mut StableHasher
<W
>) {
227 // Make sure that these have been filtered out.
228 debug_assert
!(!self.ident().map_or(false, |ident
| hcx
.is_ignored_attr(ident
.name
)));
229 debug_assert
!(!self.is_sugared_doc
);
240 style
.hash_stable(hcx
, hasher
);
241 path
.hash_stable(hcx
, hasher
);
242 for tt
in tokens
.trees() {
243 tt
.hash_stable(hcx
, hasher
);
245 span
.hash_stable(hcx
, hasher
);
249 impl<'a
> HashStable
<StableHashingContext
<'a
>>
250 for tokenstream
::TokenTree
{
251 fn hash_stable
<W
: StableHasherResult
>(&self,
252 hcx
: &mut StableHashingContext
<'a
>,
253 hasher
: &mut StableHasher
<W
>) {
254 mem
::discriminant(self).hash_stable(hcx
, hasher
);
256 tokenstream
::TokenTree
::Token(span
, ref token
) => {
257 span
.hash_stable(hcx
, hasher
);
258 hash_token(token
, hcx
, hasher
);
260 tokenstream
::TokenTree
::Delimited(span
, delim
, ref tts
) => {
261 span
.hash_stable(hcx
, hasher
);
262 std_hash
::Hash
::hash(&delim
, hasher
);
263 for sub_tt
in tts
.trees() {
264 sub_tt
.hash_stable(hcx
, hasher
);
271 impl<'a
> HashStable
<StableHashingContext
<'a
>>
272 for tokenstream
::TokenStream
{
273 fn hash_stable
<W
: StableHasherResult
>(&self,
274 hcx
: &mut StableHashingContext
<'a
>,
275 hasher
: &mut StableHasher
<W
>) {
276 for sub_tt
in self.trees() {
277 sub_tt
.hash_stable(hcx
, hasher
);
282 fn hash_token
<'a
, 'gcx
, W
: StableHasherResult
>(
283 token
: &token
::Token
,
284 hcx
: &mut StableHashingContext
<'a
>,
285 hasher
: &mut StableHasher
<W
>,
287 mem
::discriminant(token
).hash_stable(hcx
, hasher
);
296 token
::Token
::AndAnd
|
299 token
::Token
::Tilde
|
302 token
::Token
::DotDot
|
303 token
::Token
::DotDotDot
|
304 token
::Token
::DotDotEq
|
305 token
::Token
::Comma
|
307 token
::Token
::Colon
|
308 token
::Token
::ModSep
|
309 token
::Token
::RArrow
|
310 token
::Token
::LArrow
|
311 token
::Token
::FatArrow
|
312 token
::Token
::Pound
|
313 token
::Token
::Dollar
|
314 token
::Token
::Question
|
315 token
::Token
::SingleQuote
|
316 token
::Token
::Whitespace
|
317 token
::Token
::Comment
|
318 token
::Token
::Eof
=> {}
320 token
::Token
::BinOp(bin_op_token
) |
321 token
::Token
::BinOpEq(bin_op_token
) => {
322 std_hash
::Hash
::hash(&bin_op_token
, hasher
);
325 token
::Token
::OpenDelim(delim_token
) |
326 token
::Token
::CloseDelim(delim_token
) => {
327 std_hash
::Hash
::hash(&delim_token
, hasher
);
329 token
::Token
::Literal(ref lit
, ref opt_name
) => {
330 mem
::discriminant(lit
).hash_stable(hcx
, hasher
);
332 token
::Lit
::Byte(val
) |
333 token
::Lit
::Char(val
) |
334 token
::Lit
::Err(val
) |
335 token
::Lit
::Integer(val
) |
336 token
::Lit
::Float(val
) |
337 token
::Lit
::Str_(val
) |
338 token
::Lit
::ByteStr(val
) => val
.hash_stable(hcx
, hasher
),
339 token
::Lit
::StrRaw(val
, n
) |
340 token
::Lit
::ByteStrRaw(val
, n
) => {
341 val
.hash_stable(hcx
, hasher
);
342 n
.hash_stable(hcx
, hasher
);
345 opt_name
.hash_stable(hcx
, hasher
);
348 token
::Token
::Ident(ident
, is_raw
) => {
349 ident
.name
.hash_stable(hcx
, hasher
);
350 is_raw
.hash_stable(hcx
, hasher
);
352 token
::Token
::Lifetime(ident
) => ident
.name
.hash_stable(hcx
, hasher
),
354 token
::Token
::Interpolated(_
) => {
355 bug
!("interpolated tokens should not be present in the HIR")
358 token
::Token
::DocComment(val
) |
359 token
::Token
::Shebang(val
) => val
.hash_stable(hcx
, hasher
),
363 impl_stable_hash_for_spanned
!(::syntax
::ast
::NestedMetaItemKind
);
365 impl_stable_hash_for
!(enum ::syntax
::ast
::NestedMetaItemKind
{
370 impl_stable_hash_for
!(struct ::syntax
::ast
::MetaItem
{
376 impl_stable_hash_for
!(enum ::syntax
::ast
::MetaItemKind
{
382 impl_stable_hash_for
!(struct ::syntax_pos
::hygiene
::ExpnInfo
{
386 allow_internal_unstable
,
387 allow_internal_unsafe
,
392 impl_stable_hash_for
!(enum ::syntax_pos
::hygiene
::ExpnFormat
{
395 CompilerDesugaring(kind
)
398 impl_stable_hash_for
!(enum ::syntax_pos
::hygiene
::CompilerDesugaringKind
{
401 ExistentialReturnType
,
406 impl_stable_hash_for
!(enum ::syntax_pos
::FileName
{
412 ProcMacroSourceCode(s
),
419 impl<'a
> HashStable
<StableHashingContext
<'a
>> for SourceFile
{
420 fn hash_stable
<W
: StableHasherResult
>(&self,
421 hcx
: &mut StableHashingContext
<'a
>,
422 hasher
: &mut StableHasher
<W
>) {
424 name
: _
, // We hash the smaller name_hash instead of this
429 // Do not hash the source as it is not encoded
437 ref non_narrow_chars
,
440 (name_hash
as u64).hash_stable(hcx
, hasher
);
441 name_was_remapped
.hash_stable(hcx
, hasher
);
444 krate
: CrateNum
::from_u32(crate_of_origin
),
445 index
: CRATE_DEF_INDEX
,
446 }.hash_stable(hcx
, hasher
);
448 src_hash
.hash_stable(hcx
, hasher
);
450 // We only hash the relative position within this source_file
451 lines
.len().hash_stable(hcx
, hasher
);
452 for &line
in lines
.iter() {
453 stable_byte_pos(line
, start_pos
).hash_stable(hcx
, hasher
);
456 // We only hash the relative position within this source_file
457 multibyte_chars
.len().hash_stable(hcx
, hasher
);
458 for &char_pos
in multibyte_chars
.iter() {
459 stable_multibyte_char(char_pos
, start_pos
).hash_stable(hcx
, hasher
);
462 non_narrow_chars
.len().hash_stable(hcx
, hasher
);
463 for &char_pos
in non_narrow_chars
.iter() {
464 stable_non_narrow_char(char_pos
, start_pos
).hash_stable(hcx
, hasher
);
469 fn stable_byte_pos(pos
: ::syntax_pos
::BytePos
,
470 source_file_start
: ::syntax_pos
::BytePos
)
472 pos
.0 - source_file_start
.0
475 fn stable_multibyte_char(mbc
: ::syntax_pos
::MultiByteChar
,
476 source_file_start
: ::syntax_pos
::BytePos
)
478 let ::syntax_pos
::MultiByteChar
{
483 (pos
.0 - source_file_start
.0, bytes
as u32)
486 fn stable_non_narrow_char(swc
: ::syntax_pos
::NonNarrowChar
,
487 source_file_start
: ::syntax_pos
::BytePos
)
490 let width
= swc
.width();
492 (pos
.0 - source_file_start
.0, width
as u32)
497 impl<'gcx
> HashStable
<StableHashingContext
<'gcx
>> for feature_gate
::Features
{
498 fn hash_stable
<W
: StableHasherResult
>(&self,
499 hcx
: &mut StableHashingContext
<'gcx
>,
500 hasher
: &mut StableHasher
<W
>) {
501 // Unfortunately we cannot exhaustively list fields here, since the
502 // struct is macro generated.
503 self.declared_lang_features
.hash_stable(hcx
, hasher
);
504 self.declared_lib_features
.hash_stable(hcx
, hasher
);
506 self.walk_feature_fields(|feature_name
, value
| {
507 feature_name
.hash_stable(hcx
, hasher
);
508 value
.hash_stable(hcx
, hasher
);