diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-02-08 09:06:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-08 09:06:35 +0100 |
| commit | fec32358b559eee00e5ce41ca16b6bf5ba6764f8 (patch) | |
| tree | a9cec652be5f3cf02d2ec87c3f8b4693e8a85350 | |
| parent | 65aa9eae7308e282c5a4d2d98dc64f5db70a52df (diff) | |
| parent | 0a50dba50bedd24377bd1066da3b4b7066df4d28 (diff) | |
| download | rust-fec32358b559eee00e5ce41ca16b6bf5ba6764f8.tar.gz rust-fec32358b559eee00e5ce41ca16b6bf5ba6764f8.zip | |
Rollup merge of #120702 - bvanjoi:fix-120444, r=notriddle
docs: also check the inline stmt during redundant link check Fixes #120444 This issue was brought about by querying `root::webdavfs::A`, a key that doesn't exist in `doc_link_resolutions`. To avoid a panic, I've altered the gating mechanism to allow this lint pass to be skipped. I'm not certain if this is the best solution. An alternative approach might be to leverage other info from the name resolutions instead of `doc_link_resolutions`. After all, all we need is to get the resolution from a combination of `(module, name)`. However, I believe they would yield the same outcome, both skipping this lint.
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/passes/lint/redundant_explicit_links.rs | 49 | ||||
| -rw-r--r-- | tests/rustdoc-ui/issues/issue-120444-1.rs | 17 | ||||
| -rw-r--r-- | tests/rustdoc-ui/issues/issue-120444-1.stderr | 22 | ||||
| -rw-r--r-- | tests/rustdoc-ui/issues/issue-120444-2.rs | 17 | ||||
| -rw-r--r-- | tests/rustdoc-ui/issues/issue-120444-2.stderr | 22 |
6 files changed, 111 insertions, 18 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3bac71dbc24..b8e0d75e7dc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -82,7 +82,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| { - // First, lower everything other than imports. + // First, lower everything other than glob imports. if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { return Vec::new(); } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 9069098bf1a..f7bc5464707 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -7,6 +7,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; +use rustc_span::def_id::DefId; use rustc_span::Symbol; use crate::clean::utils::find_nearest_parent_module; @@ -33,17 +34,22 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } - if item.link_names(&cx.cache).is_empty() { - // If there's no link names in this item, - // then we skip resolution querying to - // avoid from panicking. - return; + if let Some(item_id) = item.def_id() { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); } + if let Some(item_id) = item.inline_stmt_id { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + } +} - let Some(item_id) = item.def_id() else { - return; - }; - let Some(local_item_id) = item_id.as_local() else { +fn check_redundant_explicit_link_for_did<'md>( + cx: &DocContext<'_>, + item: &Item, + did: DefId, + hir_id: HirId, + doc: &'md str, +) { + let Some(local_item_id) = did.as_local() else { return; }; @@ -53,12 +59,26 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } let is_private = !cx.render_options.document_private - && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id); + && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did); if is_private { return; } - check_redundant_explicit_link(cx, item, hir_id, &doc); + let module_id = match cx.tcx.def_kind(did) { + DefKind::Mod if item.inner_docs(cx.tcx) => did, + _ => find_nearest_parent_module(cx.tcx, did).unwrap(), + }; + + let Some(resolutions) = + cx.tcx.resolutions(()).doc_link_resolutions.get(&module_id.expect_local()) + else { + // If there's no resolutions in this module, + // then we skip resolution querying to + // avoid from panicking. + return; + }; + + check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); } fn check_redundant_explicit_link<'md>( @@ -66,6 +86,7 @@ fn check_redundant_explicit_link<'md>( item: &Item, hir_id: HirId, doc: &'md str, + resolutions: &DocLinkResMap, ) -> Option<()> { let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); let mut offset_iter = Parser::new_with_broken_link_callback( @@ -74,12 +95,6 @@ fn check_redundant_explicit_link<'md>( Some(&mut broken_line_callback), ) .into_offset_iter(); - let item_id = item.def_id()?; - let module_id = match cx.tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(cx.tcx) => item_id, - _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(), - }; - let resolutions = cx.tcx.doc_link_resolutions(module_id); while let Some((event, link_range)) = offset_iter.next() { match event { diff --git a/tests/rustdoc-ui/issues/issue-120444-1.rs b/tests/rustdoc-ui/issues/issue-120444-1.rs new file mode 100644 index 00000000000..25d0111a7b7 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-1.stderr b/tests/rustdoc-ui/issues/issue-120444-1.stderr new file mode 100644 index 00000000000..7bc56b4263f --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-1.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-1.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/issues/issue-120444-2.rs b/tests/rustdoc-ui/issues/issue-120444-2.rs new file mode 100644 index 00000000000..d13bf884624 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +pub mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-2.stderr b/tests/rustdoc-ui/issues/issue-120444-2.stderr new file mode 100644 index 00000000000..310bf08e2b5 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-2.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-2.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + |
