Rollup merge of #141411 - lolbinarycat:rustdoc-link-proc-macro-91274, r=GuillaumeGomez
rustdoc: linking to a local proc macro no longer warns fixes https://github.com/rust-lang/rust/issues/91274 tried to keep the fix general in case we ever have any other kind of item that occupies multiple namespaces simultaniously.
This commit is contained in:
commit
77c7f76297
4 changed files with 84 additions and 8 deletions
|
|
@ -22,6 +22,7 @@ use rustc_resolve::rustdoc::{
|
|||
MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
|
||||
source_span_for_markdown_range, strip_generics_from_path,
|
||||
};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::lint::Lint;
|
||||
use rustc_span::BytePos;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
|
|
@ -1169,7 +1170,6 @@ impl LinkCollector<'_, '_> {
|
|||
#[allow(rustc::potential_query_instability)]
|
||||
pub(crate) fn resolve_ambiguities(&mut self) {
|
||||
let mut ambiguous_links = mem::take(&mut self.ambiguous_links);
|
||||
|
||||
for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() {
|
||||
for info in info_items {
|
||||
info.resolved.retain(|(res, _)| match res {
|
||||
|
|
@ -2227,15 +2227,35 @@ fn ambiguity_error(
|
|||
emit_error: bool,
|
||||
) -> bool {
|
||||
let mut descrs = FxHashSet::default();
|
||||
let kinds = candidates
|
||||
// proc macro can exist in multiple namespaces at once, so we need to compare `DefIds`
|
||||
// to remove the candidate in the fn namespace.
|
||||
let mut possible_proc_macro_id = None;
|
||||
let is_proc_macro_crate = cx.tcx.crate_types() == &[CrateType::ProcMacro];
|
||||
let mut kinds = candidates
|
||||
.iter()
|
||||
.map(
|
||||
|(res, def_id)| {
|
||||
if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }
|
||||
},
|
||||
)
|
||||
.filter(|res| descrs.insert(res.descr()))
|
||||
.map(|(res, def_id)| {
|
||||
let r =
|
||||
if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res };
|
||||
if is_proc_macro_crate && let Res::Def(DefKind::Macro(_), id) = r {
|
||||
possible_proc_macro_id = Some(id);
|
||||
}
|
||||
r
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// In order to properly dedup proc macros, we have to do it in two passes:
|
||||
// 1. Completing the full traversal to find the possible duplicate in the macro namespace,
|
||||
// 2. Another full traversal to eliminate the candidate in the fn namespace.
|
||||
//
|
||||
// Thus, we have to do an iteration after collection is finished.
|
||||
//
|
||||
// As an optimization, we only deduplicate if we're in a proc-macro crate,
|
||||
// and only if we already found something that looks like a proc macro.
|
||||
if is_proc_macro_crate && let Some(macro_id) = possible_proc_macro_id {
|
||||
kinds.retain(|res| !matches!(res, Res::Def(DefKind::Fn, fn_id) if macro_id == *fn_id));
|
||||
}
|
||||
|
||||
kinds.retain(|res| descrs.insert(res.descr()));
|
||||
|
||||
if descrs.len() == 1 {
|
||||
// There is no way for users to disambiguate at this point, so better return the first
|
||||
// candidate and not show a warning.
|
||||
|
|
|
|||
21
tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs
Normal file
21
tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//@ compile-flags: --crate-type=proc-macro --document-private-items
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
//! Link to [`m`].
|
||||
//~^ ERROR `m` is both a module and a macro
|
||||
|
||||
// test a further edge case related to https://github.com/rust-lang/rust/issues/91274
|
||||
|
||||
// we need to make sure that when there is actually an ambiguity
|
||||
// in a proc-macro crate, we print out a sensible error.
|
||||
// because proc macro crates can't normally export modules,
|
||||
// this can only happen in --document-private-items mode.
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
mod m {}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn m(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
input
|
||||
}
|
||||
22
tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr
Normal file
22
tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
error: `m` is both a module and a macro
|
||||
--> $DIR/bad-link-to-proc-macro.rs:4:15
|
||||
|
|
||||
LL | //! Link to [`m`].
|
||||
| ^ ambiguous link
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/bad-link-to-proc-macro.rs:2:9
|
||||
|
|
||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to link to the module, prefix with `mod@`
|
||||
|
|
||||
LL | //! Link to [`mod@m`].
|
||||
| ++++
|
||||
help: to link to the macro, add an exclamation mark
|
||||
|
|
||||
LL | //! Link to [`m!`].
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
13
tests/rustdoc/intra-doc/link-to-proc-macro.rs
Normal file
13
tests/rustdoc/intra-doc/link-to-proc-macro.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//@ compile-flags: --crate-type=proc-macro
|
||||
//@ has 'foo/index.html' '//a[@href="macro.my_macro.html"]' 'my_macro'
|
||||
//! Link to [`my_macro`].
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// regression test for https://github.com/rust-lang/rust/issues/91274
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
input
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue