]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/codec.rs
Auto merge of #54813 - petrochenkov:uilocale, r=alexcrichton
[rust.git] / src / librustc / ty / codec.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 some shared code for encoding and decoding various
12 // things from the `ty` module, and in particular implements support for
13 // "shorthands" which allow to have pointers back into the already encoded
14 // stream instead of re-encoding the same thing twice.
15 //
16 // The functionality in here is shared between persisting to crate metadata and
17 // persisting to incr. comp. caches.
18
19 use hir::def_id::{DefId, CrateNum};
20 use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
21 use rustc_data_structures::fx::FxHashMap;
22 use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
23 use std::hash::Hash;
24 use std::intrinsics;
25 use ty::{self, Ty, TyCtxt};
26 use ty::subst::Substs;
27 use mir::interpret::Allocation;
28
29 /// The shorthand encoding uses an enum's variant index `usize`
30 /// and is offset by this value so it never matches a real variant.
31 /// This offset is also chosen so that the first byte is never < 0x80.
32 pub const SHORTHAND_OFFSET: usize = 0x80;
33
34 pub trait EncodableWithShorthand: Clone + Eq + Hash {
35     type Variant: Encodable;
36     fn variant(&self) -> &Self::Variant;
37 }
38
39 impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
40     type Variant = ty::TyKind<'tcx>;
41     fn variant(&self) -> &Self::Variant {
42         &self.sty
43     }
44 }
45
46 impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
47     type Variant = ty::Predicate<'tcx>;
48     fn variant(&self) -> &Self::Variant {
49         self
50     }
51 }
52
53 pub trait TyEncoder: Encoder {
54     fn position(&self) -> usize;
55 }
56
57 impl TyEncoder for opaque::Encoder {
58     #[inline]
59     fn position(&self) -> usize {
60         self.position()
61     }
62 }
63
64 /// Encode the given value or a previously cached shorthand.
65 pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
66                                       value: &T,
67                                       cache: M)
68                                       -> Result<(), E::Error>
69     where E: TyEncoder,
70           M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
71           T: EncodableWithShorthand,
72 {
73     let existing_shorthand = cache(encoder).get(value).cloned();
74     if let Some(shorthand) = existing_shorthand {
75         return encoder.emit_usize(shorthand);
76     }
77
78     let variant = value.variant();
79
80     let start = encoder.position();
81     variant.encode(encoder)?;
82     let len = encoder.position() - start;
83
84     // The shorthand encoding uses the same usize as the
85     // discriminant, with an offset so they can't conflict.
86     let discriminant = unsafe { intrinsics::discriminant_value(variant) };
87     assert!(discriminant < SHORTHAND_OFFSET as u64);
88     let shorthand = start + SHORTHAND_OFFSET;
89
90     // Get the number of bits that leb128 could fit
91     // in the same space as the fully encoded type.
92     let leb128_bits = len * 7;
93
94     // Check that the shorthand is a not longer than the
95     // full encoding itself, i.e. it's an obvious win.
96     if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
97         cache(encoder).insert(value.clone(), shorthand);
98     }
99
100     Ok(())
101 }
102
103 pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
104                                      predicates: &ty::GenericPredicates<'tcx>,
105                                      cache: C)
106                                      -> Result<(), E::Error>
107     where E: TyEncoder,
108           C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
109 {
110     predicates.parent.encode(encoder)?;
111     predicates.predicates.len().encode(encoder)?;
112     for (predicate, span) in &predicates.predicates {
113         encode_with_shorthand(encoder, predicate, &cache)?;
114         span.encode(encoder)?;
115     }
116     Ok(())
117 }
118
119 pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
120
121     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
122
123     fn peek_byte(&self) -> u8;
124
125     fn position(&self) -> usize;
126
127     fn cached_ty_for_shorthand<F>(&mut self,
128                                   shorthand: usize,
129                                   or_insert_with: F)
130                                   -> Result<Ty<'tcx>, Self::Error>
131         where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
132
133     fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
134         where F: FnOnce(&mut Self) -> R;
135
136     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
137
138     fn positioned_at_shorthand(&self) -> bool {
139         (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
140     }
141 }
142
143 #[inline]
144 pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
145     where D: TyDecoder<'a, 'tcx>,
146           'tcx: 'a,
147 {
148     let cnum = CrateNum::from_u32(u32::decode(decoder)?);
149     Ok(decoder.map_encoded_cnum_to_current(cnum))
150 }
151
152 #[inline]
153 pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
154     where D: TyDecoder<'a, 'tcx>,
155           'tcx: 'a,
156 {
157     // Handle shorthands first, if we have an usize > 0x80.
158     if decoder.positioned_at_shorthand() {
159         let pos = decoder.read_usize()?;
160         assert!(pos >= SHORTHAND_OFFSET);
161         let shorthand = pos - SHORTHAND_OFFSET;
162
163         decoder.cached_ty_for_shorthand(shorthand, |decoder| {
164             decoder.with_position(shorthand, Ty::decode)
165         })
166     } else {
167         let tcx = decoder.tcx();
168         Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
169     }
170 }
171
172 #[inline]
173 pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
174                                       -> Result<ty::GenericPredicates<'tcx>, D::Error>
175     where D: TyDecoder<'a, 'tcx>,
176           'tcx: 'a,
177 {
178     Ok(ty::GenericPredicates {
179         parent: Decodable::decode(decoder)?,
180         predicates: (0..decoder.read_usize()?).map(|_| {
181             // Handle shorthands first, if we have an usize > 0x80.
182             let predicate = if decoder.positioned_at_shorthand() {
183                 let pos = decoder.read_usize()?;
184                 assert!(pos >= SHORTHAND_OFFSET);
185                 let shorthand = pos - SHORTHAND_OFFSET;
186
187                 decoder.with_position(shorthand, ty::Predicate::decode)
188             } else {
189                 ty::Predicate::decode(decoder)
190             }?;
191             Ok((predicate, Decodable::decode(decoder)?))
192         })
193         .collect::<Result<Vec<_>, _>>()?,
194     })
195 }
196
197 #[inline]
198 pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
199     where D: TyDecoder<'a, 'tcx>,
200           'tcx: 'a,
201 {
202     let len = decoder.read_usize()?;
203     let tcx = decoder.tcx();
204     Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
205 }
206
207 #[inline]
208 pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
209     where D: TyDecoder<'a, 'tcx>,
210           'tcx: 'a,
211 {
212     Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
213 }
214
215 #[inline]
216 pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
217                                     -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
218     where D: TyDecoder<'a, 'tcx>,
219           'tcx: 'a,
220 {
221     let len = decoder.read_usize()?;
222     Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
223 }
224
225 #[inline]
226 pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
227                                    -> Result<&'tcx ty::AdtDef, D::Error>
228     where D: TyDecoder<'a, 'tcx>,
229           'tcx: 'a,
230 {
231     let def_id = DefId::decode(decoder)?;
232     Ok(decoder.tcx().adt_def(def_id))
233 }
234
235 #[inline]
236 pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
237     -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
238     where D: TyDecoder<'a, 'tcx>,
239           'tcx: 'a,
240 {
241     let len = decoder.read_usize()?;
242     Ok(decoder.tcx()
243               .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
244 }
245
246 #[inline]
247 pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
248     -> Result<CanonicalVarInfos<'tcx>, D::Error>
249     where D: TyDecoder<'a, 'tcx>,
250           'tcx: 'a,
251 {
252     let len = decoder.read_usize()?;
253     let interned: Result<Vec<CanonicalVarInfo>, _> = (0..len).map(|_| Decodable::decode(decoder))
254                                                              .collect();
255     Ok(decoder.tcx()
256               .intern_canonical_var_infos(interned?.as_slice()))
257 }
258
259 #[inline]
260 pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
261                                  -> Result<&'tcx ty::Const<'tcx>, D::Error>
262     where D: TyDecoder<'a, 'tcx>,
263           'tcx: 'a,
264 {
265     Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
266 }
267
268 #[inline]
269 pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
270     -> Result<&'tcx Allocation, D::Error>
271     where D: TyDecoder<'a, 'tcx>,
272           'tcx: 'a,
273 {
274     Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
275 }
276
277 #[macro_export]
278 macro_rules! __impl_decoder_methods {
279     ($($name:ident -> $ty:ty;)*) => {
280         $(fn $name(&mut self) -> Result<$ty, Self::Error> {
281             self.opaque.$name()
282         })*
283     }
284 }
285
286 #[macro_export]
287 macro_rules! implement_ty_decoder {
288     ($DecoderName:ident <$($typaram:tt),*>) => {
289         mod __ty_decoder_impl {
290             use super::$DecoderName;
291             use $crate::infer::canonical::CanonicalVarInfos;
292             use $crate::ty;
293             use $crate::ty::codec::*;
294             use $crate::ty::subst::Substs;
295             use $crate::hir::def_id::{CrateNum};
296             use rustc_serialize::{Decoder, SpecializedDecoder};
297             use std::borrow::Cow;
298
299             impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
300                 type Error = String;
301
302                 __impl_decoder_methods! {
303                     read_nil -> ();
304
305                     read_u128 -> u128;
306                     read_u64 -> u64;
307                     read_u32 -> u32;
308                     read_u16 -> u16;
309                     read_u8 -> u8;
310                     read_usize -> usize;
311
312                     read_i128 -> i128;
313                     read_i64 -> i64;
314                     read_i32 -> i32;
315                     read_i16 -> i16;
316                     read_i8 -> i8;
317                     read_isize -> isize;
318
319                     read_bool -> bool;
320                     read_f64 -> f64;
321                     read_f32 -> f32;
322                     read_char -> char;
323                     read_str -> Cow<'_, str>;
324                 }
325
326                 fn error(&mut self, err: &str) -> Self::Error {
327                     self.opaque.error(err)
328                 }
329             }
330
331             // FIXME(#36588) These impls are horribly unsound as they allow
332             // the caller to pick any lifetime for 'tcx, including 'static,
333             // by using the unspecialized proxies to them.
334
335             impl<$($typaram),*> SpecializedDecoder<CrateNum>
336             for $DecoderName<$($typaram),*> {
337                 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
338                     decode_cnum(self)
339                 }
340             }
341
342             impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
343             for $DecoderName<$($typaram),*> {
344                 fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
345                     decode_ty(self)
346                 }
347             }
348
349             impl<$($typaram),*> SpecializedDecoder<ty::GenericPredicates<'tcx>>
350             for $DecoderName<$($typaram),*> {
351                 fn specialized_decode(&mut self)
352                                       -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
353                     decode_predicates(self)
354                 }
355             }
356
357             impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>>
358             for $DecoderName<$($typaram),*> {
359                 fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
360                     decode_substs(self)
361                 }
362             }
363
364             impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
365             for $DecoderName<$($typaram),*> {
366                 fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
367                     decode_region(self)
368                 }
369             }
370
371             impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
372             for $DecoderName<$($typaram),*> {
373                 fn specialized_decode(&mut self)
374                                       -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
375                     decode_ty_slice(self)
376                 }
377             }
378
379             impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
380             for $DecoderName<$($typaram),*> {
381                 fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
382                     decode_adt_def(self)
383                 }
384             }
385
386             impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
387                 for $DecoderName<$($typaram),*> {
388                 fn specialized_decode(&mut self)
389                     -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
390                     decode_existential_predicate_slice(self)
391                 }
392             }
393
394             impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
395                 for $DecoderName<$($typaram),*> {
396                 fn specialized_decode(&mut self)
397                     -> Result<CanonicalVarInfos<'tcx>, Self::Error> {
398                     decode_canonical_var_infos(self)
399                 }
400             }
401
402             impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
403             for $DecoderName<$($typaram),*> {
404                 fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
405                     decode_const(self)
406                 }
407             }
408
409             impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
410             for $DecoderName<$($typaram),*> {
411                 fn specialized_decode(
412                     &mut self
413                 ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
414                     decode_allocation(self)
415                 }
416             }
417         }
418     }
419 }