Skip to content

Commit 346065f

Browse files
committed
rustdoc: fix missing method list for primitive deref target
This change makes it so that local impls count when listing primitives that need retained.
1 parent 082e4ca commit 346065f

File tree

2 files changed

+60
-35
lines changed

2 files changed

+60
-35
lines changed

src/librustdoc/passes/collect_trait_impls.rs

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,50 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
3333
coll.items
3434
};
3535

36-
let mut new_items = Vec::new();
36+
let mut new_items_external = Vec::new();
37+
let mut new_items_local = Vec::new();
3738

3839
// External trait impls.
3940
cx.with_all_trait_impls(|cx, all_trait_impls| {
4041
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls");
4142
for &impl_def_id in all_trait_impls.iter().skip_while(|def_id| def_id.is_local()) {
42-
inline::build_impl(cx, None, impl_def_id, None, &mut new_items);
43+
inline::build_impl(cx, None, impl_def_id, None, &mut new_items_external);
44+
}
45+
});
46+
47+
// Local trait impls.
48+
cx.with_all_trait_impls(|cx, all_trait_impls| {
49+
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
50+
let mut attr_buf = Vec::new();
51+
for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
52+
let mut parent = cx.tcx.parent(impl_def_id);
53+
while let Some(did) = parent {
54+
attr_buf.extend(
55+
cx.tcx
56+
.get_attrs(did)
57+
.iter()
58+
.filter(|attr| attr.has_name(sym::doc))
59+
.filter(|attr| {
60+
if let Some([attr]) = attr.meta_item_list().as_deref() {
61+
attr.has_name(sym::cfg)
62+
} else {
63+
false
64+
}
65+
})
66+
.cloned(),
67+
);
68+
parent = cx.tcx.parent(did);
69+
}
70+
inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items_local);
71+
attr_buf.clear();
4372
}
4473
});
4574

4675
cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
4776
for def_id in PrimitiveType::all_impls(cx.tcx) {
4877
// Try to inline primitive impls from other crates.
4978
if !def_id.is_local() {
50-
inline::build_impl(cx, None, def_id, None, &mut new_items);
79+
inline::build_impl(cx, None, def_id, None, &mut new_items_external);
5180
}
5281
}
5382
for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
@@ -57,7 +86,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
5786
if did.is_local() {
5887
for def_id in prim.impls(cx.tcx) {
5988
let impls = get_auto_trait_and_blanket_impls(cx, def_id);
60-
new_items.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
89+
new_items_external.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
6190
}
6291
}
6392
}
@@ -90,7 +119,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
90119
}
91120

92121
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
93-
for it in &new_items {
122+
for it in new_items_external.iter().chain(new_items_local.iter()) {
94123
if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
95124
if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
96125
&& cleaner.keep_impl(for_, true)
@@ -122,7 +151,8 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
122151
}
123152
}
124153

125-
new_items.retain(|it| {
154+
// Filter out external items that are not needed
155+
new_items_external.retain(|it| {
126156
if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
127157
cleaner.keep_impl(
128158
for_,
@@ -134,37 +164,10 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
134164
}
135165
});
136166

137-
// Local trait impls.
138-
cx.with_all_trait_impls(|cx, all_trait_impls| {
139-
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
140-
let mut attr_buf = Vec::new();
141-
for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
142-
let mut parent = cx.tcx.parent(impl_def_id);
143-
while let Some(did) = parent {
144-
attr_buf.extend(
145-
cx.tcx
146-
.get_attrs(did)
147-
.iter()
148-
.filter(|attr| attr.has_name(sym::doc))
149-
.filter(|attr| {
150-
if let Some([attr]) = attr.meta_item_list().as_deref() {
151-
attr.has_name(sym::cfg)
152-
} else {
153-
false
154-
}
155-
})
156-
.cloned(),
157-
);
158-
parent = cx.tcx.parent(did);
159-
}
160-
inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items);
161-
attr_buf.clear();
162-
}
163-
});
164-
165167
if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
166168
items.extend(synth_impls);
167-
items.extend(new_items);
169+
items.extend(new_items_external);
170+
items.extend(new_items_local);
168171
} else {
169172
panic!("collect-trait-impls can't run");
170173
};

src/test/rustdoc/deref-slice-core.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// https://github.com/rust-lang/rust/issues/95325
2+
//
3+
// Show methods reachable from Deref of primitive.
4+
#![no_std]
5+
6+
use core::ops::Deref;
7+
8+
// @has 'deref_slice_core/struct.MyArray.html'
9+
// @has '-' '//*[@id="deref-methods-%5BT%5D"]' 'Methods from Deref<Target = [T]>'
10+
// @has '-' '//*[@class="impl-items"]//*[@id="method.len"]' 'pub fn len(&self)'
11+
12+
pub struct MyArray<T> {
13+
array: [T; 10],
14+
}
15+
16+
impl<T> Deref for MyArray<T> {
17+
type Target = [T];
18+
19+
fn deref(&self) -> &Self::Target {
20+
&self.array
21+
}
22+
}

0 commit comments

Comments
 (0)