about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2023-03-24 16:10:31 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2023-03-24 16:10:31 +0100
commit415a3ca909084e83441306b21db5232ee8952fc4 (patch)
treebbcb5585f9b6fb746efc2b05bdfd9e63e7e79821 /src
parent537fdbd75b13d278645fa223b0e4bee1c0e5dc19 (diff)
downloadrust-415a3ca909084e83441306b21db5232ee8952fc4.tar.gz
rust-415a3ca909084e83441306b21db5232ee8952fc4.zip
Put back `is_derive_trait_collision` check
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 80895893ae8..0da56e70ed5 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -806,6 +806,20 @@ fn trait_impls_for<'a>(
     iter.collect()
 }
 
+/// 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<Result<Vec<(Res, T)>, ResolutionFailure<'_>>>) -> bool {
+    if let (&Ok(ref type_ns), &Ok(ref macro_ns)) = (&ns.type_ns, &ns.macro_ns) {
+        type_ns.iter().any(|(res, _)| matches!(res, Res::Def(DefKind::Trait, _)))
+            && macro_ns
+                .iter()
+                .any(|(res, _)| matches!(res, Res::Def(DefKind::Macro(MacroKind::Derive), _)))
+    } else {
+        false
+    }
+}
+
 impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
         self.resolve_links(item);
@@ -1313,9 +1327,22 @@ impl LinkCollector<'_, '_> {
                         disambiguator,
                         candidates.into_iter().filter_map(|res| res.err()).collect(),
                     );
+                } else if len == 1 {
+                    candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
+                } else {
+                    let has_derive_trait_collision = is_derive_trait_collision(&candidates);
+                    if len == 2 && has_derive_trait_collision {
+                        candidates.type_ns.unwrap()
+                    } else {
+                        // If we're reporting an ambiguity, don't mention the namespaces that failed
+                        let mut candidates = candidates.map(|candidate| candidate.ok());
+                        // If there a collision between a trait and a derive, we ignore the derive.
+                        if has_derive_trait_collision {
+                            candidates.macro_ns = None;
+                        }
+                        candidates.into_iter().filter_map(|res| res).flatten().collect::<Vec<_>>()
+                    }
                 }
-
-                candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
             }
         }
     }