Skip to main content

rustc_middle/ty/codec/
ref_decodable.rs

1use std::marker::PointeeSized;
2
3use rustc_serialize::Decodable;
4
5use crate::ty::codec::TyDecoder;
6use crate::ty::{self, Ty};
7use crate::{mir, traits};
8
9/// Trait for decoding to a reference.
10///
11/// This is a separate trait from [`Decodable`] so that we can easily implement it for
12/// upstream types, such as `FxHashSet`.
13///
14/// The [`TyDecodable`](rustc_macros::TyDecodable) derive macro will use this
15/// trait for fields that are references (and don't use a type alias to hide that).
16///
17/// [`Decodable`] can still be implemented in cases where `Decodable` is required
18/// by a trait bound; see `impl_decodable_via_ref_decodable_for_local_types!` for examples.
19///
20/// Implementations of this trait will typically allocate into an arena or interner,
21/// e.g. see `impl_ref_decodable_into_arena!` in [`rustc_middle::arena`].
22#[diagnostic::on_unimplemented(
23    note = "consider adding `{Self}` to the list in `impl_ref_decodable_into_arena!`"
24)]
25pub trait RefDecodable<'tcx>: PointeeSized {
26    fn decode(d: &mut impl TyDecoder<'tcx>) -> &'tcx Self;
27}
28
29impl<'tcx> RefDecodable<'tcx> for ty::List<Ty<'tcx>> {
30    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
31        let len = decoder.read_usize();
32        decoder
33            .interner()
34            .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
35    }
36}
37
38impl<'tcx> RefDecodable<'tcx> for ty::List<ty::PolyExistentialPredicate<'tcx>> {
39    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
40        let len = decoder.read_usize();
41        decoder.interner().mk_poly_existential_predicates_from_iter(
42            (0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)),
43        )
44    }
45}
46
47impl<'tcx> RefDecodable<'tcx> for ty::List<ty::BoundVariableKind<'tcx>> {
48    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
49        let len = decoder.read_usize();
50        decoder.interner().mk_bound_variable_kinds_from_iter(
51            (0..len).map::<ty::BoundVariableKind<'tcx>, _>(|_| Decodable::decode(decoder)),
52        )
53    }
54}
55
56impl<'tcx> RefDecodable<'tcx> for ty::List<ty::Pattern<'tcx>> {
57    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
58        let len = decoder.read_usize();
59        decoder.interner().mk_patterns_from_iter(
60            (0..len).map::<ty::Pattern<'tcx>, _>(|_| Decodable::decode(decoder)),
61        )
62    }
63}
64
65impl<'tcx> RefDecodable<'tcx> for ty::List<ty::Const<'tcx>> {
66    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
67        let len = decoder.read_usize();
68        decoder.interner().mk_const_list_from_iter(
69            (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)),
70        )
71    }
72}
73
74impl<'tcx> RefDecodable<'tcx> for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>> {
75    fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self {
76        let len = decoder.read_usize();
77        decoder.interner().mk_clauses_from_iter(
78            (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
79        )
80    }
81}
82
83/// Implements [`Decodable`] for `&'tcx T`, where [`T: RefDecodable`](RefDecodable)
84/// and T is defined in this crate (`rustc_middle`).
85///
86/// For locally-defined types, we can use a blanket impl over any [`D: TyDecoder`](TyDecoder).
87///
88/// ## Note on implementing [`Decodable`] for references to non-local types
89///
90/// For references to types not defined in this crate, including slices/tuples/collections
91/// of local types, [`Decodable`] cannot use a blanket impl and must be implemented for
92/// specific decoders instead.
93///
94/// See invocations of `impl_decodable_via_ref_decodable_for_foreign_types!` for examples.
95macro_rules! impl_decodable_via_ref_decodable_for_local_types {
96    (
97        $(
98            &'tcx $T:ty,
99        )*
100    ) => {
101        $(
102            impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx $T {
103                fn decode(decoder: &mut D) -> Self {
104                    RefDecodable::decode(decoder)
105                }
106            }
107        )*
108    }
109}
110
111impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx mir::Body<'tcx> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx traits::ImplSource<'tcx, ()> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx traits::specialization_graph::Graph {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<Ty<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx ty::List<ty::BoundVariableKind<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx ty::List<ty::Const<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx ty::List<ty::Pattern<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for
    &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>> {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::TypeckResults<'tcx>
    {
    fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}impl_decodable_via_ref_decodable_for_local_types! {
112    // tidy-alphabetical-start
113    &'tcx mir::Body<'tcx>,
114    &'tcx traits::ImplSource<'tcx, ()>,
115    &'tcx traits::specialization_graph::Graph,
116    &'tcx ty::List<Ty<'tcx>>,
117    &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
118    &'tcx ty::List<ty::Const<'tcx>>,
119    &'tcx ty::List<ty::Pattern<'tcx>>,
120    &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
121    &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
122    &'tcx ty::TypeckResults<'tcx>,
123    // tidy-alphabetical-end
124}