1
Fork 0

Auto merge of #91924 - Aaron1011:serialize-adt-def, r=michaelwoerister

Fully serialize AdtDef

This avoids needing to invoke the `adt_def` query during
the decoding of another query's result.

Split out from https://github.com/rust-lang/rust/pull/91919
See https://github.com/rust-lang/rust/issues/91696#issuecomment-993043710
This commit is contained in:
bors 2021-12-20 10:35:48 +00:00
commit 84f962a89b
6 changed files with 23 additions and 28 deletions

View file

@ -9,7 +9,7 @@ macro_rules! arena_types {
[] layout: rustc_target::abi::Layout, [] layout: rustc_target::abi::Layout,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address // AdtDef are interned and compared by address
[] adt_def: rustc_middle::ty::AdtDef, [decode] adt_def: rustc_middle::ty::AdtDef,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>, [] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>,
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>, [] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
[decode] mir: rustc_middle::mir::Body<'tcx>, [decode] mir: rustc_middle::mir::Body<'tcx>,

View file

@ -522,6 +522,7 @@ rustc_queries! {
} }
query adt_def(key: DefId) -> &'tcx ty::AdtDef { query adt_def(key: DefId) -> &'tcx ty::AdtDef {
desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern separate_provide_extern
} }
query adt_destructor(key: DefId) -> Option<ty::Destructor> { query adt_destructor(key: DefId) -> Option<ty::Destructor> {

View file

@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{self, Encodable, Encoder};
use rustc_session::DataTypeKind; use rustc_session::DataTypeKind;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
@ -20,7 +19,7 @@ use std::cell::RefCell;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Range; use std::ops::Range;
use std::{ptr, str}; use std::str;
use super::{ use super::{
Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr,
@ -30,7 +29,7 @@ use super::{
pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);
bitflags! { bitflags! {
#[derive(HashStable)] #[derive(HashStable, TyEncodable, TyDecodable)]
pub struct AdtFlags: u32 { pub struct AdtFlags: u32 {
const NO_ADT_FLAGS = 0; const NO_ADT_FLAGS = 0;
/// Indicates whether the ADT is an enum. /// Indicates whether the ADT is an enum.
@ -88,6 +87,7 @@ bitflags! {
/// ///
/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId` /// where `x` here represents the `DefId` of `S.x`. Then, the `DefId`
/// can be used with [`TyCtxt::type_of()`] to get the type of the field. /// can be used with [`TyCtxt::type_of()`] to get the type of the field.
#[derive(TyEncodable, TyDecodable)]
pub struct AdtDef { pub struct AdtDef {
/// The `DefId` of the struct, enum or union item. /// The `DefId` of the struct, enum or union item.
pub did: DefId, pub did: DefId,
@ -113,26 +113,23 @@ impl Ord for AdtDef {
} }
} }
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `PartialEq` only based on `did`.
impl PartialEq for AdtDef { impl PartialEq for AdtDef {
// `AdtDef`s are always interned, and this is part of `TyS` equality.
#[inline] #[inline]
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
ptr::eq(self, other) self.did == other.did
} }
} }
impl Eq for AdtDef {} impl Eq for AdtDef {}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `Hash` only based on `did`.
impl Hash for AdtDef { impl Hash for AdtDef {
#[inline] #[inline]
fn hash<H: Hasher>(&self, s: &mut H) { fn hash<H: Hasher>(&self, s: &mut H) {
(self as *const AdtDef).hash(s) self.did.hash(s)
}
}
impl<S: Encoder> Encodable<S> for AdtDef {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
self.did.encode(s)
} }
} }
@ -161,7 +158,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
} }
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
pub enum AdtKind { pub enum AdtKind {
Struct, Struct,
Union, Union,

View file

@ -16,7 +16,6 @@ use crate::thir;
use crate::ty::subst::SubstsRef; use crate::ty::subst::SubstsRef;
use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{self, List, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::Span; use rustc_span::Span;
use std::hash::Hash; use std::hash::Hash;
@ -160,7 +159,8 @@ encodable_via_deref! {
&'tcx mir::Body<'tcx>, &'tcx mir::Body<'tcx>,
&'tcx mir::UnsafetyCheckResult, &'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion &'tcx mir::coverage::CodeRegion,
&'tcx ty::AdtDef
} }
pub trait TyDecoder<'tcx>: Decoder { pub trait TyDecoder<'tcx>: Decoder {
@ -312,13 +312,6 @@ macro_rules! impl_decodable_via_ref {
} }
} }
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
let def_id = <DefId as Decodable<D>>::decode(decoder)?;
Ok(decoder.tcx().adt_def(def_id))
}
}
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> { impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
let len = decoder.read_usize()?; let len = decoder.read_usize()?;
@ -403,7 +396,8 @@ impl_decodable_via_ref! {
&'tcx mir::UnsafetyCheckResult, &'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion, &'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind> &'tcx ty::List<ty::BoundVariableKind>,
&'tcx ty::AdtDef
} }
#[macro_export] #[macro_export]

View file

@ -112,6 +112,7 @@ pub struct CtxtInterners<'tcx> {
const_allocation: InternedSet<'tcx, Allocation>, const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, Layout>, layout: InternedSet<'tcx, Layout>,
adt_def: InternedSet<'tcx, AdtDef>,
} }
impl<'tcx> CtxtInterners<'tcx> { impl<'tcx> CtxtInterners<'tcx> {
@ -132,6 +133,7 @@ impl<'tcx> CtxtInterners<'tcx> {
const_allocation: Default::default(), const_allocation: Default::default(),
bound_variable_kinds: Default::default(), bound_variable_kinds: Default::default(),
layout: Default::default(), layout: Default::default(),
adt_def: Default::default(),
} }
} }
@ -1078,7 +1080,7 @@ impl<'tcx> TyCtxt<'tcx> {
variants: IndexVec<VariantIdx, ty::VariantDef>, variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions, repr: ReprOptions,
) -> &'tcx ty::AdtDef { ) -> &'tcx ty::AdtDef {
self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) self.intern_adt_def(ty::AdtDef::new(self, did, kind, variants, repr))
} }
/// Allocates a read-only byte or string literal for `mir::interpret`. /// Allocates a read-only byte or string literal for `mir::interpret`.
@ -2057,6 +2059,7 @@ direct_interners! {
const_: mk_const(Const<'tcx>), const_: mk_const(Const<'tcx>),
const_allocation: intern_const_alloc(Allocation), const_allocation: intern_const_alloc(Allocation),
layout: intern_layout(Layout), layout: intern_layout(Layout),
adt_def: intern_adt_def(AdtDef),
} }
macro_rules! slice_interners { macro_rules! slice_interners {

View file

@ -1472,7 +1472,7 @@ pub struct Destructor {
} }
bitflags! { bitflags! {
#[derive(HashStable)] #[derive(HashStable, TyEncodable, TyDecodable)]
pub struct VariantFlags: u32 { pub struct VariantFlags: u32 {
const NO_VARIANT_FLAGS = 0; const NO_VARIANT_FLAGS = 0;
/// Indicates whether the field list of this variant is `#[non_exhaustive]`. /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
@ -1484,7 +1484,7 @@ bitflags! {
} }
/// Definition of a variant -- a struct's fields or an enum variant. /// Definition of a variant -- a struct's fields or an enum variant.
#[derive(Debug, HashStable)] #[derive(Debug, HashStable, TyEncodable, TyDecodable)]
pub struct VariantDef { pub struct VariantDef {
/// `DefId` that identifies the variant itself. /// `DefId` that identifies the variant itself.
/// If this variant belongs to a struct or union, then this is a copy of its `DefId`. /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
@ -1586,7 +1586,7 @@ pub enum VariantDiscr {
Relative(u32), Relative(u32),
} }
#[derive(Debug, HashStable)] #[derive(Debug, HashStable, TyEncodable, TyDecodable)]
pub struct FieldDef { pub struct FieldDef {
pub did: DefId, pub did: DefId,
#[stable_hasher(project(name))] #[stable_hasher(project(name))]