Skip to content

Commit dd78839

Browse files
authored
Rollup merge of #71289 - xliiv:70802-intra-self, r=GuillaumeGomez
Allow using `Self::` in doc Closes #70802
2 parents 215f2d3 + fc0675b commit dd78839

File tree

2 files changed

+138
-4
lines changed

2 files changed

+138
-4
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+50-4
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,43 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
431431

432432
look_for_tests(&cx, &dox, &item, true);
433433

434+
// find item's parent to resolve `Self` in item's docs below
435+
let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| {
436+
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
437+
let item_parent = self.cx.tcx.hir().find(parent_hir);
438+
match item_parent {
439+
Some(hir::Node::Item(hir::Item {
440+
kind:
441+
hir::ItemKind::Impl {
442+
self_ty:
443+
hir::Ty {
444+
kind:
445+
hir::TyKind::Path(hir::QPath::Resolved(
446+
_,
447+
hir::Path { segments, .. },
448+
)),
449+
..
450+
},
451+
..
452+
},
453+
..
454+
})) => segments.first().and_then(|seg| Some(seg.ident.to_string())),
455+
Some(hir::Node::Item(hir::Item {
456+
ident, kind: hir::ItemKind::Enum(..), ..
457+
}))
458+
| Some(hir::Node::Item(hir::Item {
459+
ident, kind: hir::ItemKind::Struct(..), ..
460+
}))
461+
| Some(hir::Node::Item(hir::Item {
462+
ident, kind: hir::ItemKind::Union(..), ..
463+
}))
464+
| Some(hir::Node::Item(hir::Item {
465+
ident, kind: hir::ItemKind::Trait(..), ..
466+
})) => Some(ident.to_string()),
467+
_ => None,
468+
}
469+
});
470+
434471
for (ori_link, link_range) in markdown_links(&dox) {
435472
// Bail early for real links.
436473
if ori_link.contains('/') {
@@ -467,7 +504,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
467504
};
468505
let (res, fragment) = {
469506
let mut kind = None;
470-
let path_str = if let Some(prefix) =
507+
let mut path_str = if let Some(prefix) =
471508
["struct@", "enum@", "type@", "trait@", "union@"]
472509
.iter()
473510
.find(|p| link.starts_with(**p))
@@ -521,6 +558,15 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
521558
let base_node =
522559
if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
523560

561+
let resolved_self;
562+
// replace `Self` with suitable item's parent name
563+
if path_str.starts_with("Self::") {
564+
if let Some(ref name) = parent_name {
565+
resolved_self = format!("{}::{}", name, &path_str[6..]);
566+
path_str = &resolved_self;
567+
}
568+
}
569+
524570
match kind {
525571
Some(ns @ ValueNS) => {
526572
match self.resolve(
@@ -529,7 +575,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
529575
&current_item,
530576
base_node,
531577
&extra_fragment,
532-
None,
578+
Some(&item),
533579
) {
534580
Ok(res) => res,
535581
Err(ErrorKind::ResolutionFailure) => {
@@ -552,7 +598,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
552598
&current_item,
553599
base_node,
554600
&extra_fragment,
555-
None,
601+
Some(&item),
556602
) {
557603
Ok(res) => res,
558604
Err(ErrorKind::ResolutionFailure) => {
@@ -577,7 +623,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
577623
&current_item,
578624
base_node,
579625
&extra_fragment,
580-
None,
626+
Some(&item),
581627
) {
582628
Err(ErrorKind::AnchorFailure(msg)) => {
583629
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);

src/test/rustdoc/intra-link-self.rs

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

3+
// ignore-tidy-linelength
4+
35
// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
46
// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
57

@@ -27,3 +29,89 @@ impl Bar {
2729
unimplemented!()
2830
}
2931
}
32+
33+
pub struct MyStruct {
34+
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#structfield.struct_field'
35+
36+
/// [`struct_field`]
37+
///
38+
/// [`struct_field`]: Self::struct_field
39+
pub struct_field: u8,
40+
}
41+
42+
pub enum MyEnum {
43+
// @has foo/enum.MyEnum.html '//a/@href' '../foo/enum.MyEnum.html#EnumVariant.v'
44+
45+
/// [`EnumVariant`]
46+
///
47+
/// [`EnumVariant`]: Self::EnumVariant
48+
EnumVariant,
49+
}
50+
51+
pub union MyUnion {
52+
// @has foo/union.MyUnion.html '//a/@href' '../foo/union.MyUnion.html#structfield.union_field'
53+
54+
/// [`union_field`]
55+
///
56+
/// [`union_field`]: Self::union_field
57+
pub union_field: f32,
58+
}
59+
60+
pub trait MyTrait {
61+
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedtype.AssoType'
62+
63+
/// [`AssoType`]
64+
///
65+
/// [`AssoType`]: Self::AssoType
66+
type AssoType;
67+
68+
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedconstant.ASSO_CONST'
69+
70+
/// [`ASSO_CONST`]
71+
///
72+
/// [`ASSO_CONST`]: Self::ASSO_CONST
73+
const ASSO_CONST: i32 = 1;
74+
75+
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#method.asso_fn'
76+
77+
/// [`asso_fn`]
78+
///
79+
/// [`asso_fn`]: Self::asso_fn
80+
fn asso_fn() {}
81+
}
82+
83+
impl MyStruct {
84+
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.for_impl'
85+
86+
/// [`for_impl`]
87+
///
88+
/// [`for_impl`]: Self::for_impl
89+
pub fn for_impl() {
90+
unimplemented!()
91+
}
92+
}
93+
94+
impl MyTrait for MyStruct {
95+
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType'
96+
97+
/// [`AssoType`]
98+
///
99+
/// [`AssoType`]: Self::AssoType
100+
type AssoType = u32;
101+
102+
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST'
103+
104+
/// [`ASSO_CONST`]
105+
///
106+
/// [`ASSO_CONST`]: Self::ASSO_CONST
107+
const ASSO_CONST: i32 = 10;
108+
109+
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.asso_fn'
110+
111+
/// [`asso_fn`]
112+
///
113+
/// [`asso_fn`]: Self::asso_fn
114+
fn asso_fn() {
115+
unimplemented!()
116+
}
117+
}

0 commit comments

Comments
 (0)