Skip to content

Commit 3cfc7fe

Browse files
committed
Auto merge of #75008 - eddyb:rmeta-indexed-trait-impls, r=nikomatsakis
rustc_metadata: track the simplified Self type for every trait impl. For the `traits_impls_of` query, we index the impls by `fast_reject::SimplifiedType` (a "shallow type"), which allows some simple cases like `impl Trait<..> for Foo<..>` to be efficiently iterated over, by e.g. `for_each_relevant_impl`. This PR encodes the `fast_reject::SimplifiedType` cross-crate to avoid needing to deserialize the `Self` type of every `impl` in order to simplify it - the simplification itself should be cheap, but the deserialization is less so. We could go further from here and make loading the list of impls lazy, for a given simplified `Self` type, but that would have more complicated implications for performance, and this PR doesn't do anything in that regard. r? @nikomatsakis cc @Mark-Simulacrum
2 parents 22ee68d + 6bf3a4b commit 3cfc7fe

File tree

6 files changed

+54
-37
lines changed

6 files changed

+54
-37
lines changed

src/librustc_metadata/rmeta/decoder.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ crate struct CrateMetadata {
7878
/// Trait impl data.
7979
/// FIXME: Used only from queries and can use query cache,
8080
/// so pre-decoding can probably be avoided.
81-
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[DefIndex]>>,
81+
trait_impls:
82+
FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>>,
8283
/// Proc macro descriptions for this crate, if it's a proc macro crate.
8384
raw_proc_macros: Option<&'static [ProcMacro]>,
8485
/// Source maps for code from the crate.
@@ -1289,7 +1290,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
12891290
&self,
12901291
tcx: TyCtxt<'tcx>,
12911292
filter: Option<DefId>,
1292-
) -> &'tcx [DefId] {
1293+
) -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
12931294
if self.root.is_proc_macro_crate() {
12941295
// proc-macro crates export no trait impls.
12951296
return &[];
@@ -1305,16 +1306,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
13051306

13061307
if let Some(filter) = filter {
13071308
if let Some(impls) = self.trait_impls.get(&filter) {
1308-
tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
1309+
tcx.arena.alloc_from_iter(
1310+
impls.decode(self).map(|(idx, simplified_self_ty)| {
1311+
(self.local_def_id(idx), simplified_self_ty)
1312+
}),
1313+
)
13091314
} else {
13101315
&[]
13111316
}
13121317
} else {
1313-
tcx.arena.alloc_from_iter(
1314-
self.trait_impls
1315-
.values()
1316-
.flat_map(|impls| impls.decode(self).map(|idx| self.local_def_id(idx))),
1317-
)
1318+
tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| {
1319+
impls
1320+
.decode(self)
1321+
.map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty))
1322+
}))
13181323
}
13191324
}
13201325

