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