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::TyKind<'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, span) in &predicates.predicates {
113 encode_with_shorthand(encoder, predicate, &cache)?;
114 span.encode(encoder)?;
119 pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
121 fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
123 fn peek_byte(&self) -> u8;
125 fn position(&self) -> usize;
127 fn cached_ty_for_shorthand<F>(&mut self,
130 -> Result<Ty<'tcx>, Self::Error>
131 where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
133 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
134 where F: FnOnce(&mut Self) -> R;
136 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
138 fn positioned_at_shorthand(&self) -> bool {
139 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
144 pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
145 where D: TyDecoder<'a, 'tcx>,
148 let cnum = CrateNum::from_u32(u32::decode(decoder)?);
149 Ok(decoder.map_encoded_cnum_to_current(cnum))
153 pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
154 where D: TyDecoder<'a, 'tcx>,
157 // Handle shorthands first, if we have an usize > 0x80.
158 if decoder.positioned_at_shorthand() {
159 let pos = decoder.read_usize()?;
160 assert!(pos >= SHORTHAND_OFFSET);
161 let shorthand = pos - SHORTHAND_OFFSET;
163 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
164 decoder.with_position(shorthand, Ty::decode)
167 let tcx = decoder.tcx();
168 Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
173 pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
174 -> Result<ty::GenericPredicates<'tcx>, D::Error>
175 where D: TyDecoder<'a, 'tcx>,
178 Ok(ty::GenericPredicates {
179 parent: Decodable::decode(decoder)?,
180 predicates: (0..decoder.read_usize()?).map(|_| {
181 // Handle shorthands first, if we have an usize > 0x80.
182 let predicate = if decoder.positioned_at_shorthand() {
183 let pos = decoder.read_usize()?;
184 assert!(pos >= SHORTHAND_OFFSET);
185 let shorthand = pos - SHORTHAND_OFFSET;
187 decoder.with_position(shorthand, ty::Predicate::decode)
189 ty::Predicate::decode(decoder)
191 Ok((predicate, Decodable::decode(decoder)?))
193 .collect::<Result<Vec<_>, _>>()?,
198 pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
199 where D: TyDecoder<'a, 'tcx>,
202 let len = decoder.read_usize()?;
203 let tcx = decoder.tcx();
204 Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
208 pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
209 where D: TyDecoder<'a, 'tcx>,
212 Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
216 pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
217 -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
218 where D: TyDecoder<'a, 'tcx>,
221 let len = decoder.read_usize()?;
222 Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
226 pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
227 -> Result<&'tcx ty::AdtDef, D::Error>
228 where D: TyDecoder<'a, 'tcx>,
231 let def_id = DefId::decode(decoder)?;
232 Ok(decoder.tcx().adt_def(def_id))
236 pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
237 -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
238 where D: TyDecoder<'a, 'tcx>,
241 let len = decoder.read_usize()?;
243 .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
247 pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
248 -> Result<CanonicalVarInfos<'tcx>, D::Error>
249 where D: TyDecoder<'a, 'tcx>,
252 let len = decoder.read_usize()?;
253 let interned: Result<Vec<CanonicalVarInfo>, _> = (0..len).map(|_| Decodable::decode(decoder))
256 .intern_canonical_var_infos(interned?.as_slice()))
260 pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
261 -> Result<&'tcx ty::Const<'tcx>, D::Error>
262 where D: TyDecoder<'a, 'tcx>,
265 Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
269 pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
270 -> Result<&'tcx Allocation, D::Error>
271 where D: TyDecoder<'a, 'tcx>,
274 Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
278 macro_rules! __impl_decoder_methods {
279 ($($name:ident -> $ty:ty;)*) => {
280 $(fn $name(&mut self) -> Result<$ty, Self::Error> {
287 macro_rules! implement_ty_decoder {
288 ($DecoderName:ident <$($typaram:tt),*>) => {
289 mod __ty_decoder_impl {
290 use super::$DecoderName;
291 use $crate::infer::canonical::CanonicalVarInfos;
293 use $crate::ty::codec::*;
294 use $crate::ty::subst::Substs;
295 use $crate::hir::def_id::{CrateNum};
296 use rustc_serialize::{Decoder, SpecializedDecoder};
297 use std::borrow::Cow;
299 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
302 __impl_decoder_methods! {
323 read_str -> Cow<'_, str>;
326 fn error(&mut self, err: &str) -> Self::Error {
327 self.opaque.error(err)
331 // FIXME(#36588) These impls are horribly unsound as they allow
332 // the caller to pick any lifetime for 'tcx, including 'static,
333 // by using the unspecialized proxies to them.
335 impl<$($typaram),*> SpecializedDecoder<CrateNum>
336 for $DecoderName<$($typaram),*> {
337 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
342 impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
343 for $DecoderName<$($typaram),*> {
344 fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
349 impl<$($typaram),*> SpecializedDecoder<ty::GenericPredicates<'tcx>>
350 for $DecoderName<$($typaram),*> {
351 fn specialized_decode(&mut self)
352 -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
353 decode_predicates(self)
357 impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>>
358 for $DecoderName<$($typaram),*> {
359 fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
364 impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
365 for $DecoderName<$($typaram),*> {
366 fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
371 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
372 for $DecoderName<$($typaram),*> {
373 fn specialized_decode(&mut self)
374 -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
375 decode_ty_slice(self)
379 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
380 for $DecoderName<$($typaram),*> {
381 fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
386 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
387 for $DecoderName<$($typaram),*> {
388 fn specialized_decode(&mut self)
389 -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
390 decode_existential_predicate_slice(self)
394 impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
395 for $DecoderName<$($typaram),*> {
396 fn specialized_decode(&mut self)
397 -> Result<CanonicalVarInfos<'tcx>, Self::Error> {
398 decode_canonical_var_infos(self)
402 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
403 for $DecoderName<$($typaram),*> {
404 fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
409 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
410 for $DecoderName<$($typaram),*> {
411 fn specialized_decode(
413 ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
414 decode_allocation(self)