about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKyle Lin <minecraft.kyle.train@gmail.com>2023-07-01 00:55:37 +0800
committerKyle Lin <minecraft.kyle.train@gmail.com>2023-08-18 15:19:17 +0800
commit5ce6cc7df3175519219c091059dd663313438c97 (patch)
treefb8423c2d39df2cf1a21cf1526a287e73279c1ae
parent46df95817d2f9700f0c5a69ea8b05b1c83d9ee35 (diff)
downloadrust-5ce6cc7df3175519219c091059dd663313438c97.tar.gz
rust-5ce6cc7df3175519219c091059dd663313438c97.zip
Still resolving rustdoc resolution panicking
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs69
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs76
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.fixed6
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.rs6
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.rs1
-rw-r--r--tests/rustdoc/description.rs2
-rw-r--r--tests/rustdoc/intra-doc/basic.rs2
-rw-r--r--tests/rustdoc/intra-doc/generic-params.rs1
-rw-r--r--tests/rustdoc/intra-doc/issue-108459.rs1
10 files changed, 90 insertions, 80 deletions
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 083d16d3b04..f7275bed59c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -410,8 +410,10 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
     while let Some(event) = event_iter.next() {
         match event {
             Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-                if let Some(display_text) = collect_link_data(&mut event_iter) {
-                    links.push(display_text);
+                if matches!(link_type, LinkType::Inline | LinkType::ReferenceUnknown | LinkType::Reference) {
+                    if let Some(display_text) = collect_link_data(&mut event_iter) {
+                        links.push(display_text);
+                    }
                 }
 
                 links.push(preprocess_link(&dest));
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 0a0ffcb5b1e..4c40363ac1d 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1038,6 +1038,7 @@ impl LinkCollector<'_, '_> {
             // resolutions are cached, for other links we want to report an error every
             // time so they are not cached.
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+            false,
         )?;
 
         self.resolve_display_text(
@@ -1232,6 +1233,9 @@ impl LinkCollector<'_, '_> {
         // If errors are cached then they are only reported on first occurrence
         // which we want in some cases but not in others.
         cache_errors: bool,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Option<(Res, Option<UrlFragment>)> {
         if let Some(res) = self.visited_links.get(&key) {
             if res.is_some() || cache_errors {
@@ -1239,7 +1243,7 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
+        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
 
         // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
         // However I'm not sure how to check that across crates.
@@ -1290,6 +1294,9 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Vec<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
@@ -1319,7 +1326,9 @@ impl LinkCollector<'_, '_> {
                                 }
                             }
                         }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        if !recoverable {
+                            resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        }
                         return vec![];
                     }
                 }
@@ -1356,13 +1365,15 @@ impl LinkCollector<'_, '_> {
                     .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
 
                 if len == 0 {
-                    resolution_failure(
-                        self,
-                        diag,
-                        path_str,
-                        disambiguator,
-                        candidates.into_iter().filter_map(|res| res.err()).collect(),
-                    );
+                    if !recoverable {
+                        resolution_failure(
+                            self,
+                            diag,
+                            path_str,
+                            disambiguator,
+                            candidates.into_iter().filter_map(|res| res.err()).collect(),
+                        );
+                    }
                     return vec![];
                 } else if len == 1 {
                     candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
@@ -1396,43 +1407,8 @@ impl LinkCollector<'_, '_> {
         ori_link: &MarkdownLink,
         diag_info: &DiagnosticInfo<'_>,
     ) {
-        // Check if explicit resolution's path is same as resolution of original link's display text path, e.g.
-        //
-        // LinkType::Inline:
-        //
-        // [target](target)
-        // [`target`](target)
-        // [target](path::to::target)
-        // [`target`](path::to::target)
-        // [path::to::target](target)
-        // [`path::to::target`](target)
-        // [path::to::target](path::to::target)
-        // [`path::to::target`](path::to::target)
-        //
-        // LinkType::ReferenceUnknown
-        //
-        // [target][target]
-        // [`target`][target]
-        // [target][path::to::target]
-        // [`target`][path::to::target]
-        // [path::to::target][target]
-        // [`path::to::target`][target]
-        // [path::to::target][path::to::target]
-        // [`path::to::target`][path::to::target]
-        //
-        // LinkType::Reference
-        //
-        // [target][target]
-        // [`target`][target]
-        // [target][path::to::target]
-        // [`target`][path::to::target]
-        // [path::to::target][target]
-        // [`path::to::target`][target]
-        // [path::to::target][path::to::target]
-        // [`path::to::target`][path::to::target]
-        //
-        // [target]: target // or [target]: path::to::target
-        // [path::to::target]: path::to::target // or [path::to::target]: target
+        // Check if explicit resolution's path is same as resolution of original link's display text path, see
+        // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
         //
         // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
         // into explicit path.
@@ -1471,6 +1447,7 @@ impl LinkCollector<'_, '_> {
                 display_res_info,
                 diag_info.clone(), // this struct should really be Copy, but Range is not :(
                 false,
+                true,
             );
         }
     }
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 722088eb79a..da8a73be60b 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -32,6 +32,13 @@ 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;
+    }
+
     check_redundant_explicit_link(cx, item, hir_id, &doc);
 }
 
@@ -57,33 +64,52 @@ fn check_redundant_explicit_link<'md>(
 
     while let Some((event, link_range)) = offset_iter.next() {
         match event {
-            Event::Start(Tag::Link(link_type, dest, _)) => match link_type {
-                LinkType::Inline | LinkType::ReferenceUnknown => {
-                    check_inline_or_reference_unknown_redundancy(
-                        cx,
-                        item,
-                        hir_id,
-                        doc,
-                        resolutions,
-                        link_range,
-                        dest.to_string(),
-                        collect_link_data(&mut offset_iter),
-                        if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') },
-                    );
+            Event::Start(Tag::Link(link_type, dest, _)) => {
+                let link_data = collect_link_data(&mut offset_iter);
+
+                let explicit_link = dest.to_string();
+                let display_link = link_data.resolvable_link.clone()?;
+                let explicit_len = explicit_link.len();
+                let display_len = display_link.len();
+
+                if explicit_len == display_len && explicit_link != display_link {
+                    // Skips if they possibly have no relativity.
+                    continue;
                 }
-                LinkType::Reference => {
-                    check_reference_redundancy(
-                        cx,
-                        item,
-                        hir_id,
-                        doc,
-                        resolutions,
-                        link_range,
-                        &dest,
-                        collect_link_data(&mut offset_iter),
-                    );
+
+                if (explicit_len >= display_len
+                    && &explicit_link[(explicit_len - display_len)..] == display_link)
+                    || (display_len >= explicit_len
+                        && &display_link[(display_len - explicit_len)..] == explicit_link) {
+                    match link_type {
+                        LinkType::Inline | LinkType::ReferenceUnknown => {
+                            check_inline_or_reference_unknown_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                dest.to_string(),
+                                link_data,
+                                if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') },
+                            );
+                        }
+                        LinkType::Reference => {
+                            check_reference_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                &dest,
+                                link_data,
+                            );
+                        }
+                        _ => {}
+                    }
                 }
-                _ => {}
             },
             _ => {}
         }
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
index 4745da879a3..900234e31e9 100644
--- a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
@@ -42,7 +42,7 @@ pub fn dummy_target() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`]
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target] TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`] TEXT
@@ -91,7 +91,7 @@ pub fn should_not_warn_inline() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`]
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target] TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`] TEXT
@@ -140,7 +140,7 @@ pub fn should_not_warn_reference_unknown() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`]
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target] TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`] TEXT
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
index 7dd8eba5a5e..13feb85e051 100644
--- a/tests/rustdoc-ui/lints/redundant_explicit_links.rs
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
@@ -42,7 +42,7 @@ pub fn dummy_target() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`](std::primitive::usize)
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target](dummy_target) TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`](dummy_target) TEXT
@@ -91,7 +91,7 @@ pub fn should_not_warn_inline() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`][std::primitive::usize]
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target][dummy_target] TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`][dummy_target] TEXT
@@ -140,7 +140,7 @@ pub fn should_not_warn_reference_unknown() {}
 //~^ ERROR redundant explicit link target
 /// [`std::primitive::usize`][std::primitive::usize]
 //~^ ERROR redundant explicit link target
