summaryrefslogtreecommitdiffstats
path: root/tests/rustdoc-ui/intra-doc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /tests/rustdoc-ui/intra-doc
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/rustdoc-ui/intra-doc')
-rw-r--r--tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.rs22
-rw-r--r--tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr14
-rw-r--r--tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs3
-rw-r--r--tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.rs4
-rw-r--r--tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr15
-rw-r--r--tests/rustdoc-ui/intra-doc/inline-external-enum.rs8
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.rs6
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr55
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs10
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr21
-rw-r--r--tests/rustdoc-ui/intra-doc/pub-export-lint.rs5
-rw-r--r--tests/rustdoc-ui/intra-doc/pub-export-lint.stderr15
-rw-r--r--tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.rs20
-rw-r--r--tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.stderr63
-rw-r--r--tests/rustdoc-ui/intra-doc/reference-links.rs6
-rw-r--r--tests/rustdoc-ui/intra-doc/reference-links.stderr14
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.rs140
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.stderr272
18 files changed, 682 insertions, 11 deletions
diff --git a/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.rs b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.rs
new file mode 100644
index 000000000..0976515f4
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.rs
@@ -0,0 +1,22 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+#[derive(Debug)]
+/// Link to [`S::fmt`]
+//~^ ERROR unresolved link
+pub struct S;
+
+pub mod inner {
+ use std::fmt::Debug;
+ use super::S;
+
+ /// Link to [`S::fmt`]
+ pub fn f() {}
+}
+
+pub mod ambiguous {
+ use std::fmt::{Display, Debug};
+ use super::S;
+
+ /// Link to [`S::fmt`]
+ pub fn f() {}
+}
diff --git a/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr
new file mode 100644
index 000000000..04594ad41
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `S::fmt`
+ --> $DIR/assoc-item-not-in-scope.rs:4:15
+ |
+LL | /// Link to [`S::fmt`]
+ | ^^^^^^ the struct `S` has no field or associated item named `fmt`
+ |
+note: the lint level is defined here
+ --> $DIR/assoc-item-not-in-scope.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs b/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs
deleted file mode 100644
index 6c48f5aa0..000000000
--- a/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub enum O {
- L = -1,
-}
diff --git a/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.rs b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.rs
new file mode 100644
index 000000000..09da124b1
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.rs
@@ -0,0 +1,4 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [v2] //~ ERROR
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr
new file mode 100644
index 000000000..3e08354a6
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `v2`
+ --> $DIR/deny-intra-link-resolution-failure.rs:3:6
+ |
+LL | /// [v2]
+ | ^^ no item named `v2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+note: the lint level is defined here
+ --> $DIR/deny-intra-link-resolution-failure.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/inline-external-enum.rs b/tests/rustdoc-ui/intra-doc/inline-external-enum.rs
deleted file mode 100644
index 363dd7f64..000000000
--- a/tests/rustdoc-ui/intra-doc/inline-external-enum.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-// aux-build: inner-crate-enum.rs
-// compile-flags:-Z unstable-options --output-format json
-
-#[doc(inline)]
-pub extern crate inner_crate_enum;
-
-fn main() {}
diff --git a/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.rs b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.rs
new file mode 100644
index 000000000..ef9c56f75
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.rs
@@ -0,0 +1,6 @@
+// this test used to ICE
+#![deny(rustdoc::broken_intra_doc_links)]
+//! [Clone ()]. //~ ERROR unresolved
+//! [Clone !]. //~ ERROR incompatible
+//! [`Clone ()`]. //~ ERROR unresolved
+//! [`Clone !`]. //~ ERROR incompatible
diff --git a/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr
new file mode 100644
index 000000000..6c834fd0a
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr
@@ -0,0 +1,55 @@
+error: unresolved link to `Clone`
+ --> $DIR/issue-110495-suffix-with-space.rs:3:6
+ |
+LL | //! [Clone ()].
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+note: the lint level is defined here
+ --> $DIR/issue-110495-suffix-with-space.rs:2:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the trait, prefix with `trait@`
+ |
+LL - //! [Clone ()].
+LL + //! [trait@Clone ].
+ |
+
+error: incompatible link kind for `Clone`
+ --> $DIR/issue-110495-suffix-with-space.rs:4:6
+ |
+LL | //! [Clone !].
+ | ^^^^^^^ this link resolved to a derive macro, which is not a macro
+ |
+help: to link to the derive macro, prefix with `derive@`
+ |
+LL - //! [Clone !].
+LL + //! [derive@Clone ].
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/issue-110495-suffix-with-space.rs:5:7
+ |
+LL | //! [`Clone ()`].
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - //! [`Clone ()`].
+LL + //! [`trait@Clone `].
+ |
+
+error: incompatible link kind for `Clone`
+ --> $DIR/issue-110495-suffix-with-space.rs:6:7
+ |
+LL | //! [`Clone !`].
+ | ^^^^^^^ this link resolved to a derive macro, which is not a macro
+ |
+help: to link to the derive macro, prefix with `derive@`
+ |
+LL - //! [`Clone !`].
+LL + //! [`derive@Clone `].
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
new file mode 100644
index 000000000..4e74278dc
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
@@ -0,0 +1,10 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111189>.
+// This test ensures that it doesn't crash.
+
+#![deny(warnings)]
+
+/// #[rustfmt::skip]
+//~^ ERROR unresolved link to `rustfmt::skip`
+/// #[clippy::whatever]
+//~^ ERROR unresolved link to `clippy::whatever`
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
new file mode 100644
index 000000000..edd3dfa7d
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
@@ -0,0 +1,21 @@
+error: unresolved link to `rustfmt::skip`
+ --> $DIR/issue-111189-resolution-ice.rs:6:7
+ |
+LL | /// #[rustfmt::skip]
+ | ^^^^^^^^^^^^^ no item named `rustfmt` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/issue-111189-resolution-ice.rs:4:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+
+error: unresolved link to `clippy::whatever`
+ --> $DIR/issue-111189-resolution-ice.rs:8:7
+ |
+LL | /// #[clippy::whatever]
+ | ^^^^^^^^^^^^^^^^ no item named `clippy` in scope
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/pub-export-lint.rs b/tests/rustdoc-ui/intra-doc/pub-export-lint.rs
new file mode 100644
index 000000000..f2e66b77b
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/pub-export-lint.rs
@@ -0,0 +1,5 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [aloha]
+//~^ ERROR unresolved link to `aloha`
+pub use std::task::RawWakerVTable;
diff --git a/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr b/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr
new file mode 100644
index 000000000..81ef79961
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `aloha`
+ --> $DIR/pub-export-lint.rs:3:6
+ |
+LL | /// [aloha]
+ | ^^^^^ no item named `aloha` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+note: the lint level is defined here
+ --> $DIR/pub-export-lint.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.rs b/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.rs
new file mode 100644
index 000000000..71bd2c522
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.rs
@@ -0,0 +1,20 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// Links to [a] [link][a]
+/// And also a [third link][a]
+/// And also a [reference link][b]
+///
+/// Other links to the same target should still emit error: [ref] //~ERROR unresolved link to `ref`
+/// Duplicate [ref] //~ERROR unresolved link to `ref`
+///
+/// Other links to other targets should still emit error: [ref2] //~ERROR unresolved link to `ref2`
+/// Duplicate [ref2] //~ERROR unresolved link to `ref2`
+///
+/// [a]: ref
+//~^ ERROR unresolved link to `ref`
+/// [b]: ref2
+//~^ ERROR unresolved link to
+
+/// [ref][]
+//~^ ERROR unresolved link
+pub fn f() {}
diff --git a/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.stderr b/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.stderr
new file mode 100644
index 000000000..2ab67090f
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/reference-link-reports-error-once.stderr
@@ -0,0 +1,63 @@
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:13:10
+ |
+LL | /// [a]: ref
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+note: the lint level is defined here
+ --> $DIR/reference-link-reports-error-once.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:15:10
+ |
+LL | /// [b]: ref2
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:7:62
+ |
+LL | /// Other links to the same target should still emit error: [ref]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:8:16
+ |
+LL | /// Duplicate [ref]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:10:60
+ |
+LL | /// Other links to other targets should still emit error: [ref2]
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:11:16
+ |
+LL | /// Duplicate [ref2]
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:18:6
+ |
+LL | /// [ref][]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/reference-links.rs b/tests/rustdoc-ui/intra-doc/reference-links.rs
new file mode 100644
index 000000000..e81e03446
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/reference-links.rs
@@ -0,0 +1,6 @@
+// Test that errors point to the reference, not to the title text.
+#![deny(rustdoc::broken_intra_doc_links)]
+//! Links to [a] [link][a]
+//!
+//! [a]: std::process::Comman
+//~^ ERROR unresolved
diff --git a/tests/rustdoc-ui/intra-doc/reference-links.stderr b/tests/rustdoc-ui/intra-doc/reference-links.stderr
new file mode 100644
index 000000000..c98a2fd7c
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/reference-links.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `std::process::Comman`
+ --> $DIR/reference-links.rs:5:10
+ |
+LL | //! [a]: std::process::Comman
+ | ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process`
+ |
+note: the lint level is defined here
+ --> $DIR/reference-links.rs:2:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.rs b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
new file mode 100644
index 000000000..ca18842fb
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
@@ -0,0 +1,140 @@
+// Many examples are from
+// https://github.com/rust-lang/rust/issues/110111#issuecomment-1517800781
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! This test case is closely linked to [raphlinus/pulldown-cmark#441], getting offsets of
+//! link components. In particular, pulldown-cmark doesn't provide the offsets of the contents
+//! of a link.
+//!
+//! To work around this, rustdoc parses parts of a link definition itself. This is basically a
+//! test suite for that link syntax parser.
+//!
+//! [raphlinus/pulldown-cmark#441]: https://github.com/raphlinus/pulldown-cmark/issues/441
+
+use std::clone::Clone;
+
+// Basic version //
+
+/// [`struct@Clone`] //~ERROR link
+pub struct LinkToCloneWithBackquotes;
+
+/// [```struct@Clone```] //~ERROR link
+pub struct LinkToCloneWithMultipleBackquotes;
+
+/// [ ` struct@Clone ` ] //~ERROR link
+pub struct LinkToCloneWithSpacesAndBackquotes;
+
+/// [ `Clone ()` ] //~ERROR link
+pub struct LinkToCloneWithSpacesBackquotesAndParens;
+
+/// [`Clone ()` ] //~ERROR link
+pub struct LinkToCloneWithSpacesEndBackquotesAndParens;
+
+/// [ `Clone ()`] //~ERROR link
+pub struct LinkToCloneWithSpacesStartBackquotesAndParens;
+
+/// [```Clone ()```] //~ERROR link
+pub struct LinkToCloneWithMultipleBackquotesAndParens;
+
+/// [```Clone \(\)```] // not URL-shaped enough
+pub struct LinkToCloneWithMultipleBackquotesAndEscapedParens;
+
+/// [ ``` Clone () ``` ] //~ERROR link
+pub struct LinkToCloneWithSpacesMultipleBackquotesAndParens;
+
+/// [ x \] ] // not URL-shaped enough
+pub struct LinkWithEscapedCloseBrace;
+
+/// [ x \[ ] // not URL-shaped enough
+pub struct LinkWithEscapedOpenBrace;
+
+/// [ x \( ] // not URL-shaped enough
+pub struct LinkWithEscapedCloseParen;
+
+/// [ x \) ] // not URL-shaped enough
+pub struct LinkWithEscapedOpenParen;
+
+/// [ Clone \(\) ] // not URL-shaped enough
+pub struct LinkWithEscapedParens;
+
+// [][] version //
+
+/// [x][ struct@Clone] //~ERROR link
+pub struct XLinkToCloneWithStartSpace;
+
+/// [x][struct@Clone ] //~ERROR link
+pub struct XLinkToCloneWithEndSpace;
+
+/// [x][Clone\(\)] not URL-shaped enough
+pub struct XLinkToCloneWithEscapedParens;
+
+/// [x][`Clone`] not URL-shaped enough
+pub struct XLinkToCloneWithBackquotes;
+
+/// [x][Clone()] //~ERROR link
+pub struct XLinkToCloneWithUnescapedParens;
+
+/// [x][Clone ()] //~ERROR link
+pub struct XLinkToCloneWithUnescapedParensAndDoubleSpace;
+
+/// [x][Clone [] //~ERROR unresolved link to `x`
+pub struct XLinkToCloneWithUnmatchedOpenParenAndDoubleSpace;
+
+/// [x][Clone \[] // not URL-shaped enough
+pub struct XLinkToCloneWithUnmatchedEscapedOpenParenAndDoubleSpace;
+
+/// [x][Clone \]] // not URL-shaped enough
+pub struct XLinkToCloneWithUnmatchedEscapedCloseParenAndDoubleSpace;
+
+// []() version //
+
+/// [w]( struct@Clone) //~ERROR link
+pub struct WLinkToCloneWithStartSpace;
+
+/// [w](struct@Clone ) //~ERROR link
+pub struct WLinkToCloneWithEndSpace;
+
+/// [w](Clone\(\)) //~ERROR link
+pub struct WLinkToCloneWithEscapedParens;
+
+/// [w](`Clone`) not URL-shaped enough
+pub struct WLinkToCloneWithBackquotes;
+
+/// [w](Clone()) //~ERROR link
+pub struct WLinkToCloneWithUnescapedParens;
+
+/// [w](Clone ()) not URL-shaped enough
+pub struct WLinkToCloneWithUnescapedParensAndDoubleSpace;
+
+/// [w](Clone () //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedOpenParenAndDoubleSpace;
+
+/// [w](Clone \() //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedEscapedOpenParenAndDoubleSpace;
+
+/// [w](Clone \)) //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedEscapedCloseParenAndDoubleSpace;
+
+// References
+
+/// The [cln][] link here is going to be unresolved, because `Clone()` gets rejected //~ERROR link
+/// in Markdown for not being URL-shaped enough.
+///
+/// [cln]: Clone() //~ERROR link
+pub struct LinkToCloneWithParensInReference;
+
+/// The [cln][] link here is going to be unresolved, because `struct@Clone` gets //~ERROR link
+/// rejected in Markdown for not being URL-shaped enough.
+///
+/// [cln]: struct@Clone //~ERROR link
+pub struct LinkToCloneWithWrongPrefix;
+
+/// The [cln][] link here will produce a plain text suggestion //~ERROR link
+///
+/// [cln]: Clone\(\)
+pub struct LinkToCloneWithEscapedParensInReference;
+
+/// The [cln][] link here will produce a plain text suggestion //~ERROR link
+///
+/// [cln]: struct\@Clone
+pub struct LinkToCloneWithEscapedAtsInReference;
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
new file mode 100644
index 000000000..f50feb57f
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
@@ -0,0 +1,272 @@
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:18:7
+ |
+LL | /// [`struct@Clone`]
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+note: the lint level is defined here
+ --> $DIR/weird-syntax.rs:3:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [`trait@Clone`]
+ | ~~~~~~
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:21:9
+ |
+LL | /// [```struct@Clone```]
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [```trait@Clone```]
+ | ~~~~~~
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:24:11
+ |
+LL | /// [ ` struct@Clone ` ]
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [ ` trait@Clone ` ]
+ | ~~~~~~
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:27:9
+ |
+LL | /// [ `Clone ()` ]
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [ `Clone ()` ]
+LL + /// [ `trait@Clone ` ]
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:30:7
+ |
+LL | /// [`Clone ()` ]
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [`Clone ()` ]
+LL + /// [`trait@Clone ` ]
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:33:9
+ |
+LL | /// [ `Clone ()`]
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [ `Clone ()`]
+LL + /// [ `trait@Clone `]
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:36:9
+ |
+LL | /// [```Clone ()```]
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [```Clone ()```]
+LL + /// [```trait@Clone ```]
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:42:13
+ |
+LL | /// [ ``` Clone () ``` ]
+ | ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [ ``` Clone () ``` ]
+LL + /// [ ``` trait@Clone ``` ]
+ |
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:62:10
+ |
+LL | /// [x][ struct@Clone]
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [x][ trait@Clone]
+ | ~~~~~~
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:65:9
+ |
+LL | /// [x][struct@Clone ]
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [x][trait@Clone ]
+ | ~~~~~~
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:74:9
+ |
+LL | /// [x][Clone()]
+ | ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [x][Clone()]
+LL + /// [x][trait@Clone]
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:77:9
+ |
+LL | /// [x][Clone ()]
+ | ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [x][Clone ()]
+LL + /// [x][trait@Clone ]
+ |
+
+error: unresolved link to `x`
+ --> $DIR/weird-syntax.rs:80:6
+ |
+LL | /// [x][Clone []
+ | ^ no item named `x` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:91:10
+ |
+LL | /// [w]( struct@Clone)
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [w]( trait@Clone)
+ | ~~~~~~
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:94:9
+ |
+LL | /// [w](struct@Clone )
+ | ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// [w](trait@Clone )
+ | ~~~~~~
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:97:9
+ |
+LL | /// [w](Clone\(\))
+ | ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [w](Clone\(\))
+LL + /// [w](trait@Clone)
+ |
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:103:9
+ |
+LL | /// [w](Clone())
+ | ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL - /// [w](Clone())
+LL + /// [w](trait@Clone)
+ |
+
+error: unresolved link to `w`
+ --> $DIR/weird-syntax.rs:109:6
+ |
+LL | /// [w](Clone ()
+ | ^ no item named `w` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `w`
+ --> $DIR/weird-syntax.rs:112:6
+ |
+LL | /// [w](Clone \()
+ | ^ no item named `w` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `w`
+ --> $DIR/weird-syntax.rs:115:6
+ |
+LL | /// [w](Clone \))
+ | ^ no item named `w` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+ --> $DIR/weird-syntax.rs:120:10
+ |
+LL | /// The [cln][] link here is going to be unresolved, because `Clone()` gets rejected
+ | ^^^ no item named `cln` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+ --> $DIR/weird-syntax.rs:123:6
+ |
+LL | /// [cln]: Clone()
+ | ^^^ no item named `cln` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+ --> $DIR/weird-syntax.rs:126:10
+ |
+LL | /// The [cln][] link here is going to be unresolved, because `struct@Clone` gets
+ | ^^^ no item named `cln` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+ --> $DIR/weird-syntax.rs:129:6
+ |
+LL | /// [cln]: struct@Clone
+ | ^^^ no item named `cln` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Clone`
+ --> $DIR/weird-syntax.rs:132:9
+ |
+LL | /// The [cln][] link here will produce a plain text suggestion
+ | ^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+ |
+ = help: to link to the trait, prefix with `trait@`: trait@Clone
+
+error: incompatible link kind for `Clone`
+ --> $DIR/weird-syntax.rs:137:9
+ |
+LL | /// The [cln][] link here will produce a plain text suggestion
+ | ^^^^^ this link resolved to a trait, which is not a struct
+ |
+ = help: to link to the trait, prefix with `trait@`: trait@Clone
+
+error: aborting due to 26 previous errors
+