about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs29
-rw-r--r--src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs5
-rw-r--r--src/test/rustdoc/intra-link-proc-macro.rs6
3 files changed, 36 insertions, 4 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 4514a616bd8..ab4dbb87425 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -12,6 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty;
 use rustc_resolve::ParentScope;
 use rustc_session::lint;
+use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
@@ -407,6 +408,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     }
 }
 
+/// Check for resolve collisions between a trait and its derive
+///
+/// These are common and we should just resolve to the trait in that case
+fn is_derive_trait_collision<T>(ns: &PerNS<Option<(Res, T)>>) -> bool {
+    if let PerNS {
+        type_ns: Some((Res::Def(DefKind::Trait, _), _)),
+        macro_ns: Some((Res::Def(DefKind::Macro(MacroKind::Derive), _), _)),
+        ..
+    } = *ns
+    {
+        true
+    } else {
+        false
+    }
+}
+
 impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
     fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let item_hir_id = if item.is_mod() {
@@ -650,7 +667,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                     }
                     None => {
                         // Try everything!
-                        let candidates = PerNS {
+                        let mut candidates = PerNS {
                             macro_ns: self
                                 .macro_resolve(path_str, base_node)
                                 .map(|res| (res, extra_fragment.clone())),
@@ -705,10 +722,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                             continue;
                         }
 
-                        let is_unambiguous = candidates.clone().present_items().count() == 1;
-                        if is_unambiguous {
+                        let len = candidates.clone().present_items().count();
+
+                        if len == 1 {
                             candidates.present_items().next().unwrap()
+                        } else if len == 2 && is_derive_trait_collision(&candidates) {
+                            candidates.type_ns.unwrap()
                         } else {
+                            if is_derive_trait_collision(&candidates) {
+                                candidates.macro_ns = None;
+                            }
                             ambiguity_error(
                                 cx,
                                 &item,
diff --git a/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs b/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs
index fee92ff2e0d..04a431d9902 100644
--- a/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs
+++ b/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs
@@ -19,6 +19,11 @@ pub fn b_derive(input: TokenStream) -> TokenStream {
     input
 }
 
+#[proc_macro_derive(DeriveTrait)]
+pub fn trait_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
 #[proc_macro_attribute]
 pub fn attr_a(input: TokenStream, _args: TokenStream) -> TokenStream {
     input
diff --git a/src/test/rustdoc/intra-link-proc-macro.rs b/src/test/rustdoc/intra-link-proc-macro.rs
index 78ef91ab682..405e08d4c07 100644
--- a/src/test/rustdoc/intra-link-proc-macro.rs
+++ b/src/test/rustdoc/intra-link-proc-macro.rs
@@ -11,7 +11,11 @@ use intra_link_proc_macro_macro::{DeriveB, attr_b};
 
 // @has - '//a/@href' '../intra_link_proc_macro/derive.DeriveA.html'
 // @has - '//a/@href' '../intra_link_proc_macro/attr.attr_a.html'
+// @has - '//a/@href' '../intra_link_proc_macro/trait.DeriveTrait.html'
 // @has - '//a/@href' '../intra_link_proc_macro_macro/derive.DeriveB.html'
 // @has - '//a/@href' '../intra_link_proc_macro_macro/attr.attr_b.html'
-/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b]
+/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait]
 pub struct Foo;
+
+// this should not cause ambiguity errors
+pub trait DeriveTrait {}