rustc_metadata: Use a query for collecting all traits in encoder

This commit is contained in:
Vadim Petrochenkov 2021-12-31 18:15:52 +08:00
parent 4d2e0fd96c
commit 2dd50d5eb2
4 changed files with 63 additions and 48 deletions

View File

@ -45,7 +45,8 @@
use std::path::Path; use std::path::Path;
use tracing::debug; use tracing::debug;
pub use cstore_impl::{provide, provide_extern}; pub(super) use cstore_impl::provide;
pub use cstore_impl::provide_extern;
use rustc_span::hygiene::HygieneDecodeContext; use rustc_span::hygiene::HygieneDecodeContext;
mod cstore_impl; mod cstore_impl;

View File

@ -4,11 +4,9 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::stable_map::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::hir::exports::Export; use rustc_middle::hir::exports::Export;
use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::middle::stability::DeprecationEntry;
@ -243,7 +241,7 @@ fn into_args(self) -> (DefId, DefId) {
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
} }
pub fn provide(providers: &mut Providers) { pub(in crate::rmeta) fn provide(providers: &mut Providers) {
// FIXME(#44234) - almost all of these queries have no sub-queries and // FIXME(#44234) - almost all of these queries have no sub-queries and
// therefore no actual inputs, they're just reading tables calculated in // therefore no actual inputs, they're just reading tables calculated in
// resolve! Does this work? Unsure! That's what the issue is about // resolve! Does this work? Unsure! That's what the issue is about
@ -289,28 +287,6 @@ pub fn provide(providers: &mut Providers) {
foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect(); foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect();
Lrc::new(modules) Lrc::new(modules)
}, },
traits_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
#[derive(Default)]
struct TraitsVisitor {
traits: Vec<DefId>,
}
impl ItemLikeVisitor<'_> for TraitsVisitor {
fn visit_item(&mut self, item: &hir::Item<'_>) {
if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind {
self.traits.push(item.def_id.to_def_id());
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
}
let mut visitor = TraitsVisitor::default();
tcx.hir().visit_all_item_likes(&mut visitor);
tcx.arena.alloc_slice(&visitor.traits)
},
// Returns a map from a sufficiently visible external item (i.e., an // Returns a map from a sufficiently visible external item (i.e., an
// external item that is visible from at least one local module) to a // external item that is visible from at least one local module) to a

View File

@ -27,6 +27,7 @@
use rustc_middle::traits::specialization_graph; use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_serialize::{opaque, Encodable, Encoder};
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
@ -612,10 +613,15 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
self.encode_def_path_table(); self.encode_def_path_table();
let def_path_table_bytes = self.position() - i; let def_path_table_bytes = self.position() - i;
// Encode the def IDs of traits, for rustdoc and diagnostics.
i = self.position();
let traits = self.encode_traits();
let traits_bytes = self.position() - i;
// Encode the def IDs of impls, for coherence checking. // Encode the def IDs of impls, for coherence checking.
i = self.position(); i = self.position();
let (traits, impls) = self.encode_traits_and_impls(); let impls = self.encode_impls();
let traits_and_impls_bytes = self.position() - i; let impls_bytes = self.position() - i;
let tcx = self.tcx; let tcx = self.tcx;
@ -726,8 +732,8 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
native_libraries, native_libraries,
foreign_modules, foreign_modules,
source_map, source_map,
impls,
traits, traits,
impls,
exported_symbols, exported_symbols,
interpret_alloc_index, interpret_alloc_index,
tables, tables,
@ -754,7 +760,8 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes); eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes);
eprintln!(" native bytes: {}", native_lib_bytes); eprintln!(" native bytes: {}", native_lib_bytes);
eprintln!(" source_map bytes: {}", source_map_bytes); eprintln!(" source_map bytes: {}", source_map_bytes);
eprintln!("traits and impls bytes: {}", traits_and_impls_bytes); eprintln!(" traits bytes: {}", traits_bytes);
eprintln!(" impls bytes: {}", impls_bytes);
eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
eprintln!(" def-path table bytes: {}", def_path_table_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes);
eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes);
@ -1791,24 +1798,22 @@ fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
self.lazy(&tcx.lang_items().missing) self.lazy(&tcx.lang_items().missing)
} }
/// Encodes an index, mapping each trait to its (local) implementations. fn encode_traits(&mut self) -> Lazy<[DefIndex]> {
fn encode_traits_and_impls(&mut self) -> (Lazy<[DefIndex]>, Lazy<[TraitImpls]>) { empty_proc_macro!(self);
if self.is_proc_macro { self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
return (Lazy::empty(), Lazy::empty());
} }
/// Encodes an index, mapping each trait to its (local) implementations.
fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
debug!("EncodeContext::encode_traits_and_impls()"); debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self);
let tcx = self.tcx; let tcx = self.tcx;
let mut visitor = let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() };
TraitsAndImplsVisitor { tcx, impls: FxHashMap::default(), traits: Default::default() };
tcx.hir().visit_all_item_likes(&mut visitor); tcx.hir().visit_all_item_likes(&mut visitor);
let mut all_traits = visitor.traits;
let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
// Bring everything into deterministic order for hashing // Bring everything into deterministic order for hashing
all_traits.sort_by_cached_key(|&local_def_index| {
tcx.hir().def_path_hash(LocalDefId { local_def_index })
});
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id)); all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
let all_impls: Vec<_> = all_impls let all_impls: Vec<_> = all_impls
@ -1826,7 +1831,7 @@ fn encode_traits_and_impls(&mut self) -> (Lazy<[DefIndex]>, Lazy<[TraitImpls]>)
}) })
.collect(); .collect();
(self.lazy(&all_traits), self.lazy(&all_impls)) self.lazy(&all_impls)
} }
// Encodes all symbols exported from this crate into the metadata. // Encodes all symbols exported from this crate into the metadata.
@ -2048,18 +2053,14 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
} }
} }
struct TraitsAndImplsVisitor<'tcx> { struct ImplsVisitor<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
traits: Vec<DefIndex>,
impls: FxHashMap<DefId, Vec<(DefIndex, Option<fast_reject::SimplifiedType>)>>, impls: FxHashMap<DefId, Vec<(DefIndex, Option<fast_reject::SimplifiedType>)>>,
} }
impl<'tcx, 'v> ItemLikeVisitor<'v> for TraitsAndImplsVisitor<'tcx> { impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
match item.kind { match item.kind {
hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
self.traits.push(item.def_id.local_def_index);
}
hir::ItemKind::Impl(..) => { hir::ItemKind::Impl(..) => {
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
let simplified_self_ty = fast_reject::simplify_type( let simplified_self_ty = fast_reject::simplify_type(
@ -2224,3 +2225,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
EncodedMetadata { raw_data: result } EncodedMetadata { raw_data: result }
} }
pub fn provide(providers: &mut Providers) {
*providers = Providers {
traits_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
#[derive(Default)]
struct TraitsVisitor {
traits: Vec<DefId>,
}
impl ItemLikeVisitor<'_> for TraitsVisitor {
fn visit_item(&mut self, item: &hir::Item<'_>) {
if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind {
self.traits.push(item.def_id.to_def_id());
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
}
let mut visitor = TraitsVisitor::default();
tcx.hir().visit_all_item_likes(&mut visitor);
// Bring everything into deterministic order.
visitor.traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
tcx.arena.alloc_slice(&visitor.traits)
},
..*providers
};
}

View File

@ -16,6 +16,7 @@
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::thir; use rustc_middle::thir;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_serialize::opaque::Encoder; use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion; use rustc_session::config::SymbolManglingVersion;
@ -29,8 +30,8 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
pub use decoder::provide_extern;
use decoder::DecodeContext; use decoder::DecodeContext;
pub use decoder::{provide, provide_extern};
crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
use encoder::EncodeContext; use encoder::EncodeContext;
pub use encoder::{encode_metadata, EncodedMetadata}; pub use encoder::{encode_metadata, EncodedMetadata};
@ -454,3 +455,8 @@ struct GeneratorData<'tcx> {
const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_LOCAL: u8 = 0;
const TAG_VALID_SPAN_FOREIGN: u8 = 1; const TAG_VALID_SPAN_FOREIGN: u8 = 1;
const TAG_PARTIAL_SPAN: u8 = 2; const TAG_PARTIAL_SPAN: u8 = 2;
pub fn provide(providers: &mut Providers) {
encoder::provide(providers);
decoder::provide(providers);
}