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}
;
13 interpret
::{AllocId, Allocation}
,
15 use crate::ty
::subst
::SubstsRef
;
16 use crate::ty
::{self, List, Ty, TyCtxt}
;
17 use rustc_data_structures
::fx
::FxHashMap
;
18 use rustc_hir
::def_id
::{CrateNum, DefId}
;
19 use rustc_serialize
::{Decodable, Decoder, Encodable, Encoder}
;
21 use std
::convert
::{TryFrom, TryInto}
;
24 use std
::marker
::DiscriminantKind
;
26 /// The shorthand encoding uses an enum's variant index `usize`
27 /// and is offset by this value so it never matches a real variant.
28 /// This offset is also chosen so that the first byte is never < 0x80.
29 pub const SHORTHAND_OFFSET
: usize = 0x80;
31 pub trait EncodableWithShorthand
<'tcx
, E
: TyEncoder
<'tcx
>>: Copy
+ Eq
+ Hash
{
32 type Variant
: Encodable
<E
>;
33 fn variant(&self) -> &Self::Variant
;
36 #[allow(rustc::usage_of_ty_tykind)]
37 impl<'tcx
, E
: TyEncoder
<'tcx
>> EncodableWithShorthand
<'tcx
, E
> for Ty
<'tcx
> {
38 type Variant
= ty
::TyKind
<'tcx
>;
41 fn variant(&self) -> &Self::Variant
{
46 impl<'tcx
, E
: TyEncoder
<'tcx
>> EncodableWithShorthand
<'tcx
, E
> for ty
::Predicate
<'tcx
> {
47 type Variant
= ty
::PredicateKind
<'tcx
>;
48 fn variant(&self) -> &Self::Variant
{
53 pub trait OpaqueEncoder
: Encoder
{
54 fn opaque(&mut self) -> &mut rustc_serialize
::opaque
::Encoder
;
55 fn encoder_position(&self) -> usize;
58 impl OpaqueEncoder
for rustc_serialize
::opaque
::Encoder
{
60 fn opaque(&mut self) -> &mut rustc_serialize
::opaque
::Encoder
{
64 fn encoder_position(&self) -> usize {
69 pub trait TyEncoder
<'tcx
>: Encoder
{
70 const CLEAR_CROSS_CRATE
: bool
;
72 fn tcx(&self) -> TyCtxt
<'tcx
>;
73 fn position(&self) -> usize;
74 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize>;
75 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<ty
::Predicate
<'tcx
>, usize>;
76 fn encode_alloc_id(&mut self, alloc_id
: &AllocId
) -> Result
<(), Self::Error
>;
79 /// Trait for decoding to a reference.
81 /// This is a separate trait from `Decodable` so that we can implement it for
82 /// upstream types, such as `FxHashSet`.
84 /// The `TyDecodable` derive macro will use this trait for fields that are
85 /// references (and don't use a type alias to hide that).
87 /// `Decodable` can still be implemented in cases where `Decodable` is required
89 pub trait RefDecodable
<'tcx
, D
: TyDecoder
<'tcx
>> {
90 fn decode(d
: &mut D
) -> Result
<&'tcx
Self, D
::Error
>;
93 /// Encode the given value or a previously cached shorthand.
94 pub fn encode_with_shorthand
<E
, T
, M
>(encoder
: &mut E
, value
: &T
, cache
: M
) -> Result
<(), E
::Error
>
97 M
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<T
, usize>,
98 T
: EncodableWithShorthand
<'tcx
, E
>,
99 <T
::Variant
as DiscriminantKind
>::Discriminant
: Ord
+ TryFrom
<usize>,
101 let existing_shorthand
= cache(encoder
).get(value
).copied();
102 if let Some(shorthand
) = existing_shorthand
{
103 return encoder
.emit_usize(shorthand
);
106 let variant
= value
.variant();
108 let start
= encoder
.position();
109 variant
.encode(encoder
)?
;
110 let len
= encoder
.position() - start
;
112 // The shorthand encoding uses the same usize as the
113 // discriminant, with an offset so they can't conflict.
114 let discriminant
= intrinsics
::discriminant_value(variant
);
115 assert
!(discriminant
< SHORTHAND_OFFSET
.try_into().ok().unwrap());
117 let shorthand
= start
+ SHORTHAND_OFFSET
;
119 // Get the number of bits that leb128 could fit
120 // in the same space as the fully encoded type.
121 let leb128_bits
= len
* 7;
123 // Check that the shorthand is a not longer than the
124 // full encoding itself, i.e., it's an obvious win.
125 if leb128_bits
>= 64 || (shorthand
as u64) < (1 << leb128_bits
) {
126 cache(encoder
).insert(*value
, shorthand
);
132 impl<'tcx
, E
: TyEncoder
<'tcx
>> Encodable
<E
> for Ty
<'tcx
> {
133 fn encode(&self, e
: &mut E
) -> Result
<(), E
::Error
> {
134 encode_with_shorthand(e
, self, TyEncoder
::type_shorthands
)
138 impl<'tcx
, E
: TyEncoder
<'tcx
>> Encodable
<E
> for ty
::Predicate
<'tcx
> {
139 fn encode(&self, e
: &mut E
) -> Result
<(), E
::Error
> {
140 encode_with_shorthand(e
, self, TyEncoder
::predicate_shorthands
)
144 impl<'tcx
, E
: TyEncoder
<'tcx
>> Encodable
<E
> for AllocId
{
145 fn encode(&self, e
: &mut E
) -> Result
<(), E
::Error
> {
146 e
.encode_alloc_id(self)
150 macro_rules
! encodable_via_deref
{
152 $
(impl<'tcx
, E
: TyEncoder
<'tcx
>> Encodable
<E
> for $t
{
153 fn encode(&self, e
: &mut E
) -> Result
<(), E
::Error
> {
160 encodable_via_deref
! {
161 &'tcx ty
::TypeckResults
<'tcx
>,
163 &'tcx mir
::Body
<'tcx
>,
164 &'tcx mir
::UnsafetyCheckResult
,
165 &'tcx mir
::BorrowCheckResult
<'tcx
>
168 pub trait TyDecoder
<'tcx
>: Decoder
{
169 const CLEAR_CROSS_CRATE
: bool
;
171 fn tcx(&self) -> TyCtxt
<'tcx
>;
173 fn peek_byte(&self) -> u8;
175 fn position(&self) -> usize;
177 fn cached_ty_for_shorthand
<F
>(
181 ) -> Result
<Ty
<'tcx
>, Self::Error
>
183 F
: FnOnce(&mut Self) -> Result
<Ty
<'tcx
>, Self::Error
>;
185 fn cached_predicate_for_shorthand
<F
>(
189 ) -> Result
<ty
::Predicate
<'tcx
>, Self::Error
>
191 F
: FnOnce(&mut Self) -> Result
<ty
::Predicate
<'tcx
>, Self::Error
>;
193 fn with_position
<F
, R
>(&mut self, pos
: usize, f
: F
) -> R
195 F
: FnOnce(&mut Self) -> R
;
197 fn map_encoded_cnum_to_current(&self, cnum
: CrateNum
) -> CrateNum
;
199 fn positioned_at_shorthand(&self) -> bool
{
200 (self.peek_byte() & (SHORTHAND_OFFSET
as u8)) != 0
203 fn decode_alloc_id(&mut self) -> Result
<AllocId
, Self::Error
>;
207 pub fn decode_arena_allocable
<'tcx
, D
, T
: ArenaAllocatable
<'tcx
> + Decodable
<D
>>(
209 ) -> Result
<&'tcx T
, D
::Error
>
213 Ok(decoder
.tcx().arena
.alloc(Decodable
::decode(decoder
)?
))
217 pub fn decode_arena_allocable_slice
<'tcx
, D
, T
: ArenaAllocatable
<'tcx
> + Decodable
<D
>>(
219 ) -> Result
<&'tcx
[T
], D
::Error
>
223 Ok(decoder
.tcx().arena
.alloc_from_iter(<Vec
<T
> as Decodable
<D
>>::decode(decoder
)?
))
226 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for Ty
<'tcx
> {
227 #[allow(rustc::usage_of_ty_tykind)]
228 fn decode(decoder
: &mut D
) -> Result
<Ty
<'tcx
>, D
::Error
> {
229 // Handle shorthands first, if we have an usize > 0x80.
230 if decoder
.positioned_at_shorthand() {
231 let pos
= decoder
.read_usize()?
;
232 assert
!(pos
>= SHORTHAND_OFFSET
);
233 let shorthand
= pos
- SHORTHAND_OFFSET
;
235 decoder
.cached_ty_for_shorthand(shorthand
, |decoder
| {
236 decoder
.with_position(shorthand
, Ty
::decode
)
239 let tcx
= decoder
.tcx();
240 Ok(tcx
.mk_ty(ty
::TyKind
::decode(decoder
)?
))
245 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for ty
::Predicate
<'tcx
> {
246 fn decode(decoder
: &mut D
) -> Result
<ty
::Predicate
<'tcx
>, D
::Error
> {
247 // Handle shorthands first, if we have an usize > 0x80.
248 let predicate_kind
= if decoder
.positioned_at_shorthand() {
249 let pos
= decoder
.read_usize()?
;
250 assert
!(pos
>= SHORTHAND_OFFSET
);
251 let shorthand
= pos
- SHORTHAND_OFFSET
;
253 decoder
.with_position(shorthand
, ty
::PredicateKind
::decode
)
255 ty
::PredicateKind
::decode(decoder
)
257 let predicate
= decoder
.tcx().mk_predicate(predicate_kind
);
262 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for SubstsRef
<'tcx
> {
263 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
264 let len
= decoder
.read_usize()?
;
265 let tcx
= decoder
.tcx();
266 Ok(tcx
.mk_substs((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
270 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for mir
::Place
<'tcx
> {
271 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
272 let local
: mir
::Local
= Decodable
::decode(decoder
)?
;
273 let len
= decoder
.read_usize()?
;
274 let projection
: &'tcx List
<mir
::PlaceElem
<'tcx
>> =
275 decoder
.tcx().mk_place_elems((0..len
).map(|_
| Decodable
::decode(decoder
)))?
;
276 Ok(mir
::Place { local, projection }
)
280 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for ty
::Region
<'tcx
> {
281 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
282 Ok(decoder
.tcx().mk_region(Decodable
::decode(decoder
)?
))
286 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for CanonicalVarInfos
<'tcx
> {
287 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
288 let len
= decoder
.read_usize()?
;
289 let interned
: Result
<Vec
<CanonicalVarInfo
>, _
> =
290 (0..len
).map(|_
| Decodable
::decode(decoder
)).collect();
291 Ok(decoder
.tcx().intern_canonical_var_infos(interned?
.as_slice()))
295 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for AllocId
{
296 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
297 decoder
.decode_alloc_id()
301 impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for ty
::SymbolName
<'tcx
> {
302 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
303 Ok(ty
::SymbolName
::new(decoder
.tcx(), &decoder
.read_str()?
))
307 macro_rules
! impl_decodable_via_ref
{
309 $
(impl<'tcx
, D
: TyDecoder
<'tcx
>> Decodable
<D
> for $t
{
310 fn decode(decoder
: &mut D
) -> Result
<Self, D
::Error
> {
311 RefDecodable
::decode(decoder
)
317 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for ty
::AdtDef
{
318 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
319 let def_id
= <DefId
as Decodable
<D
>>::decode(decoder
)?
;
320 Ok(decoder
.tcx().adt_def(def_id
))
324 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for ty
::List
<Ty
<'tcx
>> {
325 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
326 let len
= decoder
.read_usize()?
;
327 Ok(decoder
.tcx().mk_type_list((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
331 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for ty
::List
<ty
::ExistentialPredicate
<'tcx
>> {
332 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
333 let len
= decoder
.read_usize()?
;
334 Ok(decoder
.tcx().mk_existential_predicates((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
338 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for ty
::Const
<'tcx
> {
339 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
340 Ok(decoder
.tcx().mk_const(Decodable
::decode(decoder
)?
))
344 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for Allocation
{
345 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
346 Ok(decoder
.tcx().intern_const_alloc(Decodable
::decode(decoder
)?
))
350 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for [(ty
::Predicate
<'tcx
>, Span
)] {
351 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
352 Ok(decoder
.tcx().arena
.alloc_from_iter(
353 (0..decoder
.read_usize()?
)
354 .map(|_
| Decodable
::decode(decoder
))
355 .collect
::<Result
<Vec
<_
>, _
>>()?
,
360 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for [mir
::abstract_const
::Node
<'tcx
>] {
361 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
362 Ok(decoder
.tcx().arena
.alloc_from_iter(
363 (0..decoder
.read_usize()?
)
364 .map(|_
| Decodable
::decode(decoder
))
365 .collect
::<Result
<Vec
<_
>, _
>>()?
,
370 impl<'tcx
, D
: TyDecoder
<'tcx
>> RefDecodable
<'tcx
, D
> for [mir
::abstract_const
::NodeId
] {
371 fn decode(decoder
: &mut D
) -> Result
<&'tcx
Self, D
::Error
> {
372 Ok(decoder
.tcx().arena
.alloc_from_iter(
373 (0..decoder
.read_usize()?
)
374 .map(|_
| Decodable
::decode(decoder
))
375 .collect
::<Result
<Vec
<_
>, _
>>()?
,
380 impl_decodable_via_ref
! {
381 &'tcx ty
::TypeckResults
<'tcx
>,
382 &'tcx ty
::List
<Ty
<'tcx
>>,
383 &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
385 &'tcx mir
::Body
<'tcx
>,
386 &'tcx mir
::UnsafetyCheckResult
,
387 &'tcx mir
::BorrowCheckResult
<'tcx
>
391 macro_rules
! __impl_decoder_methods
{
392 ($
($name
:ident
-> $ty
:ty
;)*) => {
395 fn $
name(&mut self) -> Result
<$ty
, Self::Error
> {
402 macro_rules
! impl_arena_allocatable_decoder
{
404 ([decode $
(, $attrs
:ident
)*]
405 [[$name
:ident
: $ty
:ty
], $tcx
:lifetime
]) => {
406 impl<$tcx
, D
: TyDecoder
<$tcx
>> RefDecodable
<$tcx
, D
> for $ty
{
408 fn decode(decoder
: &mut D
) -> Result
<&$tcx
Self, D
::Error
> {
409 decode_arena_allocable(decoder
)
413 impl<$tcx
, D
: TyDecoder
<$tcx
>> RefDecodable
<$tcx
, D
> for [$ty
] {
415 fn decode(decoder
: &mut D
) -> Result
<&$tcx
Self, D
::Error
> {
416 decode_arena_allocable_slice(decoder
)
420 ([$ignore
:ident $
(, $attrs
:ident
)*]$args
:tt
) => {
421 impl_arena_allocatable_decoder
!([$
($attrs
),*]$args
);
425 macro_rules
! impl_arena_allocatable_decoders
{
426 ([], [$
($a
:tt $name
:ident
: $ty
:ty
,)*], $tcx
:lifetime
) => {
428 impl_arena_allocatable_decoder
!($a
[[$name
: $ty
], $tcx
]);
433 rustc_hir
::arena_types
!(impl_arena_allocatable_decoders
, [], 'tcx
);
434 arena_types
!(impl_arena_allocatable_decoders
, [], 'tcx
);
437 macro_rules
! implement_ty_decoder
{
438 ($DecoderName
:ident
<$
($typaram
:tt
),*>) => {
439 mod __ty_decoder_impl
{
440 use std
::borrow
::Cow
;
441 use rustc_serialize
::Decoder
;
443 use super::$DecoderName
;
445 impl<$
($typaram
),*> Decoder
for $DecoderName
<$
($typaram
),*> {
448 $
crate::__impl_decoder_methods
! {
469 read_str
-> Cow
<'_
, str>;
472 fn error(&mut self, err
: &str) -> Self::Error
{
473 self.opaque
.error(err
)