Skip to main content

rustc_middle/ty/
codec.rs

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.
5//!
6//! The functionality in here is shared between persisting to crate metadata and
7//! persisting to incr. comp. caches.
8
9use std::hash::Hash;
10use std::intrinsics;
11use std::marker::DiscriminantKind;
12
13use rustc_data_structures::fx::FxHashMap;
14use rustc_serialize::{Decodable, Encodable};
15use rustc_span::{SpanDecoder, SpanEncoder};
16
17pub use self::ref_decodable::RefDecodable;
18use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
19use crate::mir;
20use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
21use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
22
23mod ref_decodable;
24
25/// The shorthand encoding uses an enum's variant index `usize`
26/// and is offset by this value so it never matches a real variant.
27/// This offset is also chosen so that the first byte is never < 0x80.
28pub const SHORTHAND_OFFSET: usize = 0x80;
29
30pub trait TyEncoder<'tcx>: SpanEncoder {
31    const CLEAR_CROSS_CRATE: bool;
32
33    fn position(&self) -> usize;
34
35    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
36
37    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
38
39    fn encode_alloc_id(&mut self, alloc_id: &AllocId);
40}
41
42pub trait TyDecoder<'tcx>:
43    SpanDecoder + rustc_type_ir::InternerDecoder<Interner = TyCtxt<'tcx>>
44{
45    const CLEAR_CROSS_CRATE: bool;
46
47    fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
48    where
49        F: FnOnce(&mut Self) -> Ty<'tcx>;
50
51    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
52    where
53        F: FnOnce(&mut Self) -> R;
54
55    fn positioned_at_shorthand(&self) -> bool {
56        (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
57    }
58
59    fn decode_alloc_id(&mut self) -> AllocId;
60}
61
62pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
63    type Variant: Encodable<E>;
64    fn variant(&self) -> &Self::Variant;
65}
66
67#[allow(rustc::usage_of_ty_tykind)]
68impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
69    type Variant = ty::TyKind<'tcx>;
70
71    #[inline]
72    fn variant(&self) -> &Self::Variant {
73        self.kind()
74    }
75}
76
77impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
78    type Variant = ty::PredicateKind<'tcx>;
79
80    #[inline]
81    fn variant(&self) -> &Self::Variant {
82        self
83    }
84}
85
86/// Encode the given value or a previously cached shorthand.
87pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
88where
89    E: TyEncoder<'tcx>,
90    M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
91    T: EncodableWithShorthand<'tcx, E>,
92    // The discriminant and shorthand must have the same size.
93    T::Variant: DiscriminantKind<Discriminant = isize>,
94{
95    let existing_shorthand = cache(encoder).get(value).copied();
96    if let Some(shorthand) = existing_shorthand {
97        encoder.emit_usize(shorthand);
98        return;
99    }
100
101    let variant = value.variant();
102
103    let start = encoder.position();
104    variant.encode(encoder);
105    let len = encoder.position() - start;
106
107    // The shorthand encoding uses the same usize as the
108    // discriminant, with an offset so they can't conflict.
109    let discriminant = intrinsics::discriminant_value(variant);
110    if !(SHORTHAND_OFFSET > discriminant as usize) {
    ::core::panicking::panic("assertion failed: SHORTHAND_OFFSET > discriminant as usize")
};assert!(SHORTHAND_OFFSET > discriminant as usize);
111
112    let shorthand = start + SHORTHAND_OFFSET;
113
114    // Get the number of bits that leb128 could fit
115    // in the same space as the fully encoded type.
116    let leb128_bits = len * 7;
117
118    // Check that the shorthand is a not longer than the
119    // full encoding itself, i.e., it's an obvious win.
120    if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
121        cache(encoder).insert(*value, shorthand);
122    }
123}
124
125impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
126    fn encode(&self, e: &mut E) {
127        encode_with_shorthand(e, self, TyEncoder::type_shorthands);
128    }
129}
130
131impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
132    fn encode(&self, e: &mut E) {
133        let kind = self.kind();
134        kind.bound_vars().encode(e);
135        encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
136    }
137}
138
139impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Clause<'tcx> {
140    fn encode(&self, e: &mut E) {
141        self.as_predicate().encode(e);
142    }
143}
144
145impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'tcx> {
146    fn encode(&self, e: &mut E) {
147        self.0.0.encode(e);
148    }
149}
150
151impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Pattern<'tcx> {
152    fn encode(&self, e: &mut E) {
153        self.0.0.encode(e);
154    }
155}
156
157impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ValTree<'tcx> {
158    fn encode(&self, e: &mut E) {
159        self.0.0.encode(e);
160    }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
164    fn encode(&self, e: &mut E) {
165        self.inner().encode(e)
166    }
167}
168
169impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
170    fn encode(&self, e: &mut E) {
171        self.0.0.encode(e)
172    }
173}
174
175impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
176    fn encode(&self, e: &mut E) {
177        e.encode_alloc_id(self)
178    }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
182    fn encode(&self, e: &mut E) {
183        self.into_parts().encode(e);
184    }
185}
186
187impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
188    fn encode(&self, e: &mut E) {
189        self.caller_bounds.encode(e);
190    }
191}
192
193impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
194    #[allow(rustc::usage_of_ty_tykind)]
195    fn decode(decoder: &mut D) -> Ty<'tcx> {
196        // Handle shorthands first, if we have a usize > 0x80.
197        if decoder.positioned_at_shorthand() {
198            let pos = decoder.read_usize();
199            if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
200            let shorthand = pos - SHORTHAND_OFFSET;
201
202            decoder.cached_ty_for_shorthand(shorthand, |decoder| {
203                decoder.with_position(shorthand, Ty::decode)
204            })
205        } else {
206            let tcx = decoder.interner();
207            tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
208        }
209    }
210}
211
212impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
213    fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
214        let bound_vars = Decodable::decode(decoder);
215        // Handle shorthands first, if we have a usize > 0x80.
216        let predicate_kind = ty::Binder::bind_with_vars(
217            if decoder.positioned_at_shorthand() {
218                let pos = decoder.read_usize();
219                if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
220                let shorthand = pos - SHORTHAND_OFFSET;
221
222                decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
223            } else {
224                <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
225            },
226            bound_vars,
227        );
228        decoder.interner().mk_predicate(predicate_kind)
229    }
230}
231
232impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
233    fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
234        let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
235        pred.expect_clause()
236    }
237}
238
239impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
240    fn decode(decoder: &mut D) -> Self {
241        let len = decoder.read_usize();
242        let tcx = decoder.interner();
243        tcx.mk_args_from_iter(
244            (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
245        )
246    }
247}
248
249impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
250    fn decode(decoder: &mut D) -> Self {
251        let local: mir::Local = Decodable::decode(decoder);
252        let len = decoder.read_usize();
253        let projection = decoder.interner().mk_place_elems_from_iter(
254            (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
255        );
256        mir::Place { local, projection }
257    }
258}
259
260impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
261    fn decode(decoder: &mut D) -> Self {
262        let len = decoder.read_usize();
263        decoder.interner().mk_canonical_var_infos_from_iter(
264            (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
265        )
266    }
267}
268
269impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
270    fn decode(decoder: &mut D) -> Self {
271        decoder.decode_alloc_id()
272    }
273}
274
275impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
276    fn decode(decoder: &mut D) -> Self {
277        let parts = Decodable::decode(decoder);
278        CtfeProvenance::from_parts(parts)
279    }
280}
281
282impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
283    fn decode(decoder: &mut D) -> Self {
284        ty::SymbolName::new(decoder.interner(), decoder.read_str())
285    }
286}
287
288impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
289    fn decode(d: &mut D) -> Self {
290        let caller_bounds = Decodable::decode(d);
291        ty::ParamEnv { caller_bounds }
292    }
293}
294
295impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> {
296    fn decode(decoder: &mut D) -> Self {
297        let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
298        decoder.interner().mk_ct_from_kind(kind)
299    }
300}
301
302impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
303    fn decode(decoder: &mut D) -> Self {
304        decoder.interner().mk_pat(Decodable::decode(decoder))
305    }
306}
307
308impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
309    fn decode(decoder: &mut D) -> Self {
310        decoder.interner().intern_valtree(Decodable::decode(decoder))
311    }
312}
313
314impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
315    fn decode(decoder: &mut D) -> Self {
316        decoder.interner().mk_const_alloc(Decodable::decode(decoder))
317    }
318}
319
320impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
321    fn decode(decoder: &mut D) -> Self {
322        decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
323    }
324}
325
326#[macro_export]
327macro_rules! __impl_decoder_methods {
328    ($($name:ident -> $ty:ty;)*) => {
329        $(
330            #[inline]
331            fn $name(&mut self) -> $ty {
332                self.opaque.$name()
333            }
334        )*
335    }
336}
337
338#[macro_export]
339macro_rules! implement_ty_decoder {
340    ($DecoderName:ident <$($typaram:tt),*>) => {
341        mod __ty_decoder_impl {
342            use rustc_serialize::Decoder;
343
344            use super::$DecoderName;
345
346            impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
347                $crate::__impl_decoder_methods! {
348                    read_usize -> usize;
349                    read_u128 -> u128;
350                    read_u64 -> u64;
351                    read_u32 -> u32;
352                    read_u16 -> u16;
353                    read_u8 -> u8;
354
355                    read_isize -> isize;
356                    read_i128 -> i128;
357                    read_i64 -> i64;
358                    read_i32 -> i32;
359                    read_i16 -> i16;
360                }
361
362                #[inline]
363                fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
364                    self.opaque.read_raw_bytes(len)
365                }
366
367                #[inline]
368                fn peek_byte(&self) -> u8 {
369                    self.opaque.peek_byte()
370                }
371
372                #[inline]
373                fn position(&self) -> usize {
374                    self.opaque.position()
375                }
376            }
377        }
378    }
379}