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