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.
6 // The functionality in here is shared between persisting to crate metadata and
7 // persisting to incr. comp. caches.
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};
16 use crate::ty::{self, Ty, TyCtxt};
17 use crate::ty::subst::SubstsRef;
18 use crate::mir::interpret::Allocation;
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;
25 pub trait EncodableWithShorthand: Clone + Eq + Hash {
26 type Variant: Encodable;
27 fn variant(&self) -> &Self::Variant;
30 impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
31 type Variant = ty::TyKind<'tcx>;
32 fn variant(&self) -> &Self::Variant {
37 impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
38 type Variant = ty::Predicate<'tcx>;
39 fn variant(&self) -> &Self::Variant {
44 pub trait TyEncoder: Encoder {
45 fn position(&self) -> usize;
48 impl TyEncoder for opaque::Encoder {
50 fn position(&self) -> usize {
55 /// Encode the given value or a previously cached shorthand.
56 pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
59 -> Result<(), E::Error>
61 M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
62 T: EncodableWithShorthand,
64 let existing_shorthand = cache(encoder).get(value).cloned();
65 if let Some(shorthand) = existing_shorthand {
66 return encoder.emit_usize(shorthand);
69 let variant = value.variant();
71 let start = encoder.position();
72 variant.encode(encoder)?;
73 let len = encoder.position() - start;
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;
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;
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);
94 pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
95 predicates: &ty::GenericPredicates<'tcx>,
97 -> Result<(), E::Error>
99 C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
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)?;
110 pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
112 fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
114 fn peek_byte(&self) -> u8;
116 fn position(&self) -> usize;
118 fn cached_ty_for_shorthand<F>(&mut self,
121 -> Result<Ty<'tcx>, Self::Error>
122 where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
124 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
125 where F: FnOnce(&mut Self) -> R;
127 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
129 fn positioned_at_shorthand(&self) -> bool {
130 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
135 pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
137 ) -> Result<&'tcx T, D::Error>
138 where D: TyDecoder<'a, 'tcx>,
141 Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?))
145 pub fn decode_arena_allocable_slice<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
147 ) -> Result<&'tcx [T], D::Error>
148 where D: TyDecoder<'a, 'tcx>,
151 Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
155 pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
156 where D: TyDecoder<'a, 'tcx>,
159 let cnum = CrateNum::from_u32(u32::decode(decoder)?);
160 Ok(decoder.map_encoded_cnum_to_current(cnum))
164 pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
165 where D: TyDecoder<'a, 'tcx>,
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;
174 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
175 decoder.with_position(shorthand, Ty::decode)
178 let tcx = decoder.tcx();
179 Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
184 pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
185 -> Result<ty::GenericPredicates<'tcx>, D::Error>
186 where D: TyDecoder<'a, 'tcx>,
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;
198 decoder.with_position(shorthand, ty::Predicate::decode)
200 ty::Predicate::decode(decoder)
202 Ok((predicate, Decodable::decode(decoder)?))
204 .collect::<Result<Vec<_>, _>>()?,
209 pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
210 where D: TyDecoder<'a, 'tcx>,
213 let len = decoder.read_usize()?;
214 let tcx = decoder.tcx();
215 Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
219 pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
220 where D: TyDecoder<'a, 'tcx>,
223 Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
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>,
232 let len = decoder.read_usize()?;
233 Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
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>,
242 let def_id = DefId::decode(decoder)?;
243 Ok(decoder.tcx().adt_def(def_id))
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>,
252 let len = decoder.read_usize()?;
254 .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
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>,
263 let len = decoder.read_usize()?;
264 let interned: Result<Vec<CanonicalVarInfo>, _> = (0..len).map(|_| Decodable::decode(decoder))
267 .intern_canonical_var_infos(interned?.as_slice()))
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>,
276 Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
280 pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
281 -> Result<&'tcx Allocation, D::Error>
282 where D: TyDecoder<'a, 'tcx>,
285 Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
289 macro_rules! __impl_decoder_methods {
290 ($($name:ident -> $ty:ty;)*) => {
291 $(fn $name(&mut self) -> Result<$ty, Self::Error> {
298 macro_rules! impl_arena_allocatable_decoder {
300 ([decode $(, $attrs:ident)*]
301 [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
302 impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
304 fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
305 decode_arena_allocable(self)
309 impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
311 fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
312 decode_arena_allocable_slice(self)
316 ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
317 impl_arena_allocatable_decoder!([$($attrs),*]$args);
322 macro_rules! impl_arena_allocatable_decoders {
323 ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
325 impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
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;
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;
343 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
346 __impl_decoder_methods! {
367 read_str -> Cow<'_, str>;
370 fn error(&mut self, err: &str) -> Self::Error {
371 self.opaque.error(err)
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.
379 arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
381 impl<$($typaram),*> SpecializedDecoder<CrateNum>
382 for $DecoderName<$($typaram),*> {
383 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
388 impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
389 for $DecoderName<$($typaram),*> {
390 fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
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)
403 impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
404 for $DecoderName<$($typaram),*> {
405 fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
410 impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
411 for $DecoderName<$($typaram),*> {
412 fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
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)
425 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
426 for $DecoderName<$($typaram),*> {
427 fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
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)
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)
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> {
455 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
456 for $DecoderName<$($typaram),*> {
457 fn specialized_decode(
459 ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
460 decode_allocation(self)