Skip to content

Commit 03c763e

Browse files
committed
manually crafted revert of PR rust-lang#80653, to address issue rust-lang#82465.
(update: placated tidy)
1 parent 18587b1 commit 03c763e

File tree

7 files changed

+46
-176
lines changed

7 files changed

+46
-176
lines changed

src/librustdoc/html/render/context.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::rc::Rc;
66
use std::sync::mpsc::{channel, Receiver};
77

88
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9-
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
9+
use rustc_hir::def_id::LOCAL_CRATE;
1010
use rustc_middle::ty::TyCtxt;
1111
use rustc_session::Session;
1212
use rustc_span::edition::Edition;
@@ -50,9 +50,6 @@ crate struct Context<'tcx> {
5050
pub(super) render_redirect_pages: bool,
5151
/// The map used to ensure all generated 'id=' attributes are unique.
5252
pub(super) id_map: RefCell<IdMap>,
53-
/// Tracks section IDs for `Deref` targets so they match in both the main
54-
/// body and the sidebar.
55-
pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>,
5653
/// Shared mutable state.
5754
///
5855
/// Issue for improving the situation: [#82381][]
@@ -73,7 +70,7 @@ crate struct Context<'tcx> {
7370

7471
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
7572
#[cfg(target_arch = "x86_64")]
76-
rustc_data_structures::static_assert_size!(Context<'_>, 152);
73+
rustc_data_structures::static_assert_size!(Context<'_>, 112);
7774

7875
/// Shared mutable state used in [`Context`] and elsewhere.
7976
crate struct SharedContext<'tcx> {
@@ -470,7 +467,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
470467
dst,
471468
render_redirect_pages: false,
472469
id_map: RefCell::new(id_map),
473-
deref_id_map: RefCell::new(FxHashMap::default()),
474470
shared: Rc::new(scx),
475471
cache: Rc::new(cache),
476472
};
@@ -488,7 +484,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
488484
dst: self.dst.clone(),
489485
render_redirect_pages: self.render_redirect_pages,
490486
id_map: RefCell::new(IdMap::new()),
491-
deref_id_map: RefCell::new(FxHashMap::default()),
492487
shared: Rc::clone(&self.shared),
493488
cache: Rc::clone(&self.cache),
494489
}

src/librustdoc/html/render/mod.rs

+6-20
Original file line numberDiff line numberDiff line change
@@ -1034,17 +1034,12 @@ fn render_assoc_items(
10341034
RenderMode::Normal
10351035
}
10361036
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
1037-
let id =
1038-
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
1039-
debug!("Adding {} to deref id map", type_.print(cx));
1040-
cx.deref_id_map.borrow_mut().insert(type_.def_id_full(cache).unwrap(), id.clone());
10411037
write!(
10421038
w,
1043-
"<h2 id=\"{id}\" class=\"small-section-header\">\
1039+
"<h2 id=\"deref-methods\" class=\"small-section-header\">\
10441040
Methods from {trait_}&lt;Target = {type_}&gt;\
1045-
<a href=\"#{id}\" class=\"anchor\"></a>\
1041+
<a href=\"#deref-methods\" class=\"anchor\"></a>\
10461042
</h2>",
1047-
id = id,
10481043
trait_ = trait_.print(cx),
10491044
type_ = type_.print(cx),
10501045
);
@@ -1069,6 +1064,9 @@ fn render_assoc_items(
10691064
);
10701065
}
10711066
}
1067+
if let AssocItemRender::DerefFor { .. } = what {
1068+
return;
1069+
}
10721070
if !traits.is_empty() {
10731071
let deref_impl = traits
10741072
.iter()
@@ -1079,13 +1077,6 @@ fn render_assoc_items(
10791077
.any(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_mut_trait_did);
10801078
render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
10811079
}
1082-
1083-
// If we were already one level into rendering deref methods, we don't want to render
1084-
// anything after recursing into any further deref methods above.
1085-
if let AssocItemRender::DerefFor { .. } = what {
1086-
return;
1087-
}
1088-
10891080
let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
10901081
traits.iter().partition(|t| t.inner_impl().synthetic);
10911082
let (blanket_impl, concrete): (Vec<&&Impl>, _) =
@@ -1967,14 +1958,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
19671958
.flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c))
19681959
.collect::<Vec<_>>();
19691960
if !ret.is_empty() {
1970-
let deref_id_map = cx.deref_id_map.borrow();
1971-
let id = deref_id_map
1972-
.get(&real_target.def_id_full(c).unwrap())
1973-
.expect("Deref section without derived id");
19741961
write!(
19751962
out,
1976-
"<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
1977-
id,
1963+
"<a class=\"sidebar-title\" href=\"#deref-methods\">Methods from {}&lt;Target={}&gt;</a>",
19781964
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))),
19791965
Escape(&format!("{:#}", real_target.print(cx))),
19801966
);

