about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbohan <bohan-zhang@foxmail.com>2024-02-07 15:43:19 +0800
committerbohan <bohan-zhang@foxmail.com>2024-02-07 15:43:32 +0800
commit0a50dba50bedd24377bd1066da3b4b7066df4d28 (patch)
treeaf86510ec54eed8c46a39fd81b0fa1dd71a39b48
parentd4f6f9ee6a3b24f2cb97b1a5b82963609b93aa33 (diff)
downloadrust-0a50dba50bedd24377bd1066da3b4b7066df4d28.tar.gz
rust-0a50dba50bedd24377bd1066da3b4b7066df4d28.zip
docs: also check the inline stmt during redundant link check
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs49
-rw-r--r--tests/rustdoc-ui/issues/issue-120444-1.rs17
-rw-r--r--tests/rustdoc-ui/issues/issue-120444-1.stderr22
-rw-r--r--tests/rustdoc-ui/issues/issue-120444-2.rs17
-rw-r--r--tests/rustdoc-ui/issues/issue-120444-2.stderr22
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
+