Skip to content

Commit 06ce97c

Browse files
committed
Use target in Deref method section IDs
There can now be multiple `Deref` method sections, so this adds the target type to the section ID to ensure they are unique.
1 parent fd0ad03 commit 06ce97c

File tree

4 files changed

+61
-47
lines changed

4 files changed

+61
-47
lines changed

src/librustdoc/html/markdown.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,6 @@ fn init_id_map() -> FxHashMap<String, usize> {
13221322
map.insert("trait-implementations".to_owned(), 1);
13231323
map.insert("synthetic-implementations".to_owned(), 1);
13241324
map.insert("blanket-implementations".to_owned(), 1);
1325-
map.insert("deref-methods".to_owned(), 1);
13261325
map
13271326
}
13281327

src/librustdoc/html/render/mod.rs

+51-40
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ crate struct Context<'tcx> {
115115
crate render_redirect_pages: bool,
116116
/// The map used to ensure all generated 'id=' attributes are unique.
117117
id_map: Rc<RefCell<IdMap>>,
118+
/// Tracks section IDs for `Deref` targets so they match in both the main
119+
/// body and the sidebar.
120+
deref_id_map: Rc<RefCell<FxHashMap<DefId, String>>>,
118121
crate shared: Arc<SharedContext<'tcx>>,
119122
all: Rc<RefCell<AllTypes>>,
120123
/// Storage for the errors produced while generating documentation so they
@@ -372,7 +375,6 @@ crate fn initial_ids() -> Vec<String> {
372375
"implementors-list",
373376
"synthetic-implementors-list",
374377
"methods",
375-
"deref-methods",
376378
"implementations",
377379
]
378380
.iter()
@@ -506,6 +508,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
506508
dst,
507509
render_redirect_pages: false,
508510
id_map: Rc::new(RefCell::new(id_map)),
511+
deref_id_map: Rc::new(RefCell::new(FxHashMap::default())),
509512
shared: Arc::new(scx),
510513
all: Rc::new(RefCell::new(AllTypes::new())),
511514
errors: Rc::new(receiver),
@@ -3517,14 +3520,18 @@ fn render_assoc_items(
35173520
RenderMode::Normal
35183521
}
35193522
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
3523+
let id =
3524+
cx.derive_id(small_url_encode(&format!("deref-methods-{:#}", type_.print())));
3525+
cx.deref_id_map.borrow_mut().insert(type_.def_id().unwrap(), id.clone());
35203526
write!(
35213527
w,
3522-
"<h2 id=\"deref-methods\" class=\"small-section-header\">\
3523-
Methods from {}&lt;Target = {}&gt;\
3524-
<a href=\"#deref-methods\" class=\"anchor\"></a>\
3528+
"<h2 id=\"{id}\" class=\"small-section-header\">\
3529+
Methods from {trait_}&lt;Target = {type_}&gt;\
3530+
<a href=\"#{id}\" class=\"anchor\"></a>\
35253531
</h2>",
3526-
trait_.print(),
3527-
type_.print()
3532+
id = id,
3533+
trait_ = trait_.print(),
3534+
type_ = type_.print(),
35283535
);
35293536
RenderMode::ForDeref { mut_: deref_mut_ }
35303537
}
@@ -4175,14 +4182,14 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache:
41754182
);
41764183
}
41774184
match *it.kind {
4178-
clean::StructItem(ref s) => sidebar_struct(buffer, it, s),
4179-
clean::TraitItem(ref t) => sidebar_trait(buffer, it, t),
4180-
clean::PrimitiveItem(_) => sidebar_primitive(buffer, it),
4181-
clean::UnionItem(ref u) => sidebar_union(buffer, it, u),
4182-
clean::EnumItem(ref e) => sidebar_enum(buffer, it, e),
4183-
clean::TypedefItem(_, _) => sidebar_typedef(buffer, it),
4185+
clean::StructItem(ref s) => sidebar_struct(cx, buffer, it, s),
4186+
clean::TraitItem(ref t) => sidebar_trait(cx, buffer, it, t),
4187+
clean::PrimitiveItem(_) => sidebar_primitive(cx, buffer, it),
4188+
clean::UnionItem(ref u) => sidebar_union(cx, buffer, it, u),
4189+
clean::EnumItem(ref e) => sidebar_enum(cx, buffer, it, e),
4190+
clean::TypedefItem(_, _) => sidebar_typedef(cx, buffer, it),
41844191
clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items),
4185-
clean::ForeignTypeItem => sidebar_foreign_type(buffer, it),
4192+
clean::ForeignTypeItem => sidebar_foreign_type(cx, buffer, it),
41864193
_ => (),
41874194
}
41884195

@@ -4283,7 +4290,7 @@ fn small_url_encode(s: &str) -> String {
42834290
.replace("\"", "%22")
42844291
}
42854292

