From 80408ef8dc00d4add3a76e27d93cf4ed8b50727e Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Tue, 5 Oct 2021 23:48:41 -0700
Subject: [PATCH 1/2] Add regression test for #7758

---
 tests/ui/doc/doc.rs     | 5 +++++
 tests/ui/doc/doc.stderr | 8 +++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/tests/ui/doc/doc.rs b/tests/ui/doc/doc.rs
index 8b0c0f304fc..342208e52b8 100644
--- a/tests/ui/doc/doc.rs
+++ b/tests/ui/doc/doc.rs
@@ -203,6 +203,11 @@ fn issue_2343() {}
 /// __|_ _|__||_|
 fn pulldown_cmark_crash() {}
 
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
 // issue #7033 - generic_const_exprs ICE
 struct S<T, const N: usize>
 where [(); N.checked_next_power_of_two().unwrap()]: {
diff --git a/tests/ui/doc/doc.stderr b/tests/ui/doc/doc.stderr
index 7eab8a85f09..161407a6a72 100644
--- a/tests/ui/doc/doc.stderr
+++ b/tests/ui/doc/doc.stderr
@@ -186,5 +186,11 @@ error: you should put `mycrate::Collection` between ticks in the documentation
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 31 previous errors
+error: you should put `text][path::to::item` between ticks in the documentation
+  --> $DIR/doc.rs:208:12
+   |
+LL | /// [plain text][path::to::item]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 32 previous errors
 

From 2a8d7bd0dd69ab1fe2a2af0f2984959f62b5631c Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Wed, 6 Oct 2021 00:01:40 -0700
Subject: [PATCH 2/2] Handle intra-doc links in doc_markdown

---
 clippy_lints/src/doc.rs | 14 +++++++++++++-
 tests/ui/doc/doc.stderr |  8 +-------
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index 55d2265125e..75873fd7c1c 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -406,6 +406,15 @@ struct DocHeaders {
 }
 
 fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
+    use pulldown_cmark::{BrokenLink, CowStr, Options};
+    /// We don't want the parser to choke on intra doc links. Since we don't
+    /// actually care about rendering them, just pretend that all broken links are
+    /// point to a fake address.
+    #[allow(clippy::unnecessary_wraps)] // we're following a type signature
+    fn fake_broken_link_callback<'a>(_: BrokenLink<'_>) -> Option<(CowStr<'a>, CowStr<'a>)> {
+        Some(("fake".into(), "fake".into()))
+    }
+
     let mut doc = String::new();
     let mut spans = vec![];
 
@@ -440,7 +449,10 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
         };
     }
 
-    let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter();
+    let mut cb = fake_broken_link_callback;
+
+    let parser =
+        pulldown_cmark::Parser::new_with_broken_link_callback(&doc, Options::empty(), Some(&mut cb)).into_offset_iter();
     // Iterate over all `Events` and combine consecutive events into one
     let events = parser.coalesce(|previous, current| {
         use pulldown_cmark::Event::Text;
diff --git a/tests/ui/doc/doc.stderr b/tests/ui/doc/doc.stderr
index 161407a6a72..7eab8a85f09 100644
--- a/tests/ui/doc/doc.stderr
+++ b/tests/ui/doc/doc.stderr
@@ -186,11 +186,5 @@ error: you should put `mycrate::Collection` between ticks in the documentation
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
 
-error: you should put `text][path::to::item` between ticks in the documentation
-  --> $DIR/doc.rs:208:12
-   |
-LL | /// [plain text][path::to::item]
-   |            ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 32 previous errors
+error: aborting due to 31 previous errors