diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 9ef0b501c08..2f7ffce017b 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -382,7 +382,6 @@ impl<'a, I: Iterator- >> Iterator for LinkReplacer<'a, I> {
Some(Event::Code(text)) => {
trace!("saw code {}", text);
if let Some(link) = self.shortcut_link {
- trace!("original text was {}", link.original_text);
// NOTE: this only replaces if the code block is the *entire* text.
// If only part of the link has code highlighting, the disambiguator will not be removed.
// e.g. [fn@`f`]
@@ -391,8 +390,11 @@ impl<'a, I: Iterator
- >> Iterator for LinkReplacer<'a, I> {
// So we could never be sure we weren't replacing too much:
// [fn@my_`f`unc] is treated the same as [my_func()] in that pass.
//
- // NOTE: &[1..len() - 1] is to strip the backticks
- if **text == link.original_text[1..link.original_text.len() - 1] {
+ // NOTE: .get(1..len() - 1) is to strip the backticks
+ if let Some(link) = self.links.iter().find(|l| {
+ l.href == link.href
+ && Some(&**text) == l.original_text.get(1..l.original_text.len() - 1)
+ }) {
debug!("replacing {} with {}", text, link.new_text);
*text = CowStr::Borrowed(&link.new_text);
}
@@ -403,9 +405,12 @@ impl<'a, I: Iterator
- >> Iterator for LinkReplacer<'a, I> {
Some(Event::Text(text)) => {
trace!("saw text {}", text);
if let Some(link) = self.shortcut_link {
- trace!("original text was {}", link.original_text);
// NOTE: same limitations as `Event::Code`
- if **text == *link.original_text {
+ if let Some(link) = self
+ .links
+ .iter()
+ .find(|l| l.href == link.href && **text == *l.original_text)
+ {
debug!("replacing {} with {}", text, link.new_text);
*text = CowStr::Borrowed(&link.new_text);
}
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
new file mode 100644
index 00000000000..eb1c7a05e54
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -0,0 +1,37 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub struct S;
+pub mod char {}
+
+// Ensure this doesn't ICE due to trying to slice off non-existent backticks from "S"
+
+/// See [S] and [`S`]
+pub struct MyStruct1;
+
+// Ensure that link texts are replaced correctly even if there are multiple links with
+// the same target but different text
+
+/// See also [crate::char] and [mod@char] and [prim@char]
+// @has issue_108459/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char'
+// @has - '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct2;
+
+/// See also [mod@char] and [prim@char] and [crate::char]
+// @has issue_108459/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char'
+// @has - '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct3;
+
+// Ensure that links are correct even if there are multiple links with the same text but
+// different targets
+
+/// See also [char][mod@char] and [char][prim@char]
+// @has issue_108459/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct4;
+
+/// See also [char][prim@char] and [char][crate::char]
+// @has issue_108459/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct5;
diff --git a/tests/rustdoc/intra-doc/prim-precedence.rs b/tests/rustdoc/intra-doc/prim-precedence.rs
index 25625b95277..c5a64e42a01 100644
--- a/tests/rustdoc/intra-doc/prim-precedence.rs
+++ b/tests/rustdoc/intra-doc/prim-precedence.rs
@@ -12,5 +12,5 @@ pub struct MyString;
/// See also [crate::char] and [mod@char]
// @has prim_precedence/struct.MyString2.html '//*[@href="char/index.html"]' 'crate::char'
-// @has - '//*[@href="char/index.html"]' 'mod@char'
+// @has - '//*[@href="char/index.html"]' 'char'
pub struct MyString2;