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, PointeeSized};
12
13use rustc_abi::FieldIdx;
14use rustc_data_structures::fx::FxHashMap;
15use rustc_hir::def_id::LocalDefId;
16use rustc_middle::ty::Const;
17use rustc_serialize::{Decodable, Encodable};
18use rustc_span::{Span, SpanDecoder, SpanEncoder, Spanned};
19
20use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
21use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
22use crate::mono::MonoItem;
23use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
24use crate::{mir, traits};
25
26/// The shorthand encoding uses an enum's variant index `usize`
27/// and is offset by this value so it never matches a real variant.
28/// This offset is also chosen so that the first byte is never < 0x80.
29pub const SHORTHAND_OFFSET: usize = 0x80;
30
31pub trait TyEncoder<'tcx>: SpanEncoder {
32    const CLEAR_CROSS_CRATE: bool;
33
34    fn position(&self) -> usize;
35
36    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
37
38    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
39
40    fn encode_alloc_id(&mut self, alloc_id: &AllocId);
41}
42
43pub trait TyDecoder<'tcx>:
44    SpanDecoder + rustc_type_ir::InternerDecoder<Interner = TyCtxt<'tcx>>
45{
46    const CLEAR_CROSS_CRATE: bool;
47
48    fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
49    where
50        F: FnOnce(&mut Self) -> Ty<'tcx>;
51
52    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
53    where
54        F: FnOnce(&mut Self) -> R;
55
56    fn positioned_at_shorthand(&self) -> bool {
57        (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
58    }
59
60    fn decode_alloc_id(&mut self) -> AllocId;
61}
62
63pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
64    type Variant: Encodable<E>;
65    fn variant(&self) -> &Self::Variant;
66}
67
68#[allow(rustc::usage_of_ty_tykind)]
69impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
70    type Variant = ty::TyKind<'tcx>;
71
72    #[inline]
73    fn variant(&self) -> &Self::Variant {
74        self.kind()
75    }
76}
77
78impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
79    type Variant = ty::PredicateKind<'tcx>;
80
81    #[inline]
82    fn variant(&self) -> &Self::Variant {
83        self
84    }
85}
86
87/// Trait for decoding to a reference.
88///
89/// This is a separate trait from `Decodable` so that we can implement it for
90/// upstream types, such as `FxHashSet`.
91///
92/// The `TyDecodable` derive macro will use this trait for fields that are
93/// references (and don't use a type alias to hide that).
94///
95/// `Decodable` can still be implemented in cases where `Decodable` is required
96/// by a trait bound.
97///
98/// Implementations of this trait will typically allocate into an arena or interner,
99/// e.g. see `impl_ref_decodable_into_arena!`.
100pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>>: PointeeSized {
101    fn decode(d: &mut D) -> &'tcx Self;
102}
103
104/// Encode the given value or a previously cached shorthand.
105pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
106where
107    E: TyEncoder<'tcx>,
108    M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
109    T: EncodableWithShorthand<'tcx, E>,
110    // The discriminant and shorthand must have the same size.
111    T::Variant: DiscriminantKind<Discriminant = isize>,
112{
113    let existing_shorthand = cache(encoder).get(value).copied();
114    if let Some(shorthand) = existing_shorthand {
115        encoder.emit_usize(shorthand);
116        return;
117    }
118
119    let variant = value.variant();
120
121    let start = encoder.position();
122    variant.encode(encoder);
123    let len = encoder.position() - start;
124
125    // The shorthand encoding uses the same usize as the
126    // discriminant, with an offset so they can't conflict.
127    let discriminant = intrinsics::discriminant_value(variant);
128    if !(SHORTHAND_OFFSET > discriminant as usize) {
    ::core::panicking::panic("assertion failed: SHORTHAND_OFFSET > discriminant as usize")
};assert!(SHORTHAND_OFFSET > discriminant as usize);
129
130    let shorthand = start + SHORTHAND_OFFSET;
131
132    // Get the number of bits that leb128 could fit
133    // in the same space as the fully encoded type.
134    let leb128_bits = len * 7;
135
136    // Check that the shorthand is a not longer than the
137    // full encoding itself, i.e., it's an obvious win.
138    if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
139        cache(encoder).insert(*value, shorthand);
140    }
141}
142
143impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
144    fn encode(&self, e: &mut E) {
145        encode_with_shorthand(e, self, TyEncoder::type_shorthands);
146    }
147}
148
149impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
150    fn encode(&self, e: &mut E) {
151        let kind = self.kind();
152        kind.bound_vars().encode(e);
153        encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
154    }
155}
156
157impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Clause<'tcx> {
158    fn encode(&self, e: &mut E) {
159        self.as_predicate().encode(e);
160    }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'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 ty::Pattern<'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 ty::ValTree<'tcx> {
176    fn encode(&self, e: &mut E) {
177        self.0.0.encode(e);
178    }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
182    fn encode(&self, e: &mut E) {
183        self.inner().encode(e)
184    }
185}
186
187impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
188    fn encode(&self, e: &mut E) {
189        self.0.0.encode(e)
190    }
191}
192
193impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
194    fn encode(&self, e: &mut E) {
195        e.encode_alloc_id(self)
196    }
197}
198
199impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
200    fn encode(&self, e: &mut E) {
201        self.into_parts().encode(e);
202    }
203}
204
205impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
206    fn encode(&self, e: &mut E) {
207        self.caller_bounds().encode(e);
208    }
209}
210
211impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
212    #[allow(rustc::usage_of_ty_tykind)]
213    fn decode(decoder: &mut D) -> Ty<'tcx> {
214        // Handle shorthands first, if we have a usize > 0x80.
215        if decoder.positioned_at_shorthand() {
216            let pos = decoder.read_usize();
217            if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
218            let shorthand = pos - SHORTHAND_OFFSET;
219
220            decoder.cached_ty_for_shorthand(shorthand, |decoder| {
221                decoder.with_position(shorthand, Ty::decode)
222            })
223        } else {
224            let tcx = decoder.interner();
225            tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
226        }
227    }
228}
229
230impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
231    fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
232        let bound_vars = Decodable::decode(decoder);
233        // Handle shorthands first, if we have a usize > 0x80.
234        let predicate_kind = ty::Binder::bind_with_vars(
235            if decoder.positioned_at_shorthand() {
236                let pos = decoder.read_usize();
237                if !(pos >= SHORTHAND_OFFSET) {
    ::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
238                let shorthand = pos - SHORTHAND_OFFSET;
239
240                decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
241            } else {
242                <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
243            },
244            bound_vars,
245        );
246        decoder.interner().mk_predicate(predicate_kind)
247    }
248}
249
250impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
251    fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
252        let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
253        pred.expect_clause()
254    }
255}
256
257impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
258    fn decode(decoder: &mut D) -> Self {
259        let len = decoder.read_usize();
260        let tcx = decoder.interner();
261        tcx.mk_args_from_iter(
262            (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
263        )
264    }
265}
266
267impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
268    fn decode(decoder: &mut D) -> Self {
269        let local: mir::Local = Decodable::decode(decoder);
270        let len = decoder.read_usize();
271        let projection = decoder.interner().mk_place_elems_from_iter(
272            (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
273        );
274        mir::Place { local, projection }
275    }
276}
277
278impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
279    fn decode(decoder: &mut D) -> Self {
280        let len = decoder.read_usize();
281        decoder.interner().mk_canonical_var_infos_from_iter(
282            (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
283        )
284    }
285}
286
287impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
288    fn decode(decoder: &mut D) -> Self {
289        decoder.decode_alloc_id()
290    }
291}
292
293impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
294    fn decode(decoder: &mut D) -> Self {
295        let parts = Decodable::decode(decoder);
296        CtfeProvenance::from_parts(parts)
297    }
298}
299
300impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
301    fn decode(decoder: &mut D) -> Self {
302        ty::SymbolName::new(decoder.interner(), decoder.read_str())
303    }
304}
305
306impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
307    fn decode(d: &mut D) -> Self {
308        let caller_bounds = Decodable::decode(d);
309        ty::ParamEnv::new(caller_bounds)
310    }
311}
312
313macro_rules! impl_decodable_via_ref {
314    ($($t:ty,)+) => {
315        $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t {
316            fn decode(decoder: &mut D) -> Self {
317                RefDecodable::decode(decoder)
318            }
319        })*
320    }
321}
322
323impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
324    fn decode(decoder: &mut D) -> &'tcx Self {
325        let len = decoder.read_usize();
326        decoder
327            .interner()
328            .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
329    }
330}
331
332impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
333    for ty::List<ty::PolyExistentialPredicate<'tcx>>
334{
335    fn decode(decoder: &mut D) -> &'tcx Self {
336        let len = decoder.read_usize();
337        decoder.interner().mk_poly_existential_predicates_from_iter(
338            (0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)),
339        )
340    }
341}
342
343impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> {
344    fn decode(decoder: &mut D) -> Self {
345        let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
346        decoder.interner().mk_ct_from_kind(kind)
347    }
348}
349
350impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
351    fn decode(decoder: &mut D) -> Self {
352        decoder.interner().mk_pat(Decodable::decode(decoder))
353    }
354}
355
356impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
357    fn decode(decoder: &mut D) -> Self {
358        decoder.interner().intern_valtree(Decodable::decode(decoder))
359    }
360}
361
362impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
363    fn decode(decoder: &mut D) -> Self {
364        decoder.interner().mk_const_alloc(Decodable::decode(decoder))
365    }
366}
367
368impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
369    fn decode(decoder: &mut D) -> Self {
370        decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
371    }
372}
373
374impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
375    fn decode(decoder: &mut D) -> &'tcx Self {
376        decoder
377            .interner()
378            .arena
379            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
380    }
381}
382
383impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::PolyTraitRef<'tcx>, Span)] {
384    fn decode(decoder: &mut D) -> &'tcx Self {
385        decoder
386            .interner()
387            .arena
388            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
389    }
390}
391
392impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] {
393    fn decode(decoder: &mut D) -> &'tcx Self {
394        decoder
395            .interner()
396            .arena
397            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
398    }
399}
400
401impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind<'tcx>> {
402    fn decode(decoder: &mut D) -> &'tcx Self {
403        let len = decoder.read_usize();
404        decoder.interner().mk_bound_variable_kinds_from_iter(
405            (0..len).map::<ty::BoundVariableKind<'tcx>, _>(|_| Decodable::decode(decoder)),
406        )
407    }
408}
409
410impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Pattern<'tcx>> {
411    fn decode(decoder: &mut D) -> &'tcx Self {
412        let len = decoder.read_usize();
413        decoder.interner().mk_patterns_from_iter(
414            (0..len).map::<ty::Pattern<'tcx>, _>(|_| Decodable::decode(decoder)),
415        )
416    }
417}
418
419impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> {
420    fn decode(decoder: &mut D) -> &'tcx Self {
421        let len = decoder.read_usize();
422        decoder.interner().mk_const_list_from_iter(
423            (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)),
424        )
425    }
426}
427
428impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
429    for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>
430{
431    fn decode(decoder: &mut D) -> &'tcx Self {
432        let len = decoder.read_usize();
433        decoder.interner().mk_clauses_from_iter(
434            (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
435        )
436    }
437}
438
439impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<FieldIdx> {
440    fn decode(decoder: &mut D) -> &'tcx Self {
441        let len = decoder.read_usize();
442        decoder
443            .interner()
444            .mk_fields_from_iter((0..len).map::<FieldIdx, _>(|_| Decodable::decode(decoder)))
445    }
446}
447
448impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<LocalDefId> {
449    fn decode(decoder: &mut D) -> &'tcx Self {
450        let len = decoder.read_usize();
451        decoder.interner().mk_local_def_ids_from_iter(
452            (0..len).map::<LocalDefId, _>(|_| Decodable::decode(decoder)),
453        )
454    }
455}
456
457impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<LocalDefId> {
458    fn decode(d: &mut D) -> Self {
459        RefDecodable::decode(d)
460    }
461}
462
463impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<Const<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}impl_decodable_via_ref! {
464    &'tcx ty::TypeckResults<'tcx>,
465    &'tcx ty::List<Ty<'tcx>>,
466    &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
467    &'tcx traits::ImplSource<'tcx, ()>,
468    &'tcx mir::Body<'tcx>,
469    &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
470    &'tcx ty::List<ty::Pattern<'tcx>>,
471    &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
472    &'tcx ty::List<Const<'tcx>>,
473}
474
475#[macro_export]
476macro_rules! __impl_decoder_methods {
477    ($($name:ident -> $ty:ty;)*) => {
478        $(
479            #[inline]
480            fn $name(&mut self) -> $ty {
481                self.opaque.$name()
482            }
483        )*
484    }
485}
486
487#[macro_export]
488macro_rules! implement_ty_decoder {
489    ($DecoderName:ident <$($typaram:tt),*>) => {
490        mod __ty_decoder_impl {
491            use rustc_serialize::Decoder;
492
493            use super::$DecoderName;
494
495            impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
496                $crate::__impl_decoder_methods! {
497                    read_usize -> usize;
498                    read_u128 -> u128;
499                    read_u64 -> u64;
500                    read_u32 -> u32;
501                    read_u16 -> u16;
502                    read_u8 -> u8;
503
504                    read_isize -> isize;
505                    read_i128 -> i128;
506                    read_i64 -> i64;
507                    read_i32 -> i32;
508                    read_i16 -> i16;
509                }
510
511                #[inline]
512                fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
513                    self.opaque.read_raw_bytes(len)
514                }
515
516                #[inline]
517                fn peek_byte(&self) -> u8 {
518                    self.opaque.peek_byte()
519                }
520
521                #[inline]
522                fn position(&self) -> usize {
523                    self.opaque.position()
524                }
525            }
526        }
527    }
528}