Skip to content

Commit 90e3710

Browse files
committed
rustc_metadata: Encode list of all crate's traits into metadata
1 parent e91ad5f commit 90e3710

File tree

12 files changed

+95
-112
lines changed

12 files changed

+95
-112
lines changed

Diff for: compiler/rustc_metadata/src/rmeta/decoder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14061406
)
14071407
}
14081408

1409+
fn get_traits(&'a self) -> impl Iterator<Item = DefId> + 'a {
1410+
self.root.traits.decode(self).map(|index| self.local_def_id(index))
1411+
}
1412+
14091413
fn get_implementations_for_trait(
14101414
&self,
14111415
tcx: TyCtxt<'tcx>,

Diff for: compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+26
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use crate::native_libs;
44

55
use rustc_ast as ast;
66
use rustc_data_structures::stable_map::FxHashMap;
7+
use rustc_hir as hir;
78
use rustc_hir::def::{CtorKind, DefKind};
89
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
910
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
11+
use rustc_hir::itemlikevisit::ItemLikeVisitor;
1012
use rustc_middle::hir::exports::Export;
1113
use rustc_middle::middle::exported_symbols::ExportedSymbol;
1214
use rustc_middle::middle::stability::DeprecationEntry;
@@ -195,6 +197,8 @@ provide! { <'tcx> tcx, def_id, other, cdata,
195197

196198
extra_filename => { cdata.root.extra_filename.clone() }
197199

200+
traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
201+
198202
implementations_of_trait => {
199203
cdata.get_implementations_for_trait(tcx, Some(other))
200204
}
@@ -285,6 +289,28 @@ pub fn provide(providers: &mut Providers) {
285289
foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect();
286290
Lrc::new(modules)
287291
},
292+
traits_in_crate: |tcx, cnum| {
293+
assert_eq!(cnum, LOCAL_CRATE);
294+
295+
#[derive(Default)]
296+
struct TraitsVisitor {
297+
traits: Vec<DefId>,
298+
}
299+
impl ItemLikeVisitor<'_> for TraitsVisitor {
300+
fn visit_item(&mut self, item: &hir::Item<'_>) {
301+
if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind {
302+
self.traits.push(item.def_id.to_def_id());
303+
}
304+
}
305+
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
306+
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
307+
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
308+
}
309+
310+
let mut visitor = TraitsVisitor::default();
311+
tcx.hir().visit_all_item_likes(&mut visitor);
312+
tcx.arena.alloc_slice(&visitor.traits)
313+
},
288314

289315
// Returns a map from a sufficiently visible external item (i.e., an
290316
// external item that is visible from at least one local module) to a

Diff for: compiler/rustc_metadata/src/rmeta/encoder.rs

+37-22
Original file line numberDiff line numberDiff line change
@@ -614,8 +614,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
614614

615615
// Encode the def IDs of impls, for coherence checking.
616616
i = self.position();
617-
let impls = self.encode_impls();
618-
let impl_bytes = self.position() - i;
617+
let (traits, impls) = self.encode_traits_and_impls();
618+
let traits_and_impls_bytes = self.position() - i;
619619

620620
let tcx = self.tcx;
621621

@@ -727,6 +727,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
727727
foreign_modules,
728728
source_map,
729729
impls,
730+
traits,
730731
exported_symbols,
731732
interpret_alloc_index,
732733
tables,
@@ -753,7 +754,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
753754
eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes);
754755
eprintln!(" native bytes: {}", native_lib_bytes);
755756
eprintln!(" source_map bytes: {}", source_map_bytes);
756-
eprintln!(" impl bytes: {}", impl_bytes);
757+
eprintln!("traits and impls bytes: {}", traits_and_impls_bytes);
757758
eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
758759
eprintln!(" def-path table bytes: {}", def_path_table_bytes);
759760
eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes);
@@ -1784,16 +1785,23 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
17841785
}
17851786

17861787
/// Encodes an index, mapping each trait to its (local) implementations.
1787-
fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
1788-
empty_proc_macro!(self);
1789-
debug!("EncodeContext::encode_impls()");
1788+
fn encode_traits_and_impls(&mut self) -> (Lazy<[DefIndex]>, Lazy<[TraitImpls]>) {
1789+
if self.is_proc_macro {
1790+
return (Lazy::empty(), Lazy::empty());
1791+
}
1792+
debug!("EncodeContext::encode_traits_and_impls()");
17901793
let tcx = self.tcx;
1791-
let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() };
1794+
let mut visitor =
1795+
TraitsAndImplsVisitor { tcx, impls: FxHashMap::default(), traits: Default::default() };
17921796
tcx.hir().visit_all_item_likes(&mut visitor);
17931797

1798+
let mut all_traits = visitor.traits;
17941799
let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
17951800

17961801
// Bring everything into deterministic order for hashing
1802+
all_traits.sort_by_cached_key(|&local_def_index| {
1803+
tcx.hir().def_path_hash(LocalDefId { local_def_index })
1804+
});
17971805
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
17981806

