Skip to content

Commit

Permalink
Make intra-link resolve links for both trait and impl items
Browse files Browse the repository at this point in the history
  • Loading branch information
Tymoteusz Jankowski committed May 19, 2020
1 parent 914adf0 commit fc4c9a6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 26 deletions.
61 changes: 35 additions & 26 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Expand Up @@ -232,37 +232,46 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias,
did,
) => {
// We need item's parent to know if it's
// trait impl or struct/enum/etc impl
let item_parent = item_opt
// Checks if item_name belongs to `impl SomeItem`
let impl_item = cx
.tcx
.inherent_impls(did)
.iter()
.flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
.find(|item| item.ident.name == item_name);
let trait_item = item_opt
.and_then(|item| self.cx.as_local_hir_id(item.def_id))
.and_then(|item_hir| {
// Checks if item_name belongs to `impl SomeTrait for SomeItem`
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
self.cx.tcx.hir().find(parent_hir)
let item_parent = self.cx.tcx.hir().find(parent_hir);
match item_parent {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
..
})) => cx
.tcx
.associated_item_def_ids(self_ty.hir_id.owner)
.iter()
.map(|child| {
let associated_item = cx.tcx.associated_item(*child);
associated_item
})
.find(|child| child.ident.name == item_name),
_ => None,
}
});
let item = match item_parent {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
..
})) => {
// trait impl
cx.tcx
.associated_item_def_ids(self_ty.hir_id.owner)
.iter()
.map(|child| {
let associated_item = cx.tcx.associated_item(*child);
associated_item
})
.find(|child| child.ident.name == item_name)
}
_ => {
// struct/enum/etc. impl
cx.tcx
.inherent_impls(did)
.iter()
.flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
.find(|item| item.ident.name == item_name)
let item = match (impl_item, trait_item) {
(Some(from_impl), Some(_)) => {
// Although it's ambiguous, return impl version for compat. sake.
// To handle that properly resolve() would have to support
// something like
// [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
Some(from_impl)
}
(None, Some(from_trait)) => Some(from_trait),
(Some(from_impl), None) => Some(from_impl),
_ => None,
};

if let Some(item) = item {
Expand Down
19 changes: 19 additions & 0 deletions src/test/rustdoc/issue-72340.rs
@@ -0,0 +1,19 @@
#![crate_name = "foo"]

pub struct Body;

impl Body {
pub fn empty() -> Self {
Body
}

}

impl Default for Body {
// @has foo/struct.Body.html '//a/@href' '../foo/struct.Body.html#method.empty'

/// Returns [`Body::empty()`](Body::empty).
fn default() -> Body {
Body::empty()
}
}

0 comments on commit fc4c9a6

Please sign in to comment.