src/librustc_metadata/rmeta/encoder.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,7 @@ impl EncodeContext<'a, 'tcx> {
16101610
.into_iter()
16111611
.map(|(trait_def_id, mut impls)| {
16121612
// Bring everything into deterministic order for hashing
1613-
impls.sort_by_cached_key(|&index| {
1613+
impls.sort_by_cached_key(|&(index, _)| {
16141614
tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
16151615
});
16161616

@@ -1852,15 +1852,21 @@ impl EncodeContext<'a, 'tcx> {
18521852

18531853
struct ImplVisitor<'tcx> {
18541854
tcx: TyCtxt<'tcx>,
1855-
impls: FxHashMap<DefId, Vec<DefIndex>>,
1855+
impls: FxHashMap<DefId, Vec<(DefIndex, Option<ty::fast_reject::SimplifiedType>)>>,
18561856
}
18571857

18581858
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
18591859
fn visit_item(&mut self, item: &hir::Item<'_>) {
18601860
if let hir::ItemKind::Impl { .. } = item.kind {
18611861
let impl_id = self.tcx.hir().local_def_id(item.hir_id);
18621862
if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id.to_def_id()) {
1863-
self.impls.entry(trait_ref.def_id).or_default().push(impl_id.local_def_index);
1863+
let simplified_self_ty =
1864+
ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false);
1865+
1866+
self.impls
1867+
.entry(trait_ref.def_id)
1868+
.or_default()
1869+
.push((impl_id.local_def_index, simplified_self_ty));
18641870
}
18651871
}
18661872
}

src/librustc_metadata/rmeta/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ crate struct CrateDep {
233233
#[derive(RustcEncodable, RustcDecodable)]
234234
crate struct TraitImpls {
235235
trait_id: (u32, DefIndex),
236-
impls: Lazy<[DefIndex]>,
236+
impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>,
237237
}
238238

239239
/// Define `LazyTables` and `TableBuilders` at the same time.

src/librustc_middle/query/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1125,11 +1125,11 @@ rustc_queries! {
11251125

11261126
TypeChecking {
11271127
query implementations_of_trait(_: (CrateNum, DefId))
1128-
-> &'tcx [DefId] {
1128+
-> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
11291129
desc { "looking up implementations of a trait in a crate" }
11301130
}
11311131
query all_trait_implementations(_: CrateNum)
1132-
-> &'tcx [DefId] {
1132+
-> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
11331133
desc { "looking up all (?) trait implementations" }
11341134
}
11351135
}

src/librustc_middle/ty/trait_def.rs

+28-22
Original file line numberDiff line numberDiff line change
@@ -187,32 +187,38 @@ pub(super) fn all_local_trait_impls<'tcx>(
187187
pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls {
188188
let mut impls = TraitImpls::default();
189189

190-
{
191-
let mut add_impl = |impl_def_id: DefId| {
192-
let impl_self_ty = tcx.type_of(impl_def_id);
193-
if impl_def_id.is_local() && impl_self_ty.references_error() {
194-
return;
195-
}
196-
197-
if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) {
198-
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
199-
} else {
200-
impls.blanket_impls.push(impl_def_id);
201-
}
202-
};
203-
204-
// Traits defined in the current crate can't have impls in upstream
205-
// crates, so we don't bother querying the cstore.
206-
if !trait_id.is_local() {
207-
for &cnum in tcx.crates().iter() {
208-
for &def_id in tcx.implementations_of_trait((cnum, trait_id)).iter() {
209-
add_impl(def_id);
190+
// Traits defined in the current crate can't have impls in upstream
191+
// crates, so we don't bother querying the cstore.
192+
if !trait_id.is_local() {
193+
for &cnum in tcx.crates().iter() {
194+
for &(impl_def_id, simplified_self_ty) in
195+
tcx.implementations_of_trait((cnum, trait_id)).iter()
196+
{
197+
if let Some(simplified_self_ty) = simplified_self_ty {
198+
impls
199+
.non_blanket_impls
200+
.entry(simplified_self_ty)
201+
.or_default()
202+
.push(impl_def_id);
203+
} else {
204+
impls.blanket_impls.push(impl_def_id);
210205
}
211206
}
212207
}
208+
}
209+
210+
for &hir_id in tcx.hir().trait_impls(trait_id) {
211+
let impl_def_id = tcx.hir().local_def_id(hir_id).to_def_id();
212+
213+
let impl_self_ty = tcx.type_of(impl_def_id);
214+
if impl_self_ty.references_error() {
215+
continue;
216+
}
213217

214-
for &hir_id in tcx.hir().trait_impls(trait_id) {
215-
add_impl(tcx.hir().local_def_id(hir_id).to_def_id());
218+
if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) {
219+
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
220+
} else {
221+
impls.blanket_impls.push(impl_def_id);
216222
}
217223
}
218224

src/librustdoc/passes/collect_trait_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
2828
let mut new_items = Vec::new();
2929

3030
for &cnum in cx.tcx.crates().iter() {
31-
for &did in cx.tcx.all_trait_implementations(cnum).iter() {
31+
for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() {
3232
inline::build_impl(cx, did, None, &mut new_items);
3333
}
3434
}

0 commit comments

Comments
 (0)