src/librustdoc/passes/collect_trait_impls.rs

+36-66
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::clean::*;
33
use crate::core::DocContext;
44
use crate::fold::DocFolder;
55

6-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6+
use rustc_data_structures::fx::FxHashSet;
77
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
88
use rustc_middle::ty::DefIdTree;
99
use rustc_span::symbol::sym;
@@ -53,6 +53,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
5353
}
5454
}
5555

56+
let mut cleaner = BadImplStripper { prims, items: crate_items };
57+
58+
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
59+
for it in &new_items {
60+
if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
61+
if cleaner.keep_impl(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() {
62+
let target = items
63+
.iter()
64+
.find_map(|item| match *item.kind {
65+
TypedefItem(ref t, true) => Some(&t.type_),
66+
_ => None,
67+
})
68+
.expect("Deref impl without Target type");
69+
70+
if let Some(prim) = target.primitive_type() {
71+
cleaner.prims.insert(prim);
72+
} else if let Some(did) = target.def_id() {
73+
cleaner.items.insert(did);
74+
}
75+
}
76+
}
77+
}
78+
79+
new_items.retain(|it| {
80+
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
81+
cleaner.keep_impl(for_)
82+
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
83+
|| blanket_impl.is_some()
84+
} else {
85+
true
86+
}
87+
});
88+
5689
// `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
5790
// doesn't work with it anyway, so pull them from the HIR map instead
5891
let mut extra_attrs = Vec::new();
@@ -84,73 +117,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
84117
}
85118
}
86119

87-
let mut cleaner = BadImplStripper { prims, items: crate_items };
88-
89-
let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default();
90-
// Gather all type to `Deref` target edges.
91-
for it in &new_items {
92-
if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
93-
if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
94-
let target = items.iter().find_map(|item| match *item.kind {
95-
TypedefItem(ref t, true) => Some(&t.type_),
96-
_ => None,
97-
});
98-
if let (Some(for_did), Some(target)) = (for_.def_id(), target) {
99-
type_did_to_deref_target.insert(for_did, target);
100-
}
101-
}
102-
}
103-
}
104-
// Follow all `Deref` targets of included items and recursively add them as valid
105-
fn add_deref_target(
106-
map: &FxHashMap<DefId, &Type>,
107-
cleaner: &mut BadImplStripper,
108-
type_did: &DefId,
109-
) {
110-
if let Some(target) = map.get(type_did) {
111-
debug!("add_deref_target: type {:?}, target {:?}", type_did, target);
112-
if let Some(target_prim) = target.primitive_type() {
113-
cleaner.prims.insert(target_prim);
114-
} else if let Some(target_did) = target.def_id() {
115-
// `impl Deref<Target = S> for S`
116-
if target_did == *type_did {
117-
// Avoid infinite cycles
118-
return;
119-
}
120-
cleaner.items.insert(target_did);
121-
add_deref_target(map, cleaner, &target_did);
122-
}
123-
}
124-
}
125-
for type_did in type_did_to_deref_target.keys() {
126-
// Since only the `DefId` portion of the `Type` instances is known to be same for both the
127-
// `Deref` target type and the impl for type positions, this map of types is keyed by
128-
// `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
129-
if cleaner.keep_impl_with_def_id(type_did) {
130-
add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did);
131-
}
132-
}
133-
134120
let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind {
135121
items
136122
} else {
137123
panic!("collect-trait-impls can't run");
138124
};
139125

140126
items.extend(synth_impls);
141-
for it in new_items.drain(..) {
142-
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
143-
if !(cleaner.keep_impl(for_)
144-
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
145-
|| blanket_impl.is_some())
146-
{
147-
continue;
148-
}
149-
}
150-
151-
items.push(it);
152-
}
153-
127+
items.extend(new_items);
154128
krate
155129
}
156130

@@ -204,13 +178,9 @@ impl BadImplStripper {
204178
} else if let Some(prim) = ty.primitive_type() {
205179
self.prims.contains(&prim)
206180
} else if let Some(did) = ty.def_id() {
207-
self.keep_impl_with_def_id(&did)
181+
self.items.contains(&did)
208182
} else {
209183
false
210184
}
211185
}
212-
213-
fn keep_impl_with_def_id(&self, did: &DefId) -> bool {
214-
self.items.contains(did)
215-
}
216186
}

src/test/rustdoc-ui/deref-recursive-cycle.rs

-17
This file was deleted.

src/test/rustdoc/deref-recursive-pathbuf.rs

-24
This file was deleted.

src/test/rustdoc/deref-recursive.rs

-40
This file was deleted.

src/test/rustdoc/deref-typedef.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![crate_name = "foo"]
22

33
// @has 'foo/struct.Bar.html'
4-
// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
4+
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
55
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
66
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
77
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
88
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
9-
// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
9+
// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
1010
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
1111
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
1212
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'

0 commit comments

Comments
 (0)