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