]> git.lizzy.rs Git - rust.git/blob - src/librustc/ich/impls_syntax.rs
7138db01339f6a89489a6204526c24fb26c96b87
[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::parse::token;
21 use syntax::tokenstream;
22 use syntax_pos::{Span, FileMap};
23
24 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
25
26 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
27                                            StableHasherResult};
28 use rustc_data_structures::accumulate_vec::AccumulateVec;
29
30 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::symbol::InternedString {
31     #[inline]
32     fn hash_stable<W: StableHasherResult>(&self,
33                                           hcx: &mut StableHashingContext<'a, 'tcx>,
34                                           hasher: &mut StableHasher<W>) {
35         let s: &str = &**self;
36         s.hash_stable(hcx, hasher);
37     }
38 }
39
40 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Name {
41     #[inline]
42     fn hash_stable<W: StableHasherResult>(&self,
43                                           hcx: &mut StableHashingContext<'a, 'tcx>,
44                                           hasher: &mut StableHasher<W>) {
45         self.as_str().hash_stable(hcx, hasher);
46     }
47 }
48
49 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
50     Att,
51     Intel
52 });
53
54 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
55     Bang,
56     Attr,
57     Derive
58 });
59
60
61 impl_stable_hash_for!(enum ::syntax::abi::Abi {
62     Cdecl,
63     Stdcall,
64     Fastcall,
65     Vectorcall,
66     Aapcs,
67     Win64,
68     SysV64,
69     PtxKernel,
70     Msp430Interrupt,
71     X86Interrupt,
72     Rust,
73     C,
74     System,
75     RustIntrinsic,
76     RustCall,
77     PlatformIntrinsic,
78     Unadjusted
79 });
80
81 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
82 impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
83
84 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::attr::StabilityLevel {
85     fn hash_stable<W: StableHasherResult>(&self,
86                                           hcx: &mut StableHashingContext<'a, 'tcx>,
87                                           hasher: &mut StableHasher<W>) {
88         mem::discriminant(self).hash_stable(hcx, hasher);
89         match *self {
90             ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
91                 reason.hash_stable(hcx, hasher);
92                 issue.hash_stable(hcx, hasher);
93             }
94             ::syntax::attr::StabilityLevel::Stable { ref since } => {
95                 since.hash_stable(hcx, hasher);
96             }
97         }
98     }
99 }
100
101 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
102
103
104 impl_stable_hash_for!(enum ::syntax::attr::IntType {
105     SignedInt(int_ty),
106     UnsignedInt(uint_ty)
107 });
108
109 impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
110     Signed(int_ty),
111     Unsigned(int_ty),
112     Unsuffixed
113 });
114
115 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
116 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
117     Str(value, style),
118     ByteStr(value),
119     Byte(value),
120     Char(value),
121     Int(value, lit_int_type),
122     Float(value, float_ty),
123     FloatUnsuffixed(value),
124     Bool(value)
125 });
126
127 impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
128 impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
129 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
130 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
131 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
132 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
133 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
134 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
135 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
136
137 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for [ast::Attribute] {
138     fn hash_stable<W: StableHasherResult>(&self,
139                                           hcx: &mut StableHashingContext<'a, 'tcx>,
140                                           hasher: &mut StableHasher<W>) {
141         // Some attributes are always ignored during hashing.
142         let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
143             .iter()
144             .filter(|attr| {
145                 !attr.is_sugared_doc &&
146                 attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
147             })
148             .collect();
149
150         filtered.len().hash_stable(hcx, hasher);
151         for attr in filtered {
152             attr.hash_stable(hcx, hasher);
153         }
154     }
155 }
156
157 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Attribute {
158     fn hash_stable<W: StableHasherResult>(&self,
159                                           hcx: &mut StableHashingContext<'a, 'tcx>,
160                                           hasher: &mut StableHasher<W>) {
161         // Make sure that these have been filtered out.
162         debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
163         debug_assert!(!self.is_sugared_doc);
164
165         let ast::Attribute {
166             id: _,
167             style,
168             ref path,
169             ref tokens,
170             is_sugared_doc: _,
171             span,
172         } = *self;
173
174         style.hash_stable(hcx, hasher);
175         path.segments.len().hash_stable(hcx, hasher);
176         for segment in &path.segments {
177             segment.identifier.name.hash_stable(hcx, hasher);
178         }
179         for tt in tokens.trees() {
180             tt.hash_stable(hcx, hasher);
181         }
182         span.hash_stable(hcx, hasher);
183     }
184 }
185
186 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenTree {
187     fn hash_stable<W: StableHasherResult>(&self,
188                                           hcx: &mut StableHashingContext<'a, 'tcx>,
189                                           hasher: &mut StableHasher<W>) {
190         mem::discriminant(self).hash_stable(hcx, hasher);
191         match *self {
192             tokenstream::TokenTree::Token(span, ref token) => {
193                 span.hash_stable(hcx, hasher);
194                 hash_token(token, hcx, hasher, span);
195             }
196             tokenstream::TokenTree::Delimited(span, ref delimited) => {
197                 span.hash_stable(hcx, hasher);
198                 std_hash::Hash::hash(&delimited.delim, hasher);
199                 for sub_tt in delimited.stream().trees() {
200                     sub_tt.hash_stable(hcx, hasher);
201                 }
202             }
203         }
204     }
205 }
206
207 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenStream {
208     fn hash_stable<W: StableHasherResult>(&self,
209                                           hcx: &mut StableHashingContext<'a, 'tcx>,
210                                           hasher: &mut StableHasher<W>) {
211         for sub_tt in self.trees() {
212             sub_tt.hash_stable(hcx, hasher);
213         }
214     }
215 }
216
217 fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
218                                                hcx: &mut StableHashingContext<'a, 'tcx>,
219                                                hasher: &mut StableHasher<W>,
220                                                error_reporting_span: Span) {
221     mem::discriminant(token).hash_stable(hcx, hasher);
222     match *token {
223         token::Token::Eq |
224         token::Token::Lt |
225         token::Token::Le |
226         token::Token::EqEq |
227         token::Token::Ne |
228         token::Token::Ge |
229         token::Token::Gt |
230         token::Token::AndAnd |
231         token::Token::OrOr |
232         token::Token::Not |
233         token::Token::Tilde |
234         token::Token::At |
235         token::Token::Dot |
236         token::Token::DotDot |
237         token::Token::DotDotDot |
238         token::Token::Comma |
239         token::Token::Semi |
240         token::Token::Colon |
241         token::Token::ModSep |
242         token::Token::RArrow |
243         token::Token::LArrow |
244         token::Token::FatArrow |
245         token::Token::Pound |
246         token::Token::Dollar |
247         token::Token::Question |
248         token::Token::Underscore |
249         token::Token::Whitespace |
250         token::Token::Comment |
251         token::Token::Eof => {}
252
253         token::Token::BinOp(bin_op_token) |
254         token::Token::BinOpEq(bin_op_token) => {
255             std_hash::Hash::hash(&bin_op_token, hasher);
256         }
257
258         token::Token::OpenDelim(delim_token) |
259         token::Token::CloseDelim(delim_token) => {
260             std_hash::Hash::hash(&delim_token, hasher);
261         }
262         token::Token::Literal(ref lit, ref opt_name) => {
263             mem::discriminant(lit).hash_stable(hcx, hasher);
264             match *lit {
265                 token::Lit::Byte(val) |
266                 token::Lit::Char(val) |
267                 token::Lit::Integer(val) |
268                 token::Lit::Float(val) |
269                 token::Lit::Str_(val) |
270                 token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
271                 token::Lit::StrRaw(val, n) |
272                 token::Lit::ByteStrRaw(val, n) => {
273                     val.hash_stable(hcx, hasher);
274                     n.hash_stable(hcx, hasher);
275                 }
276             };
277             opt_name.hash_stable(hcx, hasher);
278         }
279
280         token::Token::Ident(ident) |
281         token::Token::Lifetime(ident) |
282         token::Token::SubstNt(ident) => ident.name.hash_stable(hcx, hasher),
283
284         token::Token::Interpolated(ref non_terminal) => {
285             // FIXME(mw): This could be implemented properly. It's just a
286             //            lot of work, since we would need to hash the AST
287             //            in a stable way, in addition to the HIR.
288             //            Since this is hardly used anywhere, just emit a
289             //            warning for now.
290             if hcx.tcx().sess.opts.debugging_opts.incremental.is_some() {
291                 let msg = format!("Quasi-quoting might make incremental \
292                                    compilation very inefficient: {:?}",
293                                   non_terminal);
294                 hcx.tcx().sess.span_warn(error_reporting_span, &msg[..]);
295             }
296
297             std_hash::Hash::hash(non_terminal, hasher);
298         }
299
300         token::Token::DocComment(val) |
301         token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
302     }
303 }
304
305 impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
306
307 impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
308     MetaItem(meta_item),
309     Literal(lit)
310 });
311
312 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
313     name,
314     node,
315     span
316 });
317
318 impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
319     Word,
320     List(nested_items),
321     NameValue(lit)
322 });
323
324 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for FileMap {
325     fn hash_stable<W: StableHasherResult>(&self,
326                                           hcx: &mut StableHashingContext<'a, 'tcx>,
327                                           hasher: &mut StableHasher<W>) {
328         let FileMap {
329             ref name,
330             name_was_remapped,
331             crate_of_origin,
332             // Do not hash the source as it is not encoded
333             src: _,
334             start_pos,
335             end_pos: _,
336             ref lines,
337             ref multibyte_chars,
338         } = *self;
339
340         name.hash_stable(hcx, hasher);
341         name_was_remapped.hash_stable(hcx, hasher);
342
343         DefId {
344             krate: CrateNum::from_u32(crate_of_origin),
345             index: CRATE_DEF_INDEX,
346         }.hash_stable(hcx, hasher);
347
348         // We only hash the relative position within this filemap
349         let lines = lines.borrow();
350         lines.len().hash_stable(hcx, hasher);
351         for &line in lines.iter() {
352             stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
353         }
354
355         // We only hash the relative position within this filemap
356         let multibyte_chars = multibyte_chars.borrow();
357         multibyte_chars.len().hash_stable(hcx, hasher);
358         for &char_pos in multibyte_chars.iter() {
359             stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
360         }
361     }
362 }
363
364 fn stable_byte_pos(pos: ::syntax_pos::BytePos,
365                    filemap_start: ::syntax_pos::BytePos)
366                    -> u32 {
367     pos.0 - filemap_start.0
368 }
369
370 fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
371                          filemap_start: ::syntax_pos::BytePos)
372                          -> (u32, u32) {
373     let ::syntax_pos::MultiByteChar {
374         pos,
375         bytes,
376     } = mbc;
377
378     (pos.0 - filemap_start.0, bytes as u32)
379 }