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