17991807
let all_impls: Vec<_> = all_impls
@@ -1811,7 +1819,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
18111819
})
18121820
.collect();
18131821

1814-
self.lazy(&all_impls)
1822+
(self.lazy(&all_traits), self.lazy(&all_impls))
18151823
}
18161824

18171825
// Encodes all symbols exported from this crate into the metadata.
@@ -2033,27 +2041,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20332041
}
20342042
}
20352043

2036-
struct ImplVisitor<'tcx> {
2044+
struct TraitsAndImplsVisitor<'tcx> {
20372045
tcx: TyCtxt<'tcx>,
2046+
traits: Vec<DefIndex>,
20382047
impls: FxHashMap<DefId, Vec<(DefIndex, Option<fast_reject::SimplifiedType>)>>,
20392048
}
20402049

2041-
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
2050+
impl<'tcx, 'v> ItemLikeVisitor<'v> for TraitsAndImplsVisitor<'tcx> {
20422051
fn visit_item(&mut self, item: &hir::Item<'_>) {
2043-
if let hir::ItemKind::Impl { .. } = item.kind {
2044-
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
2045-
let simplified_self_ty = fast_reject::simplify_type(
2046-
self.tcx,
2047-
trait_ref.self_ty(),
2048-
SimplifyParams::No,
2049-
StripReferences::No,
2050-
);
2052+
match item.kind {
2053+
hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
2054+
self.traits.push(item.def_id.local_def_index);
2055+
}
2056+
hir::ItemKind::Impl(..) => {
2057+
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
2058+
let simplified_self_ty = fast_reject::simplify_type(
2059+
self.tcx,
2060+
trait_ref.self_ty(),
2061+
SimplifyParams::No,
2062+
StripReferences::No,
2063+
);
20512064

2052-
self.impls
2053-
.entry(trait_ref.def_id)
2054-
.or_default()
2055-
.push((item.def_id.local_def_index, simplified_self_ty));
2065+
self.impls
2066+
.entry(trait_ref.def_id)
2067+
.or_default()
2068+
.push((item.def_id.local_def_index, simplified_self_ty));
2069+
}
20562070
}
2071+
_ => {}
20572072
}
20582073
}
20592074

Diff for: compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ crate struct CrateRoot<'tcx> {
222222
diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
223223
native_libraries: Lazy<[NativeLib]>,
224224
foreign_modules: Lazy<[ForeignModule]>,
225+
traits: Lazy<[DefIndex]>,
225226
impls: Lazy<[TraitImpls]>,
226227
interpret_alloc_index: Lazy<[u32]>,
227228
proc_macro_data: Option<ProcMacroData>,

Diff for: compiler/rustc_middle/src/query/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1609,11 +1609,11 @@ rustc_queries! {
16091609
desc { "fetching all foreign CrateNum instances" }
16101610
}
16111611

1612-
/// A vector of every trait accessible in the whole crate
1613-
/// (i.e., including those from subcrates). This is used only for
1614-
/// error reporting.
1615-
query all_traits(_: ()) -> &'tcx [DefId] {
1616-
desc { "fetching all foreign and local traits" }
1612+
/// A list of all traits in a crate, used by rustdoc and error reporting.
1613+
/// NOTE: Not named just `traits` due to a naming conflict.
1614+
query traits_in_crate(_: CrateNum) -> &'tcx [DefId] {
1615+
desc { "fetching all traits in a crate" }
1616+
separate_provide_extern
16171617
}
16181618

16191619
/// The list of symbols exported from the given crate.

Diff for: compiler/rustc_middle/src/ty/context.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,12 @@ impl<'tcx> TyCtxt<'tcx> {
15771577
pub fn const_eval_limit(self) -> Limit {
15781578
self.limits(()).const_eval_limit
15791579
}
1580+
1581+
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
1582+
iter::once(LOCAL_CRATE)
1583+
.chain(self.crates(()).iter().copied())
1584+
.flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
1585+
}
15801586
}
15811587

15821588
/// A trait implemented for all `X<'a>` types that can be safely and

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1567,14 +1567,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15671567
self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some)
15681568
};
15691569
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
1570-
let all_traits = self.tcx.all_traits(());
1571-
let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
1572-
.iter()
1573-
.filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
1574-
.filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
1570+
let traits_with_same_path: std::collections::BTreeSet<_> = self
1571+
.tcx
1572+
.all_traits()
1573+
.filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
1574+
.filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path)
15751575
.collect();
15761576
for trait_with_same_path in traits_with_same_path {
1577-
if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
1577+
if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) {
15781578
let impl_span = self.tcx.def_span(impl_def_id);
15791579
err.span_help(impl_span, "trait impl with same name found");
15801580
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);

