From f5f90540c9cac94a74080a4f7a4584cae4563625 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 14 Dec 2021 12:37:04 -0500 Subject: [PATCH 1/3] Fully serialize AdtDef This avoids needing to invoke the `adt_def` query during the decoding of another query's result. --- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/ty/adt.rs | 23 ++++++++++------------- compiler/rustc_middle/src/ty/codec.rs | 8 -------- compiler/rustc_middle/src/ty/context.rs | 5 ++++- compiler/rustc_middle/src/ty/mod.rs | 6 +++--- 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index ee2e190e7cd44..a936852f4e7af 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { [] layout: rustc_target::abi::Layout, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // 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>, [] steal_mir: rustc_data_structures::steal::Steal>, [decode] mir: rustc_middle::mir::Body<'tcx>, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 771ce2eb884af..5cde54c9328d1 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_serialize::{self, Encodable, Encoder}; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; use rustc_target::abi::VariantIdx; @@ -20,7 +19,7 @@ use std::cell::RefCell; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::ops::Range; -use std::{ptr, str}; +use std::str; use super::{ Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, @@ -30,7 +29,7 @@ use super::{ pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; /// Indicates whether the ADT is an enum. @@ -88,6 +87,7 @@ bitflags! { /// /// 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. +#[derive(TyEncodable, TyDecodable)] pub struct AdtDef { /// The `DefId` of the struct, enum or union item. 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 { - // `AdtDef`s are always interned, and this is part of `TyS` equality. #[inline] fn eq(&self, other: &Self) -> bool { - ptr::eq(self, other) + self.did == other.did } } 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 { #[inline] fn hash(&self, s: &mut H) { - (self as *const AdtDef).hash(s) - } -} - -impl Encodable for AdtDef { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.did.encode(s) + self.did.hash(s) } } @@ -161,7 +158,7 @@ impl<'a> HashStable> for AdtDef { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] pub enum AdtKind { Struct, Union, diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 3f2b987b1e630..2032f32ed8c2b 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -16,7 +16,6 @@ use crate::thir; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::Span; use std::hash::Hash; @@ -308,13 +307,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 = >::decode(decoder)?; - Ok(decoder.tcx().adt_def(def_id)) - } -} - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0bf457ca8a824..119120b57bec2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -112,6 +112,7 @@ pub struct CtxtInterners<'tcx> { const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, Layout>, + adt_def: InternedSet<'tcx, AdtDef>, } impl<'tcx> CtxtInterners<'tcx> { @@ -132,6 +133,7 @@ impl<'tcx> CtxtInterners<'tcx> { const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), + adt_def: Default::default(), } } @@ -1078,7 +1080,7 @@ impl<'tcx> TyCtxt<'tcx> { variants: IndexVec, repr: ReprOptions, ) -> &'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`. @@ -2057,6 +2059,7 @@ direct_interners! { const_: mk_const(Const<'tcx>), const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), + adt_def: intern_adt_def(AdtDef), } macro_rules! slice_interners { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d0d2a46fc4c1d..642ec51413058 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1472,7 +1472,7 @@ pub struct Destructor { } bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct VariantFlags: u32 { const NO_VARIANT_FLAGS = 0; /// 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. -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct VariantDef { /// `DefId` that identifies the variant itself. /// 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), } -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct FieldDef { pub did: DefId, #[stable_hasher(project(name))] From 70fba904121c6758e2874176e64db5a68ca14686 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 15 Dec 2021 17:01:09 -0500 Subject: [PATCH 2/3] Cache adt_def query result on disk --- compiler/rustc_middle/src/query/mod.rs | 1 + compiler/rustc_middle/src/ty/codec.rs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 58f584d65d58c..2a3b50c79bba8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -522,6 +522,7 @@ rustc_queries! { } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } separate_provide_extern } query adt_destructor(key: DefId) -> Option { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 2032f32ed8c2b..3a8a3c0b16491 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -155,7 +155,8 @@ encodable_via_deref! { &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::AdtDef } pub trait TyDecoder<'tcx>: Decoder { @@ -391,7 +392,8 @@ impl_decodable_via_ref! { &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, - &'tcx ty::List + &'tcx ty::List, + &'tcx ty::AdtDef } #[macro_export] From 00ce6dc7187a1d572c19d3939fa5876ea6bbcbb1 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 16 Dec 2021 18:32:00 -0500 Subject: [PATCH 3/3] Only cache local adt_def results on disk An `AdtDef` contains `Span`s, and we don't appear to actually encode the `SourceFile` for foreign spans in the incremental cache in some cases. --- compiler/rustc_middle/src/query/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2a3b50c79bba8..22caff1e8d975 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -522,7 +522,7 @@ rustc_queries! { } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } + cache_on_disk_if { key.is_local() } separate_provide_extern } query adt_destructor(key: DefId) -> Option {