-/// 
+///
 /// [dummy_target][dummy_target] TEXT
 //~^ ERROR redundant explicit link target
 /// [`dummy_target`][dummy_target] TEXT
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index e99cd1f3d58..e960e9f59e9 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -1,6 +1,7 @@
 #![deny(rustdoc::unescaped_backticks)]
 #![allow(rustdoc::broken_intra_doc_links)]
 #![allow(rustdoc::invalid_html_tags)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 ///
 pub fn empty() {}
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
index 43cd59ebd09..918ccd63968 100644
--- a/tests/rustdoc/description.rs
+++ b/tests/rustdoc/description.rs
@@ -26,5 +26,5 @@ pub fn foo_fn() {}
 // @has 'foo/fn.bar_fn.html' '//meta[@name="description"]/@content' \
 //   'Description with intra-doc link to foo_fn and [nonexistent_item] and foo_fn.'
 #[allow(rustdoc::broken_intra_doc_links)]
-/// Description with intra-doc link to [foo_fn] and [nonexistent_item] and [foo_fn](self::foo_fn).
+/// Description with intra-doc link to [foo_fn] and [nonexistent_item] and [foo_fn].
 pub fn bar_fn() {}
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
index 96e21137b2d..c88a7887f11 100644
--- a/tests/rustdoc/intra-doc/basic.rs
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -1,3 +1,5 @@
+#![allow(rustdoc::redundant_explicit_links)]
+
 // @has basic/index.html
 // @has - '//a/@href' 'struct.ThisType.html'
 // @has - '//a/@title' 'struct basic::ThisType'
diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs
index fbc9fc6a9bc..359f775f97f 100644
--- a/tests/rustdoc/intra-doc/generic-params.rs
+++ b/tests/rustdoc/intra-doc/generic-params.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
index eb1c7a05e54..b8cd478b4df 100644
--- a/tests/rustdoc/intra-doc/issue-108459.rs
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -1,4 +1,5 @@
 #![deny(rustdoc::broken_intra_doc_links)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 pub struct S;
 pub mod char {}