Diff for: compiler/rustc_typeck/src/check/method/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod prelude2021;
77
pub mod probe;
88
mod suggest;
99

10-
pub use self::suggest::{SelfSource, TraitInfo};
10+
pub use self::suggest::SelfSource;
1111
pub use self::CandidateSource::*;
1212
pub use self::MethodError::*;
1313

@@ -31,7 +31,6 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
3131
use self::probe::{IsSuggestion, ProbeScope};
3232

3333
pub fn provide(providers: &mut ty::query::Providers) {
34-
suggest::provide(providers);
3534
probe::provide(providers);
3635
}
3736

Diff for: compiler/rustc_typeck/src/check/method/suggest.rs

+5-71
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::check::FnCtxt;
55
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
66
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
77
use rustc_hir as hir;
8-
use rustc_hir::def::{DefKind, Namespace, Res};
9-
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
8+
use rustc_hir::def::Namespace;
9+
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_hir::lang_items::LangItem;
1111
use rustc_hir::{ExprKind, Node, QPath};
1212
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -1922,76 +1922,10 @@ impl Ord for TraitInfo {
19221922
}
19231923
}
19241924

1925-
/// Retrieves all traits in this crate and any dependent crates.
1925+
/// Retrieves all traits in this crate and any dependent crates,
1926+
/// and wraps them into `TraitInfo` for custom sorting.
19261927
pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1927-
tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
1928-
}
1929-
1930-
/// Computes all traits in this crate and any dependent crates.
1931-
fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
1932-
use hir::itemlikevisit;
1933-
1934-
let mut traits = vec![];
1935-
1936-
// Crate-local:
1937-
1938-
struct Visitor<'a> {
1939-
traits: &'a mut Vec<DefId>,
1940-
}
1941-
1942-
impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1943-
fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1944-
match i.kind {
1945-
hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1946-
self.traits.push(i.def_id.to_def_id());
1947-
}
1948-
_ => (),
1949-
}
1950-
}
1951-
1952-
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1953-
1954-
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1955-
1956-
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1957-
}
1958-
1959-
tcx.hir().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1960-
1961-
// Cross-crate:
1962-
1963-
let mut external_mods = FxHashSet::default();
1964-
fn handle_external_res(
1965-
tcx: TyCtxt<'_>,
1966-
traits: &mut Vec<DefId>,
1967-
external_mods: &mut FxHashSet<DefId>,
1968-
res: Res<!>,
1969-
) {
1970-
match res {
1971-
Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1972-
traits.push(def_id);
1973-
}
1974-
Res::Def(DefKind::Mod, def_id) => {
1975-
if !external_mods.insert(def_id) {
1976-
return;
1977-
}
1978-
for child in tcx.item_children(def_id).iter() {
1979-
handle_external_res(tcx, traits, external_mods, child.res)
1980-
}
1981-
}
1982-
_ => {}
1983-
}
1984-
}
1985-
for &cnum in tcx.crates(()).iter() {
1986-
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1987-
handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1988-
}
1989-
1990-
tcx.arena.alloc_from_iter(traits)
1991-
}
1992-
1993-
pub fn provide(providers: &mut ty::query::Providers) {
1994-
providers.all_traits = compute_all_traits;
1928+
tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
19951929
}
19961930

19971931
fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {

Diff for: src/librustdoc/clean/blanket_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
1919

2020
trace!("get_blanket_impls({:?})", ty);
2121
let mut impls = Vec::new();
22-
for &trait_def_id in self.cx.tcx.all_traits(()).iter() {
22+
for trait_def_id in self.cx.tcx.all_traits() {
2323
if !self.cx.cache.access_levels.is_public(trait_def_id)
2424
|| self.cx.generated_synthetics.get(&(ty, trait_def_id)).is_some()
2525
{

Diff for: src/librustdoc/core.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,8 @@ crate fn run_global_ctxt(
369369
impl_trait_bounds: Default::default(),
370370
generated_synthetics: Default::default(),
371371
auto_traits: tcx
372-
.all_traits(())
373-
.iter()
374-
.cloned()
375-
.filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id))
372+
.all_traits()
373+
.filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id))
376374
.collect(),
377375
module_trait_cache: FxHashMap::default(),
378376
cache: Cache::new(access_levels, render_options.document_private),

Diff for: src/librustdoc/passes/collect_trait_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
129129
// `tcx.crates(())` doesn't include the local crate, and `tcx.all_trait_implementations`
130130
// doesn't work with it anyway, so pull them from the HIR map instead
131131
let mut extra_attrs = Vec::new();
132-
for &trait_did in cx.tcx.all_traits(()).iter() {
132+
for trait_did in cx.tcx.all_traits() {
133133
for &impl_did in cx.tcx.hir().trait_impls(trait_did) {
134134
let impl_did = impl_did.to_def_id();
135135
cx.tcx.sess.prof.generic_activity("build_local_trait_impl").run(|| {

0 commit comments

Comments
 (0)