| use std::marker::PointeeSized; |
| |
| use rustc_serialize::Decodable; |
| |
| use crate::ty::codec::TyDecoder; |
| use crate::ty::{self, Ty}; |
| use crate::{mir, traits}; |
| |
| /// Trait for decoding to a reference. |
| /// |
| /// This is a separate trait from [`Decodable`] so that we can easily implement it for |
| /// upstream types, such as `FxHashSet`. |
| /// |
| /// The [`TyDecodable`](rustc_macros::TyDecodable) derive macro will use this |
| /// trait for fields that are references (and don't use a type alias to hide that). |
| /// |
| /// [`Decodable`] can still be implemented in cases where `Decodable` is required |
| /// by a trait bound; see `impl_decodable_via_ref_decodable_for_local_types!` for examples. |
| /// |
| /// Implementations of this trait will typically allocate into an arena or interner, |
| /// e.g. see `impl_ref_decodable_into_arena!` in [`rustc_middle::arena`]. |
| #[diagnostic::on_unimplemented( |
| note = "consider adding `{Self}` to the list in `impl_ref_decodable_into_arena!`" |
| )] |
| pub trait RefDecodable<'tcx>: PointeeSized { |
| fn decode(d: &mut impl TyDecoder<'tcx>) -> &'tcx Self; |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::List<Ty<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder |
| .interner() |
| .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder))) |
| } |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::List<ty::PolyExistentialPredicate<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder.interner().mk_poly_existential_predicates_from_iter( |
| (0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)), |
| ) |
| } |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::List<ty::BoundVariableKind<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder.interner().mk_bound_variable_kinds_from_iter( |
| (0..len).map::<ty::BoundVariableKind<'tcx>, _>(|_| Decodable::decode(decoder)), |
| ) |
| } |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::List<ty::Pattern<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder.interner().mk_patterns_from_iter( |
| (0..len).map::<ty::Pattern<'tcx>, _>(|_| Decodable::decode(decoder)), |
| ) |
| } |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::List<ty::Const<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder.interner().mk_const_list_from_iter( |
| (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)), |
| ) |
| } |
| } |
| |
| impl<'tcx> RefDecodable<'tcx> for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>> { |
| fn decode(decoder: &mut impl TyDecoder<'tcx>) -> &'tcx Self { |
| let len = decoder.read_usize(); |
| decoder.interner().mk_clauses_from_iter( |
| (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)), |
| ) |
| } |
| } |
| |
| /// Implements [`Decodable`] for `&'tcx T`, where [`T: RefDecodable`](RefDecodable) |
| /// and T is defined in this crate (`rustc_middle`). |
| /// |
| /// For locally-defined types, we can use a blanket impl over any [`D: TyDecoder`](TyDecoder). |
| /// |
| /// ## Note on implementing [`Decodable`] for references to non-local types |
| /// |
| /// For references to types not defined in this crate, including slices/tuples/collections |
| /// of local types, [`Decodable`] cannot use a blanket impl and must be implemented for |
| /// specific decoders instead. |
| /// |
| /// See invocations of `impl_decodable_via_ref_decodable_for_foreign_types!` for examples. |
| macro_rules! impl_decodable_via_ref_decodable_for_local_types { |
| ( |
| $( |
| &'tcx $T:ty, |
| )* |
| ) => { |
| $( |
| impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx $T { |
| fn decode(decoder: &mut D) -> Self { |
| RefDecodable::decode(decoder) |
| } |
| } |
| )* |
| } |
| } |
| |
| impl_decodable_via_ref_decodable_for_local_types! { |
| // tidy-alphabetical-start |
| &'tcx mir::Body<'tcx>, |
| &'tcx traits::ImplSource<'tcx, ()>, |
| &'tcx traits::specialization_graph::Graph, |
| &'tcx ty::List<Ty<'tcx>>, |
| &'tcx ty::List<ty::BoundVariableKind<'tcx>>, |
| &'tcx ty::List<ty::Const<'tcx>>, |
| &'tcx ty::List<ty::Pattern<'tcx>>, |
| &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, |
| &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>, |
| &'tcx ty::TypeckResults<'tcx>, |
| // tidy-alphabetical-end |
| } |