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 middle
::const_val
::ByteArray
;
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
;
28 /// The shorthand encoding uses an enum's variant index `usize`
29 /// and is offset by this value so it never matches a real variant.
30 /// This offset is also chosen so that the first byte is never < 0x80.
31 pub const SHORTHAND_OFFSET
: usize = 0x80;
33 pub trait EncodableWithShorthand
: Clone
+ Eq
+ Hash
{
34 type Variant
: Encodable
;
35 fn variant(&self) -> &Self::Variant
;
38 impl<'tcx
> EncodableWithShorthand
for Ty
<'tcx
> {
39 type Variant
= ty
::TypeVariants
<'tcx
>;
40 fn variant(&self) -> &Self::Variant
{
45 impl<'tcx
> EncodableWithShorthand
for ty
::Predicate
<'tcx
> {
46 type Variant
= ty
::Predicate
<'tcx
>;
47 fn variant(&self) -> &Self::Variant
{
52 pub trait TyEncoder
: Encoder
{
53 fn position(&self) -> usize;
56 impl<'buf
> TyEncoder
for opaque
::Encoder
<'buf
> {
58 fn position(&self) -> usize {
63 /// Encode the given value or a previously cached shorthand.
64 pub fn encode_with_shorthand
<E
, T
, M
>(encoder
: &mut E
,
67 -> Result
<(), E
::Error
>
69 M
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<T
, usize>,
70 T
: EncodableWithShorthand
,
72 let existing_shorthand
= cache(encoder
).get(value
).cloned();
73 if let Some(shorthand
) = existing_shorthand
{
74 return encoder
.emit_usize(shorthand
);
77 let variant
= value
.variant();
79 let start
= encoder
.position();
80 variant
.encode(encoder
)?
;
81 let len
= encoder
.position() - start
;
83 // The shorthand encoding uses the same usize as the
84 // discriminant, with an offset so they can't conflict.
85 let discriminant
= unsafe { intrinsics::discriminant_value(variant) }
;
86 assert
!(discriminant
< SHORTHAND_OFFSET
as u64);
87 let shorthand
= start
+ SHORTHAND_OFFSET
;
89 // Get the number of bits that leb128 could fit
90 // in the same space as the fully encoded type.
91 let leb128_bits
= len
* 7;
93 // Check that the shorthand is a not longer than the
94 // full encoding itself, i.e. it's an obvious win.
95 if leb128_bits
>= 64 || (shorthand
as u64) < (1 << leb128_bits
) {
96 cache(encoder
).insert(value
.clone(), shorthand
);
102 pub fn encode_predicates
<'tcx
, E
, C
>(encoder
: &mut E
,
103 predicates
: &ty
::GenericPredicates
<'tcx
>,
105 -> Result
<(), E
::Error
>
107 C
: for<'b
> Fn(&'b
mut E
) -> &'b
mut FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
109 predicates
.parent
.encode(encoder
)?
;
110 predicates
.predicates
.len().encode(encoder
)?
;
111 for predicate
in &predicates
.predicates
{
112 encode_with_shorthand(encoder
, predicate
, &cache
)?
117 pub trait TyDecoder
<'a
, 'tcx
: 'a
>: Decoder
{
119 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
>;
121 fn peek_byte(&self) -> u8;
123 fn position(&self) -> usize;
125 fn cached_ty_for_shorthand
<F
>(&mut self,
128 -> Result
<Ty
<'tcx
>, Self::Error
>
129 where F
: FnOnce(&mut Self) -> Result
<Ty
<'tcx
>, Self::Error
>;
131 fn with_position
<F
, R
>(&mut self, pos
: usize, f
: F
) -> R
132 where 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_cnum
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<CrateNum
, D
::Error
>
143 where D
: TyDecoder
<'a
, 'tcx
>,
146 let cnum
= CrateNum
::from_u32(u32::decode(decoder
)?
);
147 Ok(decoder
.map_encoded_cnum_to_current(cnum
))
151 pub fn decode_ty
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<Ty
<'tcx
>, D
::Error
>
152 where D
: TyDecoder
<'a
, 'tcx
>,
155 // Handle shorthands first, if we have an usize > 0x80.
156 if decoder
.positioned_at_shorthand() {
157 let pos
= decoder
.read_usize()?
;
158 assert
!(pos
>= SHORTHAND_OFFSET
);
159 let shorthand
= pos
- SHORTHAND_OFFSET
;
161 decoder
.cached_ty_for_shorthand(shorthand
, |decoder
| {
162 decoder
.with_position(shorthand
, Ty
::decode
)
165 let tcx
= decoder
.tcx();
166 Ok(tcx
.mk_ty(ty
::TypeVariants
::decode(decoder
)?
))
171 pub fn decode_predicates
<'a
, 'tcx
, D
>(decoder
: &mut D
)
172 -> Result
<ty
::GenericPredicates
<'tcx
>, D
::Error
>
173 where D
: TyDecoder
<'a
, 'tcx
>,
176 Ok(ty
::GenericPredicates
{
177 parent
: Decodable
::decode(decoder
)?
,
178 predicates
: (0..decoder
.read_usize()?
).map(|_
| {
179 // Handle shorthands first, if we have an usize > 0x80.
180 if decoder
.positioned_at_shorthand() {
181 let pos
= decoder
.read_usize()?
;
182 assert
!(pos
>= SHORTHAND_OFFSET
);
183 let shorthand
= pos
- SHORTHAND_OFFSET
;
185 decoder
.with_position(shorthand
, ty
::Predicate
::decode
)
187 ty
::Predicate
::decode(decoder
)
190 .collect
::<Result
<Vec
<_
>, _
>>()?
,
195 pub fn decode_substs
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<&'tcx Substs
<'tcx
>, D
::Error
>
196 where D
: TyDecoder
<'a
, 'tcx
>,
199 let len
= decoder
.read_usize()?
;
200 let tcx
= decoder
.tcx();
201 Ok(tcx
.mk_substs((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
205 pub fn decode_region
<'a
, 'tcx
, D
>(decoder
: &mut D
) -> Result
<ty
::Region
<'tcx
>, D
::Error
>
206 where D
: TyDecoder
<'a
, 'tcx
>,
209 Ok(decoder
.tcx().mk_region(Decodable
::decode(decoder
)?
))
213 pub fn decode_ty_slice
<'a
, 'tcx
, D
>(decoder
: &mut D
)
214 -> Result
<&'tcx ty
::Slice
<Ty
<'tcx
>>, D
::Error
>
215 where D
: TyDecoder
<'a
, 'tcx
>,
218 let len
= decoder
.read_usize()?
;
219 Ok(decoder
.tcx().mk_type_list((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
223 pub fn decode_adt_def
<'a
, 'tcx
, D
>(decoder
: &mut D
)
224 -> Result
<&'tcx ty
::AdtDef
, D
::Error
>
225 where D
: TyDecoder
<'a
, 'tcx
>,
228 let def_id
= DefId
::decode(decoder
)?
;
229 Ok(decoder
.tcx().adt_def(def_id
))
233 pub fn decode_existential_predicate_slice
<'a
, 'tcx
, D
>(decoder
: &mut D
)
234 -> Result
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>, D
::Error
>
235 where D
: TyDecoder
<'a
, 'tcx
>,
238 let len
= decoder
.read_usize()?
;
240 .mk_existential_predicates((0..len
).map(|_
| Decodable
::decode(decoder
)))?
)
244 pub fn decode_byte_array
<'a
, 'tcx
, D
>(decoder
: &mut D
)
245 -> Result
<ByteArray
<'tcx
>, D
::Error
>
246 where D
: TyDecoder
<'a
, 'tcx
>,
250 data
: decoder
.tcx().alloc_byte_array(&Vec
::decode(decoder
)?
)
255 pub fn decode_const
<'a
, 'tcx
, D
>(decoder
: &mut D
)
256 -> Result
<&'tcx ty
::Const
<'tcx
>, D
::Error
>
257 where D
: TyDecoder
<'a
, 'tcx
>,
260 Ok(decoder
.tcx().mk_const(Decodable
::decode(decoder
)?
))
264 macro_rules
! __impl_decoder_methods
{
265 ($
($name
:ident
-> $ty
:ty
;)*) => {
266 $
(fn $
name(&mut self) -> Result
<$ty
, Self::Error
> {
273 macro_rules
! implement_ty_decoder
{
274 ($DecoderName
:ident
<$
($typaram
:tt
),*>) => {
275 mod __ty_decoder_impl
{
276 use super::$DecoderName
;
278 use $
crate::ty
::codec
::*;
279 use $
crate::ty
::subst
::Substs
;
280 use $
crate::hir
::def_id
::{CrateNum}
;
281 use $
crate::middle
::const_val
::ByteArray
;
282 use rustc_serialize
::{Decoder, SpecializedDecoder}
;
283 use std
::borrow
::Cow
;
285 impl<$
($typaram
),*> Decoder
for $DecoderName
<$
($typaram
),*> {
288 __impl_decoder_methods
! {
309 read_str
-> Cow
<str>;
312 fn error(&mut self, err
: &str) -> Self::Error
{
313 self.opaque
.error(err
)
317 // FIXME(#36588) These impls are horribly unsound as they allow
318 // the caller to pick any lifetime for 'tcx, including 'static,
319 // by using the unspecialized proxies to them.
321 impl<$
($typaram
),*> SpecializedDecoder
<CrateNum
>
322 for $DecoderName
<$
($typaram
),*> {
323 fn specialized_decode(&mut self) -> Result
<CrateNum
, Self::Error
> {
328 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Ty
<'tcx
>>
329 for $DecoderName
<$
($typaram
),*> {
330 fn specialized_decode(&mut self) -> Result
<ty
::Ty
<'tcx
>, Self::Error
> {
335 impl<$
($typaram
),*> SpecializedDecoder
<ty
::GenericPredicates
<'tcx
>>
336 for $DecoderName
<$
($typaram
),*> {
337 fn specialized_decode(&mut self)
338 -> Result
<ty
::GenericPredicates
<'tcx
>, Self::Error
> {
339 decode_predicates(self)
343 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx Substs
<'tcx
>>
344 for $DecoderName
<$
($typaram
),*> {
345 fn specialized_decode(&mut self) -> Result
<&'tcx Substs
<'tcx
>, Self::Error
> {
350 impl<$
($typaram
),*> SpecializedDecoder
<ty
::Region
<'tcx
>>
351 for $DecoderName
<$
($typaram
),*> {
352 fn specialized_decode(&mut self) -> Result
<ty
::Region
<'tcx
>, Self::Error
> {
357 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::Slice
<ty
::Ty
<'tcx
>>>
358 for $DecoderName
<$
($typaram
),*> {
359 fn specialized_decode(&mut self)
360 -> Result
<&'tcx ty
::Slice
<ty
::Ty
<'tcx
>>, Self::Error
> {
361 decode_ty_slice(self)
365 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::AdtDef
>
366 for $DecoderName
<$
($typaram
),*> {
367 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::AdtDef
, Self::Error
> {
372 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>>
373 for $DecoderName
<$
($typaram
),*> {
374 fn specialized_decode(&mut self)
375 -> Result
<&'tcx ty
::Slice
<ty
::ExistentialPredicate
<'tcx
>>, Self::Error
> {
376 decode_existential_predicate_slice(self)
380 impl<$
($typaram
),*> SpecializedDecoder
<ByteArray
<'tcx
>>
381 for $DecoderName
<$
($typaram
),*> {
382 fn specialized_decode(&mut self) -> Result
<ByteArray
<'tcx
>, Self::Error
> {
383 decode_byte_array(self)
387 impl<$
($typaram
),*> SpecializedDecoder
<&'tcx $
crate::ty
::Const
<'tcx
>>
388 for $DecoderName
<$
($typaram
),*> {
389 fn specialized_decode(&mut self) -> Result
<&'tcx ty
::Const
<'tcx
>, Self::Error
> {