1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // This module contains some shared code for encoding and decoding various
12 // things from the `ty` module, and in particular implements support for
13 // "shorthands" which allow to have pointers back into the already encoded
14 // stream instead of re-encoding the same thing twice.
16 // The functionality in here is shared between persisting to crate metadata and
17 // persisting to incr. comp. caches.
19 use hir
::def_id
::{DefId, CrateNum}
;
20 use infer
::canonical
::{CanonicalVarInfo, CanonicalVarInfos}
;
21 use rustc_data_structures
::fx
::FxHashMap
;
22 use rustc_serialize
::{Decodable, Decoder, Encoder, Encodable, opaque}
;
25 use ty
::{self, Ty, TyCtxt}
;
26 use ty
::subst
::Substs
;
27 use mir
::interpret
::Allocation
;
29 /// The shorthand encoding uses an enum's variant index `usize`
30 /// and is offset by this value so it never matches a real variant.
31 /// This offset is also chosen so that the first byte is never < 0x80.
32 pub const SHORTHAND_OFFSET
: usize = 0x80;
34 pub trait EncodableWithShorthand
: Clone
+ Eq
+ Hash
{
35 type Variant
: Encodable
;
36 fn variant(&self) -> &Self::Variant
;
39 impl<'tcx
> EncodableWithShorthand
for Ty
<'tcx
> {
40 type Variant
= ty
::TypeVariants
<'tcx
>;
41 fn variant(&self) -> &Self::Variant
{
46 impl<'tcx
> EncodableWithShorthand
for ty
::Predicate
<'tcx
> {
47 type Variant
= ty
::Predicate
<'tcx
>;
48 fn variant(&self) -> &Self::Variant
{
53 pub trait TyEncoder
: Encoder
{
54 fn position(&self) -> usize;
57 impl TyEncoder
for opaque
::Encoder
{
59 fn position(&self) -> usize {
64 /// Encode the given value or a previously cached shorthand.
65 pub fn encode_with_shorthand
<E
, T
, M
>(encoder
: &mut E
,
68 -> Result
<(), E
::Error
>
70 M
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<T
, usize>,
71 T
: EncodableWithShorthand
,
73 let existing_shorthand
= cache(encoder
).get(value
).cloned();
74 if let Some(shorthand
) = existing_shorthand
{
75 return encoder
.emit_usize(shorthand
);
78 let variant
= value
.variant();
80 let start
= encoder
.position();
81 variant
.encode(encoder
)?
;
82 let len
= encoder
.position() - start
;
84 // The shorthand encoding uses the same usize as the
85 // discriminant, with an offset so they can't conflict.
86 let discriminant
= unsafe { intrinsics::discriminant_value(variant) }
;
87 assert
!(discriminant
< SHORTHAND_OFFSET
as u64);
88 let shorthand
= start
+ SHORTHAND_OFFSET
;
90 // Get the number of bits that leb128 could fit
91 // in the same space as the fully encoded type.
92 let leb128_bits
= len
* 7;
94 // Check that the shorthand is a not longer than the
95 // full encoding itself, i.e. it's an obvious win.
96 if leb128_bits
>= 64 || (shorthand
as u64) < (1 << leb128_bits
) {
97 cache(encoder
).insert(value
.clone(), shorthand
);
103 pub fn encode_predicates
<'tcx
, E
, C
>(encoder
: &mut E
,
104 predicates
: &ty
::GenericPredicates
<'tcx
>,
106 -> Result
<(), E
::Error
>
108 C
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
110 predicates
.parent
.encode(encoder
)?
;
111 predicates
.predicates
.len().encode(encoder
)?
;
112 for predicate
in &predicates
.predicates
{
113 encode_with_shorthand(encoder
, predicate
, &cache
)?
118 pub trait TyDecoder
<'a
, 'tcx
: 'a
>: Decoder
{
120 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
>;
122 fn peek_byte(&self) -> u8;
124 fn position(&self) -> usize;
126 fn cached_ty_for_shorthand
<F
>(&mut self,
129 -> Result
<Ty
<'tcx
>, Self::Error
>
130 where F
: FnOnce(&mut Self) -> Result
<Ty
<'tcx
>, Self::Error
>;
132 fn with_position
<F
, R
>(&mut self, pos
: usize, f
: F
) -> R
133 where F
: FnOnce(&mut Self) -> R
;
135 fn map_encoded_cnum_to_current(&self, cnum
: CrateNum
) -> CrateNum
;
137 fn positioned_at_shorthand(&self) -> bool
{
138 (self.peek_byte() & (SHORTHAND_OFFSET
as u8)) != 0
143 pub fn decode_cnum
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<CrateNum
, D
::Error
>
144 where D
: TyDecoder
<'a
, 'tcx
>,
147 let cnum
= CrateNum
::from_u32(u32::decode(decoder
)?
);
148 Ok(decoder
.map_encoded_cnum_to_current(cnum
))
152 pub fn decode_ty
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<Ty
<'tcx
>, D
::Error
>
153 where D
: TyDecoder
<'a
, 'tcx
>,
156 // Handle shorthands first, if we have an usize > 0x80.
157 if decoder
.positioned_at_shorthand() {
158 let pos
= decoder
.read_usize()?
;
159 assert
!(pos
>= SHORTHAND_OFFSET
);
160 let shorthand
= pos
- SHORTHAND_OFFSET
;
162 decoder
.cached_ty_for_shorthand(shorthand
, |decoder
| {
163 decoder
.with_position(shorthand
, Ty
::decode
)
166 let tcx
= decoder
.tcx();
167 Ok(tcx
.mk_ty(ty
::TypeVariants
::decode(decoder
)?
))
172 pub fn decode_predicates
<'a
, 'tcx
, D
>(decoder
: &mut D
)
173 -> Result
<ty
::GenericPredicates
<'tcx
>, D
::Error
>
174 where D
: TyDecoder
<'a
, 'tcx
>,
177 Ok(ty
::GenericPredicates
{
178 parent
: Decodable
::decode(decoder
)?
,
179 predicates
: (0..decoder
.read_usize()?
).map(|_
| {
180 // Handle shorthands first, if we have an usize > 0x80.
181 if decoder
.positioned_at_shorthand() {
182 let pos
= decoder
.read_usize()?
;
183 assert
!(pos
>= SHORTHAND_OFFSET
);
184 let shorthand
= pos
- SHORTHAND_OFFSET
;
186 decoder
.with_position(shorthand
, ty
::Predicate
::decode
)
188 ty
::Predicate
::decode(decoder
)
191 .collect
::<Result
<Vec
<_
>, _
>>()?
,
196 pub fn decode_substs
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<&'tcx Substs
<'tcx
>, D
::Error
>
197 where D
: TyDecoder
<'a
, 'tcx
>,
200 let len
= decoder
.read_usize()?
;
201 let tcx
= decoder
.tcx();
202 Ok(tcx
.mk_substs((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
206 pub fn decode_region
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<ty
::Region
<'tcx
>, D
::Error
>
207 where D
: TyDecoder
<'a
, 'tcx
>,
210 Ok(decoder
.tcx().mk_region(Decodable
::decode(decoder
)?
))
214 pub fn decode_ty_slice
<'a
, 'tcx
, D
>(decoder
: &mut D
)
215 -> Result
<&'tcx ty
::Slice
<Ty
<'tcx
>>, D
::Error
>
216 where D
: TyDecoder
<'a
, 'tcx
>,
219 let len
= decoder
.read_usize()?
;
220 Ok(decoder
.tcx().mk_type_list((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
224 pub fn decode_adt_def
<'a
, 'tcx
, D
>(decoder
: &mut D
)
225 -> Result
<&'tcx ty
::AdtDef
, D
::Error
>
226 where D
: TyDecoder
<'a
, 'tcx
>,
229 let def_id
= DefId
::decode(decoder
)?
;
230 Ok(decoder
.tcx().adt_def(def_id
))
234 pub fn decode_existential_predicate_slice
<'a
, 'tcx
, D
>(decoder
: &mut D
)
235 -> Result
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>, D
::Error
>
236 where D
: TyDecoder
<'a
, 'tcx
>,
239 let len
= decoder
.read_usize()?
;
241 .mk_existential_predicates((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
245 pub fn decode_canonical_var_infos
<'a
, 'tcx
, D
>(decoder
: &mut D
)
246 -> Result
<CanonicalVarInfos
<'tcx
>, D
::Error
>
247 where D
: TyDecoder
<'a
, 'tcx
>,
250 let len
= decoder
.read_usize()?
;
251 let interned
: Result
<Vec
<CanonicalVarInfo
>, _
> = (0..len
).map(|_
| Decodable
::decode(decoder
))
254 .intern_canonical_var_infos(interned?
.as_slice()))
258 pub fn decode_const
<'a
, 'tcx
, D
>(decoder
: &mut D
)
259 -> Result
<&'tcx ty
::Const
<'tcx
>, D
::Error
>
260 where D
: TyDecoder
<'a
, 'tcx
>,
263 Ok(decoder
.tcx().mk_const(Decodable
::decode(decoder
)?
))
267 pub fn decode_allocation
<'a
, 'tcx
, D
>(decoder
: &mut D
)
268 -> Result
<&'tcx Allocation
, D
::Error
>
269 where D
: TyDecoder
<'a
, 'tcx
>,
272 Ok(decoder
.tcx().intern_const_alloc(Decodable
::decode(decoder
)?
))
276 macro_rules
! __impl_decoder_methods
{
277 ($
($name
:ident
-> $ty
:ty
;)*) => {
278 $
(fn $
name(&mut self) -> Result
<$ty
, Self::Error
> {
285 macro_rules
! implement_ty_decoder
{
286 ($DecoderName
:ident
<$
($typaram
:tt
),*>) => {
287 mod __ty_decoder_impl
{
288 use super::$DecoderName
;
289 use $
crate::infer
::canonical
::CanonicalVarInfos
;
291 use $
crate::ty
::codec
::*;
292 use $
crate::ty
::subst
::Substs
;
293 use $
crate::hir
::def_id
::{CrateNum}
;
294 use rustc_serialize
::{Decoder, SpecializedDecoder}
;
295 use std
::borrow
::Cow
;
297 impl<$
($typaram
),*> Decoder
for $DecoderName
<$
($typaram
),*> {
300 __impl_decoder_methods
! {
321 read_str
-> Cow
<str>;
324 fn error(&mut self, err
: &str) -> Self::Error
{
325 self.opaque
.error(err
)
329 // FIXME(#36588) These impls are horribly unsound as they allow
330 // the caller to pick any lifetime for 'tcx, including 'static,
331 // by using the unspecialized proxies to them.
333 impl<$
($typaram
),*> SpecializedDecoder
<CrateNum
>
334 for $DecoderName
<$
($typaram
),*> {
335 fn specialized_decode(&mut self) -> Result
<CrateNum
, Self::Error
> {
340 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Ty
<'tcx
>>
341 for $DecoderName
<$
($typaram
),*> {
342 fn specialized_decode(&mut self) -> Result
<ty
::Ty
<'tcx
>, Self::Error
> {
347 impl<$
($typaram
),*> SpecializedDecoder
<ty
::GenericPredicates
<'tcx
>>
348 for $DecoderName
<$
($typaram
),*> {
349 fn specialized_decode(&mut self)
350 -> Result
<ty
::GenericPredicates
<'tcx
>, Self::Error
> {
351 decode_predicates(self)
355 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx Substs
<'tcx
>>
356 for $DecoderName
<$
($typaram
),*> {
357 fn specialized_decode(&mut self) -> Result
<&'tcx Substs
<'tcx
>, Self::Error
> {
362 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Region
<'tcx
>>
363 for $DecoderName
<$
($typaram
),*> {
364 fn specialized_decode(&mut self) -> Result
<ty
::Region
<'tcx
>, Self::Error
> {
369 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::Slice
<ty
::Ty
<'tcx
>>>
370 for $DecoderName
<$
($typaram
),*> {
371 fn specialized_decode(&mut self)
372 -> Result
<&'tcx ty
::Slice
<ty
::Ty
<'tcx
>>, Self::Error
> {
373 decode_ty_slice(self)
377 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::AdtDef
>
378 for $DecoderName
<$
($typaram
),*> {
379 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::AdtDef
, Self::Error
> {
384 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>>
385 for $DecoderName
<$
($typaram
),*> {
386 fn specialized_decode(&mut self)
387 -> Result
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>, Self::Error
> {
388 decode_existential_predicate_slice(self)
392 impl<$
($typaram
),*> SpecializedDecoder
<CanonicalVarInfos
<'tcx
>>
393 for $DecoderName
<$
($typaram
),*> {
394 fn specialized_decode(&mut self)
395 -> Result
<CanonicalVarInfos
<'tcx
>, Self::Error
> {
396 decode_canonical_var_infos(self)
400 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx $
crate::ty
::Const
<'tcx
>>
401 for $DecoderName
<$
($typaram
),*> {
402 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::Const
<'tcx
>, Self::Error
> {
407 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx $
crate::mir
::interpret
::Allocation
>
408 for $DecoderName
<$
($typaram
),*> {
409 fn specialized_decode(
411 ) -> Result
<&'tcx $
crate::mir
::interpret
::Allocation
, Self::Error
> {
412 decode_allocation(self)