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