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