From 415a3ca909084e83441306b21db5232ee8952fc4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Mar 2023 16:10:31 +0100 Subject: [PATCH] Put back `is_derive_trait_collision` check --- .../passes/collect_intra_doc_links.rs | 31 +++++++++++++++++-- .../issue-108653-associated-items-10.rs | 22 +++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 80895893ae86b..0da56e70ed582 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(ns: &PerNS, 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::>() + } 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::>() + } } - - candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::>() } } } diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs new file mode 100644 index 0000000000000..464c5f0d5439c --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs @@ -0,0 +1,22 @@ +// This test ensures that this warning doesn't show up: +// warning: `PartialEq` is both a trait and a derive macro +// --> tests/rustdoc-ui/intra-doc/issue-108653-associated-items-10.rs:1:7 +// | +// 1 | //! [`PartialEq`] +// | ^^^^^^^^^ ambiguous link +// | +// = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default +// help: to link to the trait, prefix with `trait@` +// | +// 1 | //! [`trait@PartialEq`] +// | ++++++ +// help: to link to the derive macro, prefix with `derive@` +// | +// 1 | //! [`derive@PartialEq`] +// | +++++++ + +// check-pass + +#![deny(rustdoc::broken_intra_doc_links)] + +//! [`PartialEq`]