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