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::Pattern<'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::ValTree<'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 ConstAllocation<'tcx> {
158    fn encode(&self, e: &mut E) {
159        self.inner().encode(e)
160    }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
164    fn encode(&self, e: &mut E) {
165        self.0.0.encode(e)
166    }
167}
168
169impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
170    fn encode(&self, e: &mut E) {
171        e.encode_alloc_id(self)
172    }
173}
174
175impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
176    fn encode(&self, e: &mut E) {
177        self.into_parts().encode(e);
178    }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
182    fn encode(&self, e: &mut E) {
183        self.caller_bounds.encode(e);
184    }
185}
186
187impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
188    #[allow(rustc::usage_of_ty_tykind)]
189    fn decode(decoder: &mut D) -> Ty<'tcx> {
190        // Handle shorthands first, if we have a usize > 0x80.
191        if decoder.positioned_at_shorthand() {
192            let pos = decoder.read_usize();
193            if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
194            let shorthand = pos - SHORTHAND_OFFSET;
195
196            decoder.cached_ty_for_shorthand(shorthand, |decoder| {
197                decoder.with_position(shorthand, Ty::decode)
198            })
199        } else {
200            let tcx = decoder.interner();
201            tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
202        }
203    }
204}
205
206impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
207    fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
208        let bound_vars = Decodable::decode(decoder);
209        // Handle shorthands first, if we have a usize > 0x80.
210        let predicate_kind = ty::Binder::bind_with_vars(
211            if decoder.positioned_at_shorthand() {
212                let pos = decoder.read_usize();
213                if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
214                let shorthand = pos - SHORTHAND_OFFSET;
215
216                decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
217            } else {
218                <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
219            },
220            bound_vars,
221        );
222        decoder.interner().mk_predicate(predicate_kind)
223    }
224}
225
226impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
227    fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
228        let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
229        pred.expect_clause()
230    }
231}
232
233impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
234    fn decode(decoder: &mut D) -> Self {
235        let len = decoder.read_usize();
236        let tcx = decoder.interner();
237        tcx.mk_args_from_iter(
238            (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
239        )
240    }
241}
242
243impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
244    fn decode(decoder: &mut D) -> Self {
245        let local: mir::Local = Decodable::decode(decoder);
246        let len = decoder.read_usize();
247        let projection = decoder.interner().mk_place_elems_from_iter(
248            (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
249        );
250        mir::Place { local, projection }
251    }
252}
253
254impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
255    fn decode(decoder: &mut D) -> Self {
256        let len = decoder.read_usize();
257        decoder.interner().mk_canonical_var_infos_from_iter(
258            (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
259        )
260    }
261}
262
263impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
264    fn decode(decoder: &mut D) -> Self {
265        decoder.decode_alloc_id()
266    }
267}
268
269impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
270    fn decode(decoder: &mut D) -> Self {
271        let parts = Decodable::decode(decoder);
272        CtfeProvenance::from_parts(parts)
273    }
274}
275
276impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
277    fn decode(decoder: &mut D) -> Self {
278        ty::SymbolName::new(decoder.interner(), decoder.read_str())
279    }
280}
281
282impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
283    fn decode(d: &mut D) -> Self {
284        let caller_bounds = Decodable::decode(d);
285        ty::ParamEnv { caller_bounds }
286    }
287}
288
289impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
290    fn decode(decoder: &mut D) -> Self {
291        decoder.interner().mk_pat(Decodable::decode(decoder))
292    }
293}
294
295impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
296    fn decode(decoder: &mut D) -> Self {
297        decoder.interner().intern_valtree(Decodable::decode(decoder))
298    }
299}
300
301impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
302    fn decode(decoder: &mut D) -> Self {
303        decoder.interner().mk_const_alloc(Decodable::decode(decoder))
304    }
305}
306
307impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
308    fn decode(decoder: &mut D) -> Self {
309        decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
310    }
311}
312
313/// Declares implementations of all [`Decoder`](rustc_serialize::Decoder) methods,
314/// each of which forwards to a method of the same name on some underlying decoder,
315/// typically a field of type [`MemDecoder`](rustc_serialize::opaque::MemDecoder).
316///
317/// Call this macro within an impl block `impl Decoder for $MyDecoder { ... }`.
318pub macro forward_all_decoder_methods_to {
319    (
320        // Make the caller provide an explicit `self` (using closure syntax),
321        // so that `$inner:expr` can refer to `self` without violating hygiene.
322        //
323        // This isn't an actual closure, because it needs to work for both
324        // `&self` and `&mut self` methods.
325        |$self:ident| $inner:expr
326    ) => {
327        #[inline] fn read_usize(&mut $self) -> usize { $inner.read_usize() }
328        #[inline] fn read_u128 (&mut $self) -> u128  { $inner.read_u128()  }
329        #[inline] fn read_u64  (&mut $self) -> u64   { $inner.read_u64()   }
330        #[inline] fn read_u32  (&mut $self) -> u32   { $inner.read_u32()   }
331        #[inline] fn read_u16  (&mut $self) -> u16   { $inner.read_u16()   }
332        #[inline] fn read_u8   (&mut $self) -> u8    { $inner.read_u8()    }
333        #[inline] fn read_isize(&mut $self) -> isize { $inner.read_isize() }
334        #[inline] fn read_i128 (&mut $self) -> i128  { $inner.read_i128()  }
335        #[inline] fn read_i64  (&mut $self) -> i64   { $inner.read_i64()   }
336        #[inline] fn read_i32  (&mut $self) -> i32   { $inner.read_i32()   }
337        #[inline] fn read_i16  (&mut $self) -> i16   { $inner.read_i16()   }
338
339        #[inline]
340        fn read_raw_bytes(&mut $self, len: usize) -> &[u8] {
341            $inner.read_raw_bytes(len)
342        }
343
344        #[inline]
345        fn peek_byte(&$self) -> u8 {
346            $inner.peek_byte()
347        }
348
349        #[inline]
350        fn position(&$self) -> usize {
351            $inner.position()
352        }
353    }
354}