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 rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
16 use crate::ty::{self, List, Ty, TyCtxt};
17 use crate::ty::subst::SubstsRef;
18 use crate::mir::{self, interpret::Allocation};
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;
26 pub trait EncodableWithShorthand: Clone + Eq + Hash {
27 type Variant: Encodable;
28 fn variant(&self) -> &Self::Variant;
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 {
39 impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
40 type Variant = ty::Predicate<'tcx>;
41 fn variant(&self) -> &Self::Variant {
46 pub trait TyEncoder: Encoder {
47 fn position(&self) -> usize;
50 impl TyEncoder for opaque::Encoder {
52 fn position(&self) -> usize {
57 /// Encode the given value or a previously cached shorthand.
58 pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
61 -> Result<(), E::Error>
63 M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
64 T: EncodableWithShorthand,
66 let existing_shorthand = cache(encoder).get(value).cloned();
67 if let Some(shorthand) = existing_shorthand {
68 return encoder.emit_usize(shorthand);
71 let variant = value.variant();
73 let start = encoder.position();
74 variant.encode(encoder)?;
75 let len = encoder.position() - start;
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;
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;
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);
96 pub fn encode_spanned_predicates<'tcx, E, C>(
98 predicates: &'tcx [(ty::Predicate<'tcx>, Span)],
100 ) -> Result<(), E::Error>
102 C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
104 predicates.len().encode(encoder)?;
105 for (predicate, span) in predicates {
106 encode_with_shorthand(encoder, predicate, &cache)?;
107 span.encode(encoder)?;
112 pub trait TyDecoder<'tcx>: Decoder {
113 fn tcx(&self) -> TyCtxt<'tcx>;
115 fn peek_byte(&self) -> u8;
117 fn position(&self) -> usize;
119 fn cached_ty_for_shorthand<F>(&mut self,
122 -> Result<Ty<'tcx>, Self::Error>
123 where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
125 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
126 where F: FnOnce(&mut Self) -> R;
128 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
130 fn positioned_at_shorthand(&self) -> bool {
131 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
136 pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>(
138 ) -> Result<&'tcx T, D::Error>
142 Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?))
146 pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>(
148 ) -> Result<&'tcx [T], D::Error>
152 Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
156 pub fn decode_cnum<D>(decoder: &mut D) -> Result<CrateNum, D::Error>
160 let cnum = CrateNum::from_u32(u32::decode(decoder)?);
161 Ok(decoder.map_encoded_cnum_to_current(cnum))
164 #[allow(rustc::usage_of_ty_tykind)]
166 pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
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;
176 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
177 decoder.with_position(shorthand, Ty::decode)
180 let tcx = decoder.tcx();
181 Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
186 pub fn decode_spanned_predicates<D>(
188 ) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error>
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;
201 decoder.with_position(shorthand, ty::Predicate::decode)
203 ty::Predicate::decode(decoder)
205 Ok((predicate, Decodable::decode(decoder)?))
207 .collect::<Result<Vec<_>, _>>()?,
212 pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
216 let len = decoder.read_usize()?;
217 let tcx = decoder.tcx();
218 Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
222 pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
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 })
234 pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
238 Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
242 pub fn decode_ty_slice<D>(decoder: &mut D) -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
246 let len = decoder.read_usize()?;
247 Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
251 pub fn decode_adt_def<D>(decoder: &mut D) -> Result<&'tcx ty::AdtDef, D::Error>
255 let def_id = DefId::decode(decoder)?;
256 Ok(decoder.tcx().adt_def(def_id))
260 pub fn decode_existential_predicate_slice<D>(
262 ) -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
266 let len = decoder.read_usize()?;
268 .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
272 pub fn decode_canonical_var_infos<D>(decoder: &mut D) -> Result<CanonicalVarInfos<'tcx>, D::Error>
276 let len = decoder.read_usize()?;
277 let interned: Result<Vec<CanonicalVarInfo>, _> = (0..len).map(|_| Decodable::decode(decoder))
280 .intern_canonical_var_infos(interned?.as_slice()))
284 pub fn decode_const<D>(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Error>
288 Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
292 pub fn decode_allocation<D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error>
296 Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
300 macro_rules! __impl_decoder_methods {
301 ($($name:ident -> $ty:ty;)*) => {
303 fn $name(&mut self) -> Result<$ty, Self::Error> {
311 macro_rules! impl_arena_allocatable_decoder {
313 ([decode $(, $attrs:ident)*]
314 [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
315 impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
317 fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
318 decode_arena_allocable(self)
322 impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
324 fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
325 decode_arena_allocable_slice(self)
329 ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
330 impl_arena_allocatable_decoder!([$($attrs),*]$args);
335 macro_rules! impl_arena_allocatable_decoders {
336 ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
338 impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
344 macro_rules! implement_ty_decoder {
345 ($DecoderName:ident <$($typaram:tt),*>) => {
346 mod __ty_decoder_impl {
347 use std::borrow::Cow;
349 use rustc_serialize::{Decoder, SpecializedDecoder};
351 use $crate::infer::canonical::CanonicalVarInfos;
353 use $crate::ty::codec::*;
354 use $crate::ty::subst::SubstsRef;
355 use $crate::hir::def_id::{CrateNum};
357 use syntax_pos::Span;
359 use super::$DecoderName;
361 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
364 __impl_decoder_methods! {
385 read_str -> Cow<'_, str>;
388 fn error(&mut self, err: &str) -> Self::Error {
389 self.opaque.error(err)
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.
397 arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
399 impl<$($typaram),*> SpecializedDecoder<CrateNum>
400 for $DecoderName<$($typaram),*> {
401 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
406 impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
407 for $DecoderName<$($typaram),*> {
408 fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
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)
421 impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
422 for $DecoderName<$($typaram),*> {
423 fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
428 impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
429 for $DecoderName<$($typaram),*> {
430 fn specialized_decode(
432 ) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
437 impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
438 for $DecoderName<$($typaram),*> {
439 fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
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)
452 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
453 for $DecoderName<$($typaram),*> {
454 fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
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)
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)
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> {
482 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
483 for $DecoderName<$($typaram),*> {
484 fn specialized_decode(
486 ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
487 decode_allocation(self)