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::infer
::canonical
::{CanonicalVarInfo, CanonicalVarInfos}
;
11 use crate::mir
::{self, interpret::Allocation}
;
12 use crate::ty
::subst
::SubstsRef
;
13 use crate::ty
::{self, List, ToPredicate, 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}
;
18 use std
::convert
::{TryFrom, TryInto}
;
21 use std
::marker
::DiscriminantKind
;
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;
28 pub trait EncodableWithShorthand
: Clone
+ Eq
+ Hash
{
29 type Variant
: Encodable
;
30 fn variant(&self) -> &Self::Variant
;
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
{
41 impl<'tcx
> EncodableWithShorthand
for ty
::Predicate
<'tcx
> {
42 type Variant
= ty
::PredicateKind
<'tcx
>;
43 fn variant(&self) -> &Self::Variant
{
48 pub trait TyEncoder
: Encoder
{
49 fn position(&self) -> usize;
52 impl TyEncoder
for opaque
::Encoder
{
54 fn position(&self) -> usize {
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
>
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>,
67 let existing_shorthand
= cache(encoder
).get(value
).cloned();
68 if let Some(shorthand
) = existing_shorthand
{
69 return encoder
.emit_usize(shorthand
);
72 let variant
= value
.variant();
74 let start
= encoder
.position();
75 variant
.encode(encoder
)?
;
76 let len
= encoder
.position() - start
;
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());
83 let shorthand
= start
+ SHORTHAND_OFFSET
;
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;
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
);
98 pub fn encode_spanned_predicates
<'tcx
, E
, C
>(
100 predicates
: &'tcx
[(ty
::Predicate
<'tcx
>, Span
)],
102 ) -> Result
<(), E
::Error
>
105 C
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
107 predicates
.len().encode(encoder
)?
;
108 for (predicate
, span
) in predicates
{
109 encode_with_shorthand(encoder
, predicate
, &cache
)?
;
110 span
.encode(encoder
)?
;
115 pub trait TyDecoder
<'tcx
>: Decoder
{
116 fn tcx(&self) -> TyCtxt
<'tcx
>;
118 fn peek_byte(&self) -> u8;
120 fn position(&self) -> usize;
122 fn cached_ty_for_shorthand
<F
>(
126 ) -> Result
<Ty
<'tcx
>, Self::Error
>
128 F
: FnOnce(&mut Self) -> Result
<Ty
<'tcx
>, Self::Error
>;
130 fn with_position
<F
, R
>(&mut self, pos
: usize, f
: F
) -> R
132 F
: FnOnce(&mut Self) -> R
;
134 fn map_encoded_cnum_to_current(&self, cnum
: CrateNum
) -> CrateNum
;
136 fn positioned_at_shorthand(&self) -> bool
{
137 (self.peek_byte() & (SHORTHAND_OFFSET
as u8)) != 0
142 pub fn decode_arena_allocable
<D
, T
: ArenaAllocatable
+ Decodable
>(
144 ) -> Result
<&'tcx T
, D
::Error
>
148 Ok(decoder
.tcx().arena
.alloc(Decodable
::decode(decoder
)?
))
152 pub fn decode_arena_allocable_slice
<D
, T
: ArenaAllocatable
+ Decodable
>(
154 ) -> Result
<&'tcx
[T
], D
::Error
>
158 Ok(decoder
.tcx().arena
.alloc_from_iter(<Vec
<T
> as Decodable
>::decode(decoder
)?
))
162 pub fn decode_cnum
<D
>(decoder
: &mut D
) -> Result
<CrateNum
, D
::Error
>
166 let cnum
= CrateNum
::from_u32(u32::decode(decoder
)?
);
167 Ok(decoder
.map_encoded_cnum_to_current(cnum
))
170 #[allow(rustc::usage_of_ty_tykind)]
172 pub fn decode_ty
<D
>(decoder
: &mut D
) -> Result
<Ty
<'tcx
>, D
::Error
>
176 // Handle shorthands first, if we have an usize > 0x80.
177 if decoder
.positioned_at_shorthand() {
178 let pos
= decoder
.read_usize()?
;
179 assert
!(pos
>= SHORTHAND_OFFSET
);
180 let shorthand
= pos
- SHORTHAND_OFFSET
;
182 decoder
.cached_ty_for_shorthand(shorthand
, |decoder
| {
183 decoder
.with_position(shorthand
, Ty
::decode
)
186 let tcx
= decoder
.tcx();
187 Ok(tcx
.mk_ty(ty
::TyKind
::decode(decoder
)?
))
192 pub fn decode_spanned_predicates
<D
>(
194 ) -> Result
<&'tcx
[(ty
::Predicate
<'tcx
>, Span
)], D
::Error
>
198 let tcx
= decoder
.tcx();
199 Ok(tcx
.arena
.alloc_from_iter(
200 (0..decoder
.read_usize()?
)
202 // Handle shorthands first, if we have an usize > 0x80.
203 let predicate_kind
= if decoder
.positioned_at_shorthand() {
204 let pos
= decoder
.read_usize()?
;
205 assert
!(pos
>= SHORTHAND_OFFSET
);
206 let shorthand
= pos
- SHORTHAND_OFFSET
;
208 decoder
.with_position(shorthand
, ty
::PredicateKind
::decode
)
210 ty
::PredicateKind
::decode(decoder
)
212 let predicate
= predicate_kind
.to_predicate(tcx
);
213 Ok((predicate
, Decodable
::decode(decoder
)?
))
215 .collect
::<Result
<Vec
<_
>, _
>>()?
,
220 pub fn decode_substs
<D
>(decoder
: &mut D
) -> Result
<SubstsRef
<'tcx
>, D
::Error
>
224 let len
= decoder
.read_usize()?
;
225 let tcx
= decoder
.tcx();
226 Ok(tcx
.mk_substs((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
230 pub fn decode_place
<D
>(decoder
: &mut D
) -> Result
<mir
::Place
<'tcx
>, D
::Error
>
234 let local
: mir
::Local
= Decodable
::decode(decoder
)?
;
235 let len
= decoder
.read_usize()?
;
236 let projection
: &'tcx List
<mir
::PlaceElem
<'tcx
>> =
237 decoder
.tcx().mk_place_elems((0..len
).map(|_
| Decodable
::decode(decoder
)))?
;
238 Ok(mir
::Place { local, projection }
)
242 pub fn decode_region
<D
>(decoder
: &mut D
) -> Result
<ty
::Region
<'tcx
>, D
::Error
>
246 Ok(decoder
.tcx().mk_region(Decodable
::decode(decoder
)?
))
250 pub fn decode_ty_slice
<D
>(decoder
: &mut D
) -> Result
<&'tcx ty
::List
<Ty
<'tcx
>>, D
::Error
>
254 let len
= decoder
.read_usize()?
;
255 Ok(decoder
.tcx().mk_type_list((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
259 pub fn decode_adt_def
<D
>(decoder
: &mut D
) -> Result
<&'tcx ty
::AdtDef
, D
::Error
>
263 let def_id
= DefId
::decode(decoder
)?
;
264 Ok(decoder
.tcx().adt_def(def_id
))
268 pub fn decode_existential_predicate_slice
<D
>(
270 ) -> Result
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>, D
::Error
>
274 let len
= decoder
.read_usize()?
;
275 Ok(decoder
.tcx().mk_existential_predicates((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
279 pub fn decode_canonical_var_infos
<D
>(decoder
: &mut D
) -> Result
<CanonicalVarInfos
<'tcx
>, D
::Error
>
283 let len
= decoder
.read_usize()?
;
284 let interned
: Result
<Vec
<CanonicalVarInfo
>, _
> =
285 (0..len
).map(|_
| Decodable
::decode(decoder
)).collect();
286 Ok(decoder
.tcx().intern_canonical_var_infos(interned?
.as_slice()))
290 pub fn decode_const
<D
>(decoder
: &mut D
) -> Result
<&'tcx ty
::Const
<'tcx
>, D
::Error
>
294 Ok(decoder
.tcx().mk_const(Decodable
::decode(decoder
)?
))
298 pub fn decode_allocation
<D
>(decoder
: &mut D
) -> Result
<&'tcx Allocation
, D
::Error
>
302 Ok(decoder
.tcx().intern_const_alloc(Decodable
::decode(decoder
)?
))
306 macro_rules
! __impl_decoder_methods
{
307 ($
($name
:ident
-> $ty
:ty
;)*) => {
310 fn $
name(&mut self) -> Result
<$ty
, Self::Error
> {
318 macro_rules
! impl_arena_allocatable_decoder
{
320 ([decode $
(, $attrs
:ident
)*]
321 [[$DecoderName
:ident
[$
($typaram
:tt
),*]], [$name
:ident
: $ty
:ty
], $tcx
:lifetime
]) => {
322 impl<$
($typaram
),*> SpecializedDecoder
<&$tcx $ty
> for $DecoderName
<$
($typaram
),*> {
324 fn specialized_decode(&mut self) -> Result
<&$tcx $ty
, Self::Error
> {
325 decode_arena_allocable(self)
329 impl<$
($typaram
),*> SpecializedDecoder
<&$tcx
[$ty
]> for $DecoderName
<$
($typaram
),*> {
331 fn specialized_decode(&mut self) -> Result
<&$tcx
[$ty
], Self::Error
> {
332 decode_arena_allocable_slice(self)
336 ([$ignore
:ident $
(, $attrs
:ident
)*]$args
:tt
) => {
337 impl_arena_allocatable_decoder
!([$
($attrs
),*]$args
);
342 macro_rules
! impl_arena_allocatable_decoders
{
343 ($args
:tt
, [$
($a
:tt $name
:ident
: $ty
:ty
,)*], $tcx
:lifetime
) => {
345 impl_arena_allocatable_decoder
!($a
[$args
, [$name
: $ty
], $tcx
]);
351 macro_rules
! implement_ty_decoder
{
352 ($DecoderName
:ident
<$
($typaram
:tt
),*>) => {
353 mod __ty_decoder_impl
{
354 use std
::borrow
::Cow
;
356 use rustc_serialize
::{Decoder, SpecializedDecoder}
;
358 use $
crate::infer
::canonical
::CanonicalVarInfos
;
360 use $
crate::ty
::codec
::*;
361 use $
crate::ty
::subst
::SubstsRef
;
362 use rustc_hir
::def_id
::{CrateNum}
;
364 use rustc_span
::Span
;
366 use super::$DecoderName
;
368 impl<$
($typaram
),*> Decoder
for $DecoderName
<$
($typaram
),*> {
371 __impl_decoder_methods
! {
392 read_str
-> Cow
<'_
, str>;
395 fn error(&mut self, err
: &str) -> Self::Error
{
396 self.opaque
.error(err
)
400 // FIXME(#36588): These impls are horribly unsound as they allow
401 // the caller to pick any lifetime for `'tcx`, including `'static`,
402 // by using the unspecialized proxies to them.
404 rustc_hir
::arena_types
!(impl_arena_allocatable_decoders
, [$DecoderName
[$
($typaram
),*]], 'tcx
);
405 arena_types
!(impl_arena_allocatable_decoders
, [$DecoderName
[$
($typaram
),*]], 'tcx
);
407 impl<$
($typaram
),*> SpecializedDecoder
<CrateNum
>
408 for $DecoderName
<$
($typaram
),*> {
409 fn specialized_decode(&mut self) -> Result
<CrateNum
, Self::Error
> {
414 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Ty
<'tcx
>>
415 for $DecoderName
<$
($typaram
),*> {
416 fn specialized_decode(&mut self) -> Result
<ty
::Ty
<'tcx
>, Self::Error
> {
421 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx
[(ty
::Predicate
<'tcx
>, Span
)]>
422 for $DecoderName
<$
($typaram
),*> {
423 fn specialized_decode(&mut self)
424 -> Result
<&'tcx
[(ty
::Predicate
<'tcx
>, Span
)], Self::Error
> {
425 decode_spanned_predicates(self)
429 impl<$
($typaram
),*> SpecializedDecoder
<SubstsRef
<'tcx
>>
430 for $DecoderName
<$
($typaram
),*> {
431 fn specialized_decode(&mut self) -> Result
<SubstsRef
<'tcx
>, Self::Error
> {
436 impl<$
($typaram
),*> SpecializedDecoder
<$
crate::mir
::Place
<'tcx
>>
437 for $DecoderName
<$
($typaram
),*> {
438 fn specialized_decode(
440 ) -> Result
<$
crate::mir
::Place
<'tcx
>, Self::Error
> {
445 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Region
<'tcx
>>
446 for $DecoderName
<$
($typaram
),*> {
447 fn specialized_decode(&mut self) -> Result
<ty
::Region
<'tcx
>, Self::Error
> {
452 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::List
<ty
::Ty
<'tcx
>>>
453 for $DecoderName
<$
($typaram
),*> {
454 fn specialized_decode(&mut self)
455 -> Result
<&'tcx ty
::List
<ty
::Ty
<'tcx
>>, Self::Error
> {
456 decode_ty_slice(self)
460 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::AdtDef
>
461 for $DecoderName
<$
($typaram
),*> {
462 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::AdtDef
, Self::Error
> {
467 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>>
468 for $DecoderName
<$
($typaram
),*> {
469 fn specialized_decode(&mut self)
470 -> Result
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>, Self::Error
> {
471 decode_existential_predicate_slice(self)
475 impl<$
($typaram
),*> SpecializedDecoder
<CanonicalVarInfos
<'tcx
>>
476 for $DecoderName
<$
($typaram
),*> {
477 fn specialized_decode(&mut self)
478 -> Result
<CanonicalVarInfos
<'tcx
>, Self::Error
> {
479 decode_canonical_var_infos(self)
483 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx $
crate::ty
::Const
<'tcx
>>
484 for $DecoderName
<$
($typaram
),*> {
485 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::Const
<'tcx
>, Self::Error
> {
490 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx $
crate::mir
::interpret
::Allocation
>
491 for $DecoderName
<$
($typaram
),*> {
492 fn specialized_decode(
494 ) -> Result
<&'tcx $
crate::mir
::interpret
::Allocation
, Self::Error
> {
495 decode_allocation(self)