]> git.lizzy.rs Git - rust.git/blob - src/librustc/ich/impls_syntax.rs
d90dba2ff0495b5a21d6ebfe41a811d0ff8d2089
[rust.git] / src / librustc / ich / impls_syntax.rs
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.
4 //
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.
10
11 //! This module contains `HashStable` implementations for various data types
12 //! from libsyntax in no particular order.
13
14 use ich::StableHashingContext;
15
16 use std::hash as std_hash;
17 use std::mem;
18
19 use syntax::ast;
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;
25
26 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
27
28 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
29                                            StableHasher, StableHasherResult};
30 use rustc_data_structures::accumulate_vec::AccumulateVec;
31
32 impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
33     #[inline]
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))
38     }
39 }
40
41 impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
42     type KeyType = InternedString;
43
44     #[inline]
45     fn to_stable_hash_key(&self,
46                           _: &StableHashingContext<'a>)
47                           -> InternedString {
48         self.clone()
49     }
50 }
51
52 impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
53     #[inline]
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);
59     }
60 }
61
62 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
63     type KeyType = LocalInternedString;
64
65     #[inline]
66     fn to_stable_hash_key(&self,
67                           _: &StableHashingContext<'a>)
68                           -> LocalInternedString {
69         self.clone()
70     }
71 }
72
73 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
74     #[inline]
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);
79     }
80 }
81
82 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
83     type KeyType = InternedString;
84
85     #[inline]
86     fn to_stable_hash_key(&self,
87                           _: &StableHashingContext<'a>)
88                           -> InternedString {
89         self.as_interned_str()
90     }
91 }
92
93 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
94     Att,
95     Intel
96 });
97
98 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
99     Bang,
100     Attr,
101     Derive
102 });
103
104
105 impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
106     Cdecl,
107     Stdcall,
108     Fastcall,
109     Vectorcall,
110     Thiscall,
111     Aapcs,
112     Win64,
113     SysV64,
114     PtxKernel,
115     Msp430Interrupt,
116     X86Interrupt,
117     Rust,
118     C,
119     System,
120     RustIntrinsic,
121     RustCall,
122     PlatformIntrinsic,
123     Unadjusted
124 });
125
126 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
127 impl_stable_hash_for!(struct ::syntax::attr::Stability {
128     level,
129     feature,
130     rustc_depr,
131     rustc_const_unstable
132 });
133
134 impl<'a> HashStable<StableHashingContext<'a>>
135 for ::syntax::attr::StabilityLevel {
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);
140         match *self {
141             ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
142                 reason.hash_stable(hcx, hasher);
143                 issue.hash_stable(hcx, hasher);
144             }
145             ::syntax::attr::StabilityLevel::Stable { ref since } => {
146                 since.hash_stable(hcx, hasher);
147             }
148         }
149     }
150 }
151
152 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
153 impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
154
155
156 impl_stable_hash_for!(enum ::syntax::attr::IntType {
157     SignedInt(int_ty),
158     UnsignedInt(uint_ty)
159 });
160
161 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
162     Signed(int_ty),
163     Unsigned(int_ty),
164     Unsuffixed
165 });
166
167 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
168 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
169     Str(value, style),
170     ByteStr(value),
171     Byte(value),
172     Char(value),
173     Int(value, lit_int_type),
174     Float(value, float_ty),
175     FloatUnsuffixed(value),
176     Bool(value)
177 });
178
179 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
180 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
181 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
182 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
183 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
184 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
185 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
186 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
187 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
188
189 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
190     fn hash_stable<W: StableHasherResult>(&self,
191                                           hcx: &mut StableHashingContext<'a>,
192                                           hasher: &mut StableHasher<W>) {
193         if self.len() == 0 {
194             self.len().hash_stable(hcx, hasher);
195             return
196         }
197
198         // Some attributes are always ignored during hashing.
199         let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
200             .iter()
201             .filter(|attr| {
202                 !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
203             })
204             .collect();
205
206         filtered.len().hash_stable(hcx, hasher);
207         for attr in filtered {
208             attr.hash_stable(hcx, hasher);
209         }
210     }
211 }
212
213 impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
214     fn hash_stable<W: StableHasherResult>(&self,
215                                           hcx: &mut StableHashingContext<'a>,
216                                           hasher: &mut StableHasher<W>) {
217         self.segments.len().hash_stable(hcx, hasher);
218         for segment in &self.segments {
219             segment.identifier.name.hash_stable(hcx, hasher);
220         }
221     }
222 }
223
224 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
225     fn hash_stable<W: StableHasherResult>(&self,
226                                           hcx: &mut StableHashingContext<'a>,
227                                           hasher: &mut StableHasher<W>) {
228         // Make sure that these have been filtered out.
229         debug_assert!(!hcx.is_ignored_attr(self.name()));
230         debug_assert!(!self.is_sugared_doc);
231
232         let ast::Attribute {
233             id: _,
234             style,
235             ref path,
236             ref tokens,
237             is_sugared_doc: _,
238             span,
239         } = *self;
240
241         style.hash_stable(hcx, hasher);
242         path.hash_stable(hcx, hasher);
243         for tt in tokens.trees() {
244             tt.hash_stable(hcx, hasher);
245         }
246         span.hash_stable(hcx, hasher);
247     }
248 }
249
250 impl<'a> HashStable<StableHashingContext<'a>>
251 for tokenstream::TokenTree {
252     fn hash_stable<W: StableHasherResult>(&self,
253                                           hcx: &mut StableHashingContext<'a>,
254                                           hasher: &mut StableHasher<W>) {
255         mem::discriminant(self).hash_stable(hcx, hasher);
256         match *self {
257             tokenstream::TokenTree::Token(span, ref token) => {
258                 span.hash_stable(hcx, hasher);
259                 hash_token(token, hcx, hasher);
260             }
261             tokenstream::TokenTree::Delimited(span, ref delimited) => {
262                 span.hash_stable(hcx, hasher);
263                 std_hash::Hash::hash(&delimited.delim, hasher);
264                 for sub_tt in delimited.stream().trees() {
265                     sub_tt.hash_stable(hcx, hasher);
266                 }
267             }
268         }
269     }
270 }
271
272 impl<'a> HashStable<StableHashingContext<'a>>
273 for tokenstream::TokenStream {
274     fn hash_stable<W: StableHasherResult>(&self,
275                                           hcx: &mut StableHashingContext<'a>,
276                                           hasher: &mut StableHasher<W>) {
277         for sub_tt in self.trees() {
278             sub_tt.hash_stable(hcx, hasher);
279         }
280     }
281 }
282
283 fn hash_token<'a, 'gcx, W: StableHasherResult>(
284     token: &token::Token,
285     hcx: &mut StableHashingContext<'a>,
286     hasher: &mut StableHasher<W>,
287 ) {
288     mem::discriminant(token).hash_stable(hcx, hasher);
289     match *token {
290         token::Token::Eq |
291         token::Token::Lt |
292         token::Token::Le |
293         token::Token::EqEq |
294         token::Token::Ne |
295         token::Token::Ge |
296         token::Token::Gt |
297         token::Token::AndAnd |
298         token::Token::OrOr |
299         token::Token::Not |
300         token::Token::Tilde |
301         token::Token::At |
302         token::Token::Dot |
303         token::Token::DotDot |
304         token::Token::DotDotDot |
305         token::Token::DotDotEq |
306         token::Token::DotEq |
307         token::Token::Comma |
308         token::Token::Semi |
309         token::Token::Colon |
310         token::Token::ModSep |
311         token::Token::RArrow |
312         token::Token::LArrow |
313         token::Token::FatArrow |
314         token::Token::Pound |
315         token::Token::Dollar |
316         token::Token::Question |
317         token::Token::Whitespace |
318         token::Token::Comment |
319         token::Token::Eof => {}
320
321         token::Token::BinOp(bin_op_token) |
322         token::Token::BinOpEq(bin_op_token) => {
323             std_hash::Hash::hash(&bin_op_token, hasher);
324         }
325
326         token::Token::OpenDelim(delim_token) |
327         token::Token::CloseDelim(delim_token) => {
328             std_hash::Hash::hash(&delim_token, hasher);
329         }
330         token::Token::Literal(ref lit, ref opt_name) => {
331             mem::discriminant(lit).hash_stable(hcx, hasher);
332             match *lit {
333                 token::Lit::Byte(val) |
334                 token::Lit::Char(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);
343                 }
344             };
345             opt_name.hash_stable(hcx, hasher);
346         }
347
348         token::Token::Ident(ident, is_raw) => {
349             ident.name.hash_stable(hcx, hasher);
350             is_raw.hash_stable(hcx, hasher);
351         }
352         token::Token::Lifetime(ident) => ident.name.hash_stable(hcx, hasher),
353
354         token::Token::Interpolated(_) => {
355             bug!("interpolated tokens should not be present in the HIR")
356         }
357
358         token::Token::DocComment(val) |
359         token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
360     }
361 }
362
363 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
364
365 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
366     MetaItem(meta_item),
367     Literal(lit)
368 });
369
370 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
371     ident,
372     node,
373     span
374 });
375
376 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
377     Word,
378     List(nested_items),
379     NameValue(lit)
380 });
381
382 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
383     call_site,
384     callee
385 });
386
387 impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
388     format,
389     allow_internal_unstable,
390     allow_internal_unsafe,
391     span
392 });
393
394 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
395     MacroAttribute(sym),
396     MacroBang(sym),
397     CompilerDesugaring(kind)
398 });
399
400 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
401     DotFill,
402     QuestionMark,
403     Catch
404 });
405
406 impl_stable_hash_for!(enum ::syntax_pos::FileName {
407     Real(pb),
408     Macros(s),
409     QuoteExpansion,
410     Anon,
411     MacroExpansion,
412     ProcMacroSourceCode,
413     CfgSpec,
414     Custom(s)
415 });
416
417 impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
418     fn hash_stable<W: StableHasherResult>(&self,
419                                           hcx: &mut StableHashingContext<'a>,
420                                           hasher: &mut StableHasher<W>) {
421         let FileMap {
422             name: _, // We hash the smaller name_hash instead of this
423             name_hash,
424             name_was_remapped,
425             unmapped_path: _,
426             crate_of_origin,
427             // Do not hash the source as it is not encoded
428             src: _,
429             src_hash,
430             external_src: _,
431             start_pos,
432             end_pos: _,
433             ref lines,
434             ref multibyte_chars,
435             ref non_narrow_chars,
436         } = *self;
437
438         (name_hash as u64).hash_stable(hcx, hasher);
439         name_was_remapped.hash_stable(hcx, hasher);
440
441         DefId {
442             krate: CrateNum::from_u32(crate_of_origin),
443             index: CRATE_DEF_INDEX,
444         }.hash_stable(hcx, hasher);
445
446         src_hash.hash_stable(hcx, hasher);
447
448         // We only hash the relative position within this filemap
449         lines.with_lock(|lines| {
450             lines.len().hash_stable(hcx, hasher);
451             for &line in lines.iter() {
452                 stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
453             }
454         });
455
456         // We only hash the relative position within this filemap
457         multibyte_chars.with_lock(|multibyte_chars| {
458             multibyte_chars.len().hash_stable(hcx, hasher);
459             for &char_pos in multibyte_chars.iter() {
460                 stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
461             }
462         });
463
464         non_narrow_chars.with_lock(|non_narrow_chars| {
465             non_narrow_chars.len().hash_stable(hcx, hasher);
466             for &char_pos in non_narrow_chars.iter() {
467                 stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
468             }
469         });
470     }
471 }
472
473 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
474                    filemap_start: ::syntax_pos::BytePos)
475                    -> u32 {
476     pos.0 - filemap_start.0
477 }
478
479 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
480                          filemap_start: ::syntax_pos::BytePos)
481                          -> (u32, u32) {
482     let ::syntax_pos::MultiByteChar {
483         pos,
484         bytes,
485     } = mbc;
486
487     (pos.0 - filemap_start.0, bytes as u32)
488 }
489
490 fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
491                           filemap_start: ::syntax_pos::BytePos)
492                           -> (u32, u32) {
493     let pos = swc.pos();
494     let width = swc.width();
495
496     (pos.0 - filemap_start.0, width as u32)
497 }
498
499
500
501 impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
502     fn hash_stable<W: StableHasherResult>(&self,
503                                           hcx: &mut StableHashingContext<'gcx>,
504                                           hasher: &mut StableHasher<W>) {
505         // Unfortunately we cannot exhaustively list fields here, since the
506         // struct is macro generated.
507         self.declared_stable_lang_features.hash_stable(hcx, hasher);
508         self.declared_lib_features.hash_stable(hcx, hasher);
509
510         self.walk_feature_fields(|feature_name, value| {
511             feature_name.hash_stable(hcx, hasher);
512             value.hash_stable(hcx, hasher);
513         });
514     }
515 }