--- title: Type library plans --- # Type library plans ## 2021-03-30 ### Current status * Have [`rustc_type_ir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/index.html) crate * `rustc_type_ir` contains "leaf types" like `FloatTy` etc * contains `Debug` and `HashStable` implementations for those types ### Pending PR [#83142] * Adds `Interner` trait * Adds impl of `Interner` for `TyCtxt<'tcx>` [#83142]: https://github.com/rust-lang/rust/pull/83142 ### After this PR ### Eventual destination ```mermaid graph TD; rustc_type_ir --> rustc_middle rustc_serialize --> rustc_type_ir rustc_serialize --> rustc_middle rustc_data_structures --> rustc_type_ir rustc_data_structures --> rustc_middle ``` ```rust= // crate rustc_serialize trait Enocder {} trait Decoder {} trait Encodable<E: Encoder> {} trait Decodable<D: Decoder> {} // crate rustc_data_structures trait HashStable<CTX> { } // crate rustc_serialize // crate rustc_type_ir trait Interner { type SpanData; type Span; type InternedTy: Intern<Self, TyS<Self>>; } trait Intern<I, S> { fn intern(interner: &I, source: S) -> Self; } struct Ty<I: Interned> { interned: I::InternedTy } struct TyS<I: Interner> { ... } #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)] pub enum BoundRegionKind<I: Interner> { BrAnon(u32), BrNamed(I::DefId, I::Symbol), BrEnv, } // crate rustc_middle trait TyEncoder<'tcx>: rustc_serialize::Encoder {} trait TyDecoder<'tcx>: rustc_serialize::Decoder {} impl<'tcx> rustc_type_ir::Interner for TyCtxt<'tcx> { type DefId = DefId; type Symbol = Symbol; } // Implication: all the impls will have to use `StableHashingContext` if they might reach `BoundRegionKind` impl<CTX> rustc_data_structures::HashStable<StableHashingContext> for rustc_type_ir::BoundRegionKind<TyCtxt<'tcx>> { ... } impl<'tcx, CTX, E> Encodable<E> for rustc_type_ir::BoundRegionKind<TyCtxt<'tcx>> where E: TyEncoder<'tcx> { .. } ``` Alternative ```rust= ... // crate rustc_type_ir trait TyEncoder<I: Interner>: rustc_serialize::Encoder {} trait TyDecoder<I: Interner>: rustc_serialize::Decoder {} impl<'tcx, CTX, E> TyEncoder<I> for rustc_type_ir::TyKind<I> where E: TyEncoder<'tcx> { .. } ``` ## 2021-04-01 ### Should `rustc_type_ir` depends on `rustc_data_structures`? Probably yes, so we can use the newtype index declarations and the like. ### Why should impl of `HashStable` for `BoundRegionKind` live in `rustc_middle`? It's only important to rustc. ### But it *could* live in `rustc_type_ir`? Yes, possibly behind a feature gate. It would mean that `rustc_type_ir` would depend on `rustc_data_structures`, but that's ok, and we may do that anyway. ### Why should impl of `Encodable` for `BoundRegionKind` live in `rustc_middle`? Again, only important to rustc ### But it *could* live in `rustc_type_ir`? It could. We'd need the impls to look something like this: ```rust= impl<E, I> Encodable<E> for BoundRegionKind<I> where E: TyEncoder<I>, I: Interner, I::DefId: Encodable<E> ``` Also `TyEncoder` would have to move to `rustc_type_ir` and be made generic over `I: Interner`: ```rust= pub trait TyEncoder<I: Interner>: Encoder { const CLEAR_CROSS_CRATE: bool; fn position(&self) -> usize; fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<I>, usize>; fn predicate_shorthands( &mut self ) -> &mut FxHashMap<PredicateKind<I>, usize>; fn encode_alloc_id(&mut self, alloc_id: &AllocId) -> Result<(), Self::Error>; } ```