Skip to content

Commit e426874

Browse files
authored
Rollup merge of #103192 - petrochenkov:noalltraits, r=jyn514
rustdoc: Eliminate uses of `EarlyDocLinkResolver::all_traits` Another step to #94857.
2 parents 518d5eb + 1754745 commit e426874

File tree

4 files changed

+117
-133
lines changed

4 files changed

+117
-133
lines changed

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

-5
Original file line numberDiff line numberDiff line change
@@ -587,11 +587,6 @@ impl CStore {
587587
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
588588
}
589589

590-
/// Decodes all traits in the crate (for rustdoc).
591-
pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
592-
self.get_crate_data(cnum).get_traits()
593-
}
594-
595590
/// Decodes all trait impls in the crate (for rustdoc).
596591
pub fn trait_impls_in_crate_untracked(
597592
&self,

src/librustdoc/clean/blanket_impl.rs

+102-94
Original file line numberDiff line numberDiff line change
@@ -13,116 +13,124 @@ pub(crate) struct BlanketImplFinder<'a, 'tcx> {
1313

1414
impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
1515
pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
16-
let param_env = self.cx.tcx.param_env(item_def_id);
17-
let ty = self.cx.tcx.bound_type_of(item_def_id);
16+
let cx = &mut self.cx;
17+
let param_env = cx.tcx.param_env(item_def_id);
18+
let ty = cx.tcx.bound_type_of(item_def_id);
1819

1920
trace!("get_blanket_impls({:?})", ty);
2021
let mut impls = Vec::new();
21-
self.cx.with_all_traits(|cx, all_traits| {
22-
for &trait_def_id in all_traits {
23-
if !cx.cache.access_levels.is_public(trait_def_id)
24-
|| cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
25-
{
22+
for trait_def_id in cx.tcx.all_traits() {
23+
if !cx.cache.access_levels.is_public(trait_def_id)
24+
|| cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
25+
{
26+
continue;
27+
}
28+
// NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
29+
let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
30+
'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
31+
trace!(
32+
"get_blanket_impls: Considering impl for trait '{:?}' {:?}",
33+
trait_def_id,
34+
impl_def_id
35+
);
36+
let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
37+
if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
2638
continue;
2739
}
28-
// NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
29-
let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
30-
'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
31-
trace!(
32-
"get_blanket_impls: Considering impl for trait '{:?}' {:?}",
33-
trait_def_id,
34-
impl_def_id
35-
);
36-
let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
37-
if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
38-
continue;
39-
}
40-
let infcx = cx.tcx.infer_ctxt().build();
41-
let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
42-
let impl_ty = ty.subst(infcx.tcx, substs);
43-
let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
40+
let infcx = cx.tcx.infer_ctxt().build();
41+
let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
42+
let impl_ty = ty.subst(infcx.tcx, substs);
43+
let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
4444

45-
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
46-
let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
45+
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
46+
let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
4747

48-
// Require the type the impl is implemented on to match
49-
// our type, and ignore the impl if there was a mismatch.
50-
let cause = traits::ObligationCause::dummy();
51-
let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else {
48+
// Require the type the impl is implemented on to match
49+
// our type, and ignore the impl if there was a mismatch.
50+
let cause = traits::ObligationCause::dummy();
51+
let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else {
5252
continue
5353
};
54-
let InferOk { value: (), obligations } = eq_result;
55-
// FIXME(eddyb) ignoring `obligations` might cause false positives.
56-
drop(obligations);
54+
let InferOk { value: (), obligations } = eq_result;
55+
// FIXME(eddyb) ignoring `obligations` might cause false positives.
56+
drop(obligations);
5757

58-
trace!(
59-
"invoking predicate_may_hold: param_env={:?}, impl_trait_ref={:?}, impl_ty={:?}",
58+
trace!(
59+
"invoking predicate_may_hold: param_env={:?}, impl_trait_ref={:?}, impl_ty={:?}",
60+
param_env,
61+
impl_trait_ref,
62+
impl_ty
63+
);
64+
let predicates = cx
65+
.tcx
66+
.predicates_of(impl_def_id)
67+
.instantiate(cx.tcx, impl_substs)
68+
.predicates
69+
.into_iter()
70+
.chain(Some(
71+
ty::Binder::dummy(impl_trait_ref)
72+
.to_poly_trait_predicate()
73+
.map_bound(ty::PredicateKind::Trait)
74+
.to_predicate(infcx.tcx),
75+
));
76+
for predicate in predicates {
77+
debug!("testing predicate {:?}", predicate);
78+
let obligation = traits::Obligation::new(
79+
traits::ObligationCause::dummy(),
6080
param_env,
61-
impl_trait_ref,
62-
impl_ty
81+
predicate,
6382
);
64-
let predicates = cx
65-
.tcx
66-
.predicates_of(impl_def_id)
67-
.instantiate(cx.tcx, impl_substs)
68-
.predicates
69-
.into_iter()
70-
.chain(Some(
71-
ty::Binder::dummy(impl_trait_ref)
72-
.to_poly_trait_predicate()
73-
.map_bound(ty::PredicateKind::Trait)
74-
.to_predicate(infcx.tcx),
75-
));
76-
for predicate in predicates {
77-
debug!("testing predicate {:?}", predicate);
78-
let obligation = traits::Obligation::new(
79-
traits::ObligationCause::dummy(),
80-
param_env,
81-
predicate,
82-
);
83-
match infcx.evaluate_obligation(&obligation) {
84-
Ok(eval_result) if eval_result.may_apply() => {}
85-
Err(traits::OverflowError::Canonical) => {}
86-
Err(traits::OverflowError::ErrorReporting) => {}
87-
_ => continue 'blanket_impls,
88-
}
83+
match infcx.evaluate_obligation(&obligation) {
84+
Ok(eval_result) if eval_result.may_apply() => {}
85+
Err(traits::OverflowError::Canonical) => {}
86+
Err(traits::OverflowError::ErrorReporting) => {}
87+
_ => continue 'blanket_impls,
8988
}
90-
debug!(
91-
"get_blanket_impls: found applicable impl for trait_ref={:?}, ty={:?}",
92-
trait_ref, ty
93-
);
89+
}
90+
debug!(
91+
"get_blanket_impls: found applicable impl for trait_ref={:?}, ty={:?}",
92+
trait_ref, ty
93+
);
9494

95-
cx.generated_synthetics.insert((ty.0, trait_def_id));
95+
cx.generated_synthetics.insert((ty.0, trait_def_id));
9696

97-
impls.push(Item {
98-
name: None,
99-
attrs: Default::default(),
100-
visibility: Inherited,
101-
item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
102-
kind: Box::new(ImplItem(Box::new(Impl {
103-
unsafety: hir::Unsafety::Normal,
104-
generics: clean_ty_generics(
105-
cx,
106-
cx.tcx.generics_of(impl_def_id),
107-
cx.tcx.explicit_predicates_of(impl_def_id),
108-
),
109-
// FIXME(eddyb) compute both `trait_` and `for_` from
110-
// the post-inference `trait_ref`, as it's more accurate.
111-
trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, ThinVec::new())),
112-
for_: clean_middle_ty(ty.0, cx, None),
113-
items: cx.tcx
114-
.associated_items(impl_def_id)
115-
.in_definition_order()
116-
.map(|x| clean_middle_assoc_item(x, cx))
117-
.collect::<Vec<_>>(),
118-
polarity: ty::ImplPolarity::Positive,
119-
kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))),
120-
}))),
121-
cfg: None,
122-
});
123-
}
97+
impls.push(Item {
98+
name: None,
99+
attrs: Default::default(),
100+
visibility: Inherited,
101+
item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
102+
kind: Box::new(ImplItem(Box::new(Impl {
103+
unsafety: hir::Unsafety::Normal,
104+
generics: clean_ty_generics(
105+
cx,
106+
cx.tcx.generics_of(impl_def_id),
107+
cx.tcx.explicit_predicates_of(impl_def_id),
108+
),
109+
// FIXME(eddyb) compute both `trait_` and `for_` from
110+
// the post-inference `trait_ref`, as it's more accurate.
111+
trait_: Some(clean_trait_ref_with_bindings(
112+
cx,
113+
trait_ref.0,
114+
ThinVec::new(),
115+
)),
116+
for_: clean_middle_ty(ty.0, cx, None),
117+
items: cx
118+
.tcx
119+
.associated_items(impl_def_id)
120+
.in_definition_order()
121+
.map(|x| clean_middle_assoc_item(x, cx))
122+
.collect::<Vec<_>>(),
123+
polarity: ty::ImplPolarity::Positive,
124+
kind: ImplKind::Blanket(Box::new(clean_middle_ty(
125+
trait_ref.0.self_ty(),
126+
cx,
127+
None,
128+
))),
129+
}))),
130+
cfg: None,
131+
});
124132
}
125-
});
133+
}
126134