4286-
fn sidebar_assoc_items(it: &clean::Item) -> String {
4293+
fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String {
42874294
let mut out = String::new();
42884295
let c = cache();
42894296
if let Some(v) = c.impls.get(&it.def_id) {
@@ -4313,7 +4320,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
43134320
.filter(|i| i.inner_impl().trait_.is_some())
43144321
.find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
43154322
{
4316-
out.push_str(&sidebar_deref_methods(impl_, v));
4323+
out.push_str(&sidebar_deref_methods(cx, impl_, v));
43174324
}
43184325
let format_impls = |impls: Vec<&Impl>| {
43194326
let mut links = FxHashSet::default();
@@ -4381,7 +4388,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
43814388
out
43824389
}
43834390

4384-
fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
4391+
fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec<Impl>) -> String {
43854392
let mut out = String::new();
43864393
let c = cache();
43874394

@@ -4408,22 +4415,26 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44084415
.and_then(|did| c.impls.get(&did));
44094416
if let Some(impls) = inner_impl {
44104417
debug!("found inner_impl: {:?}", impls);
4411-
out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
4412-
out.push_str(&format!(
4413-
"Methods from {}&lt;Target={}&gt;",
4414-
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print())),
4415-
Escape(&format!("{:#}", real_target.print()))
4416-
));
4417-
out.push_str("</a>");
44184418
let mut used_links = FxHashSet::default();
44194419
let mut ret = impls
44204420
.iter()
44214421
.filter(|i| i.inner_impl().trait_.is_none())
44224422
.flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut))
44234423
.collect::<Vec<_>>();
4424-
// We want links' order to be reproducible so we don't use unstable sort.
4425-
ret.sort();
44264424
if !ret.is_empty() {
4425+
let deref_id_map = cx.deref_id_map.borrow();
4426+
let id = deref_id_map
4427+
.get(&real_target.def_id().unwrap())
4428+
.expect("Deref section without derived id");
4429+
out.push_str(&format!("<a class=\"sidebar-title\" href=\"#{}\">", id));
4430+
out.push_str(&format!(
4431+
"Methods from {}&lt;Target={}&gt;",
4432+
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print())),
4433+
Escape(&format!("{:#}", real_target.print()))
4434+
));
4435+
out.push_str("</a>");
4436+
// We want links' order to be reproducible so we don't use unstable sort.
4437+
ret.sort();
44274438
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret.join("")));
44284439
}
44294440
}
@@ -4443,7 +4454,7 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44434454
return out;
44444455
}
44454456
}
4446-
out.push_str(&sidebar_deref_methods(target_deref_impl, target_impls));
4457+
out.push_str(&sidebar_deref_methods(cx, target_deref_impl, target_impls));
44474458
}
44484459
}
44494460
}
@@ -4452,7 +4463,7 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44524463
out
44534464
}
44544465

4455-
fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
4466+
fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
44564467
let mut sidebar = String::new();
44574468
let fields = get_struct_fields_name(&s.fields);
44584469

@@ -4466,7 +4477,7 @@ fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
44664477
}
44674478
}
44684479

4469-
sidebar.push_str(&sidebar_assoc_items(it));
4480+
sidebar.push_str(&sidebar_assoc_items(cx, it));
44704481

44714482
if !sidebar.is_empty() {
44724483
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4497,7 +4508,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool {
44974508
i.polarity == Some(clean::ImplPolarity::Negative)
44984509
}
44994510

4500-
fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
4511+
fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
45014512
let mut sidebar = String::new();
45024513

45034514
let mut types = t
@@ -4597,7 +4608,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
45974608
}
45984609
}
45994610

4600-
sidebar.push_str(&sidebar_assoc_items(it));
4611+
sidebar.push_str(&sidebar_assoc_items(cx, it));
46014612

46024613
sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
46034614
if t.is_auto {
@@ -4610,16 +4621,16 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
46104621
write!(buf, "<div class=\"block items\">{}</div>", sidebar)
46114622
}
46124623

4613-
fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item) {
4614-
let sidebar = sidebar_assoc_items(it);
4624+
fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
4625+
let sidebar = sidebar_assoc_items(cx, it);
46154626

46164627
if !sidebar.is_empty() {
46174628
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
46184629
}
46194630
}
46204631

4621-
fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) {
4622-
let sidebar = sidebar_assoc_items(it);
4632+
fn sidebar_typedef(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
4633+
let sidebar = sidebar_assoc_items(cx, it);
46234634

46244635
if !sidebar.is_empty() {
46254636
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4641,7 +4652,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String {
46414652
fields.join("")
46424653
}
46434654

4644-
fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
4655+
fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
46454656
let mut sidebar = String::new();
46464657
let fields = get_struct_fields_name(&u.fields);
46474658

@@ -4653,14 +4664,14 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
46534664
));
46544665
}
46554666

4656-
sidebar.push_str(&sidebar_assoc_items(it));
4667+
sidebar.push_str(&sidebar_assoc_items(cx, it));
46574668

46584669
if !sidebar.is_empty() {
46594670
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
46604671
}
46614672
}
46624673

4663-
fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
4674+
fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
46644675
let mut sidebar = String::new();
46654676

46664677
let mut variants = e
@@ -4680,7 +4691,7 @@ fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
46804691
));
46814692
}
46824693

4683-
sidebar.push_str(&sidebar_assoc_items(it));
4694+
sidebar.push_str(&sidebar_assoc_items(cx, it));
46844695

46854696
if !sidebar.is_empty() {
46864697
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4769,8 +4780,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
47694780
}
47704781
}
47714782

4772-
fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
4773-
let sidebar = sidebar_assoc_items(it);
4783+
fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
4784+
let sidebar = sidebar_assoc_items(cx, it);
47744785
if !sidebar.is_empty() {
47754786
write!(buf, "<div class=\"block items\">{}</div>", sidebar);
47764787
}

src/test/rustdoc/deref-recursive.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
// ignore-tidy-linelength
2+
13
// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
24
// levels if needed.
35

46
// @has 'foo/struct.Foo.html'
5-
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = Bar>'
7+
// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
68
// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
7-
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = Baz>'
9+
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
810
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
9-
// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=Bar>'
11+
// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
1012
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
11-
// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=Baz>'
13+
// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
1214
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
1315

1416
#![crate_name = "foo"]

src/test/rustdoc/deref-typedef.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
// ignore-tidy-linelength
2+
13
#![crate_name = "foo"]
24

35
// @has 'foo/struct.Bar.html'
4-
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
6+
// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
57
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
68
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
79
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
810
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
9-
// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooJ>'
11+
// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
1012
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
1113
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
1214
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'

0 commit comments

Comments
 (0)