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