127135
impls
128136
}

src/librustdoc/core.rs

+2-15
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub(crate) struct ResolverCaches {
3838
/// Traits in scope for a given module.
3939
/// See `collect_intra_doc_links::traits_implemented_by` for more details.
4040
pub(crate) traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
41-
pub(crate) all_traits: Option<Vec<DefId>>,
4241
pub(crate) all_trait_impls: Option<Vec<DefId>>,
4342
pub(crate) all_macro_rules: FxHashMap<Symbol, Res<NodeId>>,
4443
}
@@ -134,12 +133,6 @@ impl<'tcx> DocContext<'tcx> {
134133
}
135134
}
136135

137-
pub(crate) fn with_all_traits(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
138-
let all_traits = self.resolver_caches.all_traits.take();
139-
f(self, all_traits.as_ref().expect("`all_traits` are already borrowed"));
140-
self.resolver_caches.all_traits = all_traits;
141-
}
142-
143136
pub(crate) fn with_all_trait_impls(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
144137
let all_trait_impls = self.resolver_caches.all_trait_impls.take();
145138
f(self, all_trait_impls.as_ref().expect("`all_trait_impls` are already borrowed"));
@@ -353,14 +346,8 @@ pub(crate) fn run_global_ctxt(
353346
});
354347
rustc_passes::stability::check_unused_or_stable_features(tcx);
355348

356-
let auto_traits = resolver_caches
357-
.all_traits
358-
.as_ref()
359-
.expect("`all_traits` are already borrowed")
360-
.iter()
361-
.copied()
362-
.filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id))
363-
.collect();
349+
let auto_traits =
350+
tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect();
364351
let access_levels = tcx.privacy_access_levels(()).map_id(Into::into);
365352

366353
let mut ctxt = DocContext {

src/librustdoc/passes/collect_intra_doc_links/early.rs

+13-19
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub(crate) fn early_resolve_intra_doc_links(
3737
markdown_links: Default::default(),
3838
doc_link_resolutions: Default::default(),
3939
traits_in_scope: Default::default(),
40-
all_traits: Default::default(),
4140
all_trait_impls: Default::default(),
4241
all_macro_rules: Default::default(),
4342
document_private_items,
@@ -63,7 +62,6 @@ pub(crate) fn early_resolve_intra_doc_links(
6362
markdown_links: Some(link_resolver.markdown_links),
6463
doc_link_resolutions: link_resolver.doc_link_resolutions,
6564
traits_in_scope: link_resolver.traits_in_scope,
66-
all_traits: Some(link_resolver.all_traits),
6765
all_trait_impls: Some(link_resolver.all_trait_impls),
6866
all_macro_rules: link_resolver.all_macro_rules,
6967
}
@@ -81,7 +79,6 @@ struct EarlyDocLinkResolver<'r, 'ra> {
8179
markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
8280
doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
8381
traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
84-
all_traits: Vec<DefId>,
8582
all_trait_impls: Vec<DefId>,
8683
all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
8784
document_private_items: bool,
@@ -122,8 +119,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
122119
loop {
123120
let crates = Vec::from_iter(self.resolver.cstore().crates_untracked());
124121
for &cnum in &crates[start_cnum..] {
125-
let all_traits =
126-
Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum));
127122
let all_trait_impls =
128123
Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
129124
let all_inherent_impls =
@@ -132,20 +127,18 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
132127
self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum),
133128
);
134129

135-
// Querying traits in scope is expensive so we try to prune the impl and traits lists
136-
// using privacy, private traits and impls from other crates are never documented in
130+
// Querying traits in scope is expensive so we try to prune the impl lists using
131+
// privacy, private traits and impls from other crates are never documented in
137132
// the current crate, and links in their doc comments are not resolved.
138-
for &def_id in &all_traits {
139-
if self.resolver.cstore().visibility_untracked(def_id).is_public() {
140-
self.resolve_doc_links_extern_impl(def_id, false);
141-
}
142-
}
143133
for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
144134
if self.resolver.cstore().visibility_untracked(trait_def_id).is_public()
145135
&& simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| {
146136
self.resolver.cstore().visibility_untracked(ty_def_id).is_public()
147137
})
148138
{
139+
if self.visited_mods.insert(trait_def_id) {
140+
self.resolve_doc_links_extern_impl(trait_def_id, false);
141+
}
149142
self.resolve_doc_links_extern_impl(impl_def_id, false);
150143
}
151144
}
@@ -158,7 +151,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
158151
self.resolve_doc_links_extern_impl(impl_def_id, true);
159152
}
160153

161-
self.all_traits.extend(all_traits);
162154
self.all_trait_impls
163155
.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
164156
}
@@ -307,15 +299,20 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
307299
{
308300
if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
309301
let scope_id = match child.res {
310-
Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id),
302+
Res::Def(
303+
DefKind::Variant
304+
| DefKind::AssocTy
305+
| DefKind::AssocFn
306+
| DefKind::AssocConst,
307+
..,
308+
) => self.resolver.parent(def_id),
311309
_ => def_id,
312310
};
313311
self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope
314312
if let Res::Def(DefKind::Mod, ..) = child.res {
315313
self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope
316314
}
317-
// `DefKind::Trait`s are processed in `process_extern_impls`.
318-
if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res {
315+
if let Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, ..) = child.res {
319316
self.process_module_children_or_reexports(def_id);
320317
}
321318
if let Res::Def(DefKind::Struct | DefKind::Union | DefKind::Variant, _) =
@@ -357,9 +354,6 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
357354
self.parent_scope.module = old_module;
358355
} else {
359356
match &item.kind {
360-
ItemKind::Trait(..) => {
361-
self.all_traits.push(self.resolver.local_def_id(item.id).to_def_id());
362-
}
363357
ItemKind::Impl(box ast::Impl { of_trait: Some(..), .. }) => {
364358
self.all_trait_impls.push(self.resolver.local_def_id(item.id).to_def_id());
365359
}

0 commit comments

Comments
 (0)