summaryrefslogtreecommitdiffstats
path: root/src/test/rustdoc-ui/intra-doc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/rustdoc-ui/intra-doc')
-rw-r--r--src/test/rustdoc-ui/intra-doc/alias-ice.rs6
-rw-r--r--src/test/rustdoc-ui/intra-doc/alias-ice.stderr14
-rw-r--r--src/test/rustdoc-ui/intra-doc/ambiguity.rs40
-rw-r--r--src/test/rustdoc-ui/intra-doc/ambiguity.stderr101
-rw-r--r--src/test/rustdoc-ui/intra-doc/anchors.rs39
-rw-r--r--src/test/rustdoc-ui/intra-doc/anchors.stderr32
-rw-r--r--src/test/rustdoc-ui/intra-doc/assoc-field.rs26
-rw-r--r--src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs19
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs18
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs11
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs4
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/pointer-reexports-allowed.rs4
-rw-r--r--src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs20
-rw-r--r--src/test/rustdoc-ui/intra-doc/broken-reexport.rs8
-rw-r--r--src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs5
-rw-r--r--src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr14
-rw-r--r--src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs81
-rw-r--r--src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr153
-rw-r--r--src/test/rustdoc-ui/intra-doc/double-anchor.rs7
-rw-r--r--src/test/rustdoc-ui/intra-doc/double-anchor.stderr12
-rw-r--r--src/test/rustdoc-ui/intra-doc/email-address-localhost.rs7
-rw-r--r--src/test/rustdoc-ui/intra-doc/errors.rs105
-rw-r--r--src/test/rustdoc-ui/intra-doc/errors.stderr157
-rw-r--r--src/test/rustdoc-ui/intra-doc/extern-crate-load.rs26
-rw-r--r--src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs6
-rw-r--r--src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr23
-rw-r--r--src/test/rustdoc-ui/intra-doc/field-ice.rs11
-rw-r--r--src/test/rustdoc-ui/intra-doc/field-ice.stderr18
-rw-r--r--src/test/rustdoc-ui/intra-doc/global-path.rs8
-rw-r--r--src/test/rustdoc-ui/intra-doc/global-path.stderr10
-rw-r--r--src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs25
-rw-r--r--src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr69
-rw-r--r--src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs3
-rw-r--r--src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr18
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules-error.rs26
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr23
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules.rs24
-rw-r--r--src/test/rustdoc-ui/intra-doc/malformed-generics.rs19
-rw-r--r--src/test/rustdoc-ui/intra-doc/malformed-generics.stderr102
-rw-r--r--src/test/rustdoc-ui/intra-doc/non-path-primitives.rs34
-rw-r--r--src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr63
-rw-r--r--src/test/rustdoc-ui/intra-doc/pointer-reexports-allowed.rs4
-rw-r--r--src/test/rustdoc-ui/intra-doc/prim-conflict.rs30
-rw-r--r--src/test/rustdoc-ui/intra-doc/prim-conflict.stderr59
-rw-r--r--src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs6
-rw-r--r--src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr11
-rw-r--r--src/test/rustdoc-ui/intra-doc/private.private.stderr27
-rw-r--r--src/test/rustdoc-ui/intra-doc/private.public.stderr27
-rw-r--r--src/test/rustdoc-ui/intra-doc/private.rs18
-rw-r--r--src/test/rustdoc-ui/intra-doc/span-ice-55723.rs13
-rw-r--r--src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr15
-rw-r--r--src/test/rustdoc-ui/intra-doc/through-proc-macro.rs18
-rw-r--r--src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr15
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs14
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr56
-rw-r--r--src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs6
-rw-r--r--src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr13
-rw-r--r--src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs5
-rw-r--r--src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr15
-rw-r--r--src/test/rustdoc-ui/intra-doc/warning-crlf.rs26
-rw-r--r--src/test/rustdoc-ui/intra-doc/warning-crlf.stderr35
-rw-r--r--src/test/rustdoc-ui/intra-doc/warning.rs84
-rw-r--r--src/test/rustdoc-ui/intra-doc/warning.stderr175
67 files changed, 2067 insertions, 0 deletions
diff --git a/src/test/rustdoc-ui/intra-doc/alias-ice.rs b/src/test/rustdoc-ui/intra-doc/alias-ice.rs
new file mode 100644
index 000000000..51922caeb
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/alias-ice.rs
@@ -0,0 +1,6 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub type TypeAlias = usize;
+
+/// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+pub fn some_public_item() {}
diff --git a/src/test/rustdoc-ui/intra-doc/alias-ice.stderr b/src/test/rustdoc-ui/intra-doc/alias-ice.stderr
new file mode 100644
index 000000000..5e7ffeeb8
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/alias-ice.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `TypeAlias::hoge`
+ --> $DIR/alias-ice.rs:5:30
+ |
+LL | /// [broken cross-reference](TypeAlias::hoge)
+ | ^^^^^^^^^^^^^^^ the type alias `TypeAlias` has no associated item named `hoge`
+ |
+note: the lint level is defined here
+ --> $DIR/alias-ice.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/ambiguity.rs b/src/test/rustdoc-ui/intra-doc/ambiguity.rs
new file mode 100644
index 000000000..1f3dc722e
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/ambiguity.rs
@@ -0,0 +1,40 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+
+pub fn ambiguous() {}
+
+pub struct ambiguous {}
+
+#[macro_export]
+macro_rules! multi_conflict { () => {} }
+
+#[allow(non_camel_case_types)]
+pub struct multi_conflict {}
+
+pub fn multi_conflict() {}
+
+pub mod type_and_value {}
+
+pub const type_and_value: i32 = 0;
+
+pub mod foo {
+ pub enum bar {}
+
+ pub fn bar() {}
+}
+
+/// [`ambiguous`] is ambiguous. //~ERROR `ambiguous`
+///
+/// [ambiguous] is ambiguous. //~ERROR ambiguous
+///
+/// [`multi_conflict`] is a three-way conflict. //~ERROR `multi_conflict`
+///
+/// Ambiguous [type_and_value]. //~ERROR type_and_value
+///
+/// Ambiguous non-implied shortcut link [`foo::bar`]. //~ERROR `foo::bar`
+pub struct Docs {}
+
+/// [true] //~ ERROR `true` is both a module and a builtin type
+/// [primitive@true]
+pub mod r#true {}
diff --git a/src/test/rustdoc-ui/intra-doc/ambiguity.stderr b/src/test/rustdoc-ui/intra-doc/ambiguity.stderr
new file mode 100644
index 000000000..7974796e4
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/ambiguity.stderr
@@ -0,0 +1,101 @@
+error: `true` is both a module and a builtin type
+ --> $DIR/ambiguity.rs:38:6
+ |
+LL | /// [true]
+ | ^^^^ ambiguous link
+ |
+note: the lint level is defined here
+ --> $DIR/ambiguity.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the module, prefix with `mod@`
+ |
+LL | /// [mod@true]
+ | ++++
+help: to link to the builtin type, prefix with `prim@`
+ |
+LL | /// [prim@true]
+ | +++++
+
+error: `ambiguous` is both a struct and a function
+ --> $DIR/ambiguity.rs:27:7
+ |
+LL | /// [`ambiguous`] is ambiguous.
+ | ^^^^^^^^^ ambiguous link
+ |
+help: to link to the struct, prefix with `struct@`
+ |
+LL | /// [`struct@ambiguous`] is ambiguous.
+ | +++++++
+help: to link to the function, add parentheses
+ |
+LL | /// [`ambiguous()`] is ambiguous.
+ | ++
+
+error: `ambiguous` is both a struct and a function
+ --> $DIR/ambiguity.rs:29:6
+ |
+LL | /// [ambiguous] is ambiguous.
+ | ^^^^^^^^^ ambiguous link
+ |
+help: to link to the struct, prefix with `struct@`
+ |
+LL | /// [struct@ambiguous] is ambiguous.
+ | +++++++
+help: to link to the function, add parentheses
+ |
+LL | /// [ambiguous()] is ambiguous.
+ | ++
+
+error: `multi_conflict` is a struct, a function, and a macro
+ --> $DIR/ambiguity.rs:31:7
+ |
+LL | /// [`multi_conflict`] is a three-way conflict.
+ | ^^^^^^^^^^^^^^ ambiguous link
+ |
+help: to link to the struct, prefix with `struct@`
+ |
+LL | /// [`struct@multi_conflict`] is a three-way conflict.
+ | +++++++
+help: to link to the function, add parentheses
+ |
+LL | /// [`multi_conflict()`] is a three-way conflict.
+ | ++
+help: to link to the macro, add an exclamation mark
+ |
+LL | /// [`multi_conflict!`] is a three-way conflict.
+ | +
+
+error: `type_and_value` is both a module and a constant
+ --> $DIR/ambiguity.rs:33:16
+ |
+LL | /// Ambiguous [type_and_value].
+ | ^^^^^^^^^^^^^^ ambiguous link
+ |
+help: to link to the module, prefix with `mod@`
+ |
+LL | /// Ambiguous [mod@type_and_value].
+ | ++++
+help: to link to the constant, prefix with `const@`
+ |
+LL | /// Ambiguous [const@type_and_value].
+ | ++++++
+
+error: `foo::bar` is both an enum and a function
+ --> $DIR/ambiguity.rs:35:43
+ |
+LL | /// Ambiguous non-implied shortcut link [`foo::bar`].
+ | ^^^^^^^^ ambiguous link
+ |
+help: to link to the enum, prefix with `enum@`
+ |
+LL | /// Ambiguous non-implied shortcut link [`enum@foo::bar`].
+ | +++++
+help: to link to the function, add parentheses
+ |
+LL | /// Ambiguous non-implied shortcut link [`foo::bar()`].
+ | ++
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/anchors.rs b/src/test/rustdoc-ui/intra-doc/anchors.rs
new file mode 100644
index 000000000..34e11c7c7
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/anchors.rs
@@ -0,0 +1,39 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// A few tests on anchors.
+
+/// Hello people.
+///
+/// You can anchors? Here's one!
+///
+/// # hola
+///
+/// Isn't it amazing?
+pub struct Foo {
+ pub f: u8,
+}
+
+pub enum Enum {
+ A,
+ B,
+}
+
+/// Have you heard about stuff?
+///
+/// Like [Foo#hola].
+///
+/// Or maybe [Foo::f#hola].
+//~^ ERROR `Foo::f#hola` contains an anchor
+pub fn foo() {}
+
+/// Empty.
+///
+/// Another anchor error: [hello#people#!].
+//~^ ERROR `hello#people#!` contains multiple anchors
+pub fn bar() {}
+
+/// Empty?
+///
+/// Damn enum's variants: [Enum::A#whatever].
+//~^ ERROR `Enum::A#whatever` contains an anchor
+pub fn enum_link() {}
diff --git a/src/test/rustdoc-ui/intra-doc/anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr
new file mode 100644
index 000000000..0d226b277
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr
@@ -0,0 +1,32 @@
+error: `Foo::f#hola` contains an anchor, but links to fields are already anchored
+ --> $DIR/anchors.rs:25:15
+ |
+LL | /// Or maybe [Foo::f#hola].
+ | ^^^^^^-----
+ | |
+ | invalid anchor
+ |
+note: the lint level is defined here
+ --> $DIR/anchors.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `hello#people#!` contains multiple anchors
+ --> $DIR/anchors.rs:31:28
+ |
+LL | /// Another anchor error: [hello#people#!].
+ | ^^^^^^^^^^^^--
+ | |
+ | invalid anchor
+
+error: `Enum::A#whatever` contains an anchor, but links to variants are already anchored
+ --> $DIR/anchors.rs:37:28
+ |
+LL | /// Damn enum's variants: [Enum::A#whatever].
+ | ^^^^^^^---------
+ | |
+ | invalid anchor
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/assoc-field.rs b/src/test/rustdoc-ui/intra-doc/assoc-field.rs
new file mode 100644
index 000000000..e18404e44
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/assoc-field.rs
@@ -0,0 +1,26 @@
+// Traits in scope are collected for doc links in field attributes.
+
+// check-pass
+// aux-build: assoc-field-dep.rs
+
+extern crate assoc_field_dep;
+pub use assoc_field_dep::*;
+
+#[derive(Clone)]
+pub struct Struct;
+
+pub mod mod1 {
+ pub struct Fields {
+ /// [crate::Struct::clone]
+ pub field: u8,
+ }
+}
+
+pub mod mod2 {
+ pub enum Fields {
+ V {
+ /// [crate::Struct::clone]
+ field: u8,
+ },
+ }
+}
diff --git a/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs
new file mode 100644
index 000000000..b4ce3443c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs
@@ -0,0 +1,19 @@
+// Traits in scope are collected for doc links in both outer and inner module attributes.
+
+// check-pass
+// aux-build: assoc-mod-inner-outer-dep.rs
+
+extern crate assoc_mod_inner_outer_dep;
+pub use assoc_mod_inner_outer_dep::*;
+
+#[derive(Clone)]
+pub struct Struct;
+
+pub mod outer1 {
+ /// [crate::Struct::clone]
+ pub mod inner {}
+}
+
+pub mod outer2 {
+ //! [crate::Struct::clone]
+}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs
new file mode 100644
index 000000000..cfb24fc2c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs
@@ -0,0 +1,18 @@
+#[derive(Clone)]
+pub struct Struct;
+
+pub mod dep_mod1 {
+ pub struct Fields {
+ /// [crate::Struct::clone]
+ pub field: u8,
+ }
+}
+
+pub mod dep_mod2 {
+ pub enum Fields {
+ V {
+ /// [crate::Struct::clone]
+ field: u8,
+ },
+ }
+}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs
new file mode 100644
index 000000000..7a11a1657
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs
@@ -0,0 +1,11 @@
+#[derive(Clone)]
+pub struct Struct;
+
+pub mod dep_outer1 {
+ /// [crate::Struct::clone]
+ pub mod inner {}
+}
+
+pub mod dep_outer2 {
+ //! [crate::Struct::clone]
+}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs
new file mode 100644
index 000000000..31a8310d4
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs
@@ -0,0 +1,4 @@
+#![crate_name = "intra_doc_broken"]
+
+/// [not_found]
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/pointer-reexports-allowed.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/pointer-reexports-allowed.rs
new file mode 100644
index 000000000..0a3dc57f1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/pointer-reexports-allowed.rs
@@ -0,0 +1,4 @@
+#![feature(intra_doc_pointers)]
+#![crate_name = "inner"]
+/// Link to [some pointer](*const::to_raw_parts)
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs
new file mode 100644
index 000000000..5c4a01ee3
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/auxiliary/through-proc-macro-aux.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+#![crate_name="some_macros"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ item // This doesn't erase the spans.
+}
+
+#[proc_macro_attribute]
+pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ // Make a new `TokenStream` to erase the spans:
+ let mut out: TokenStream = TokenStream::new();
+ out.extend(item);
+ out
+}
diff --git a/src/test/rustdoc-ui/intra-doc/broken-reexport.rs b/src/test/rustdoc-ui/intra-doc/broken-reexport.rs
new file mode 100644
index 000000000..862faa50b
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/broken-reexport.rs
@@ -0,0 +1,8 @@
+// aux-build:intra-doc-broken.rs
+// check-pass
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate intra_doc_broken;
+
+pub use intra_doc_broken::foo;
diff --git a/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs
new file mode 100644
index 000000000..ceecfa681
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs
@@ -0,0 +1,5 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [crate::DoesNotExist]
+//~^ ERROR unresolved link to `crate::DoesNotExist`
+pub struct Item;
diff --git a/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr
new file mode 100644
index 000000000..a69b1c52a
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `crate::DoesNotExist`
+ --> $DIR/crate-nonexistent.rs:3:6
+ |
+LL | /// [crate::DoesNotExist]
+ | ^^^^^^^^^^^^^^^^^^^ no item named `DoesNotExist` in module `crate_nonexistent`
+ |
+note: the lint level is defined here
+ --> $DIR/crate-nonexistent.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs
new file mode 100644
index 000000000..2d6656611
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs
@@ -0,0 +1,81 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//~^ NOTE lint level is defined
+pub enum S {}
+fn S() {}
+
+#[macro_export]
+macro_rules! m {
+ () => {};
+}
+
+static s: usize = 0;
+const c: usize = 0;
+
+trait T {}
+
+/// Link to [struct@S]
+//~^ ERROR incompatible link kind for `S`
+//~| NOTE this link resolved
+//~| HELP prefix with `enum@`
+
+/// Link to [mod@S]
+//~^ ERROR incompatible link kind for `S`
+//~| NOTE this link resolved
+//~| HELP prefix with `enum@`
+
+/// Link to [union@S]
+//~^ ERROR incompatible link kind for `S`
+//~| NOTE this link resolved
+//~| HELP prefix with `enum@`
+
+/// Link to [trait@S]
+//~^ ERROR incompatible link kind for `S`
+//~| NOTE this link resolved
+//~| HELP prefix with `enum@`
+
+/// Link to [struct@T]
+//~^ ERROR incompatible link kind for `T`
+//~| NOTE this link resolved
+//~| HELP prefix with `trait@`
+
+/// Link to [derive@m]
+//~^ ERROR incompatible link kind for `m`
+//~| NOTE this link resolved
+//~| HELP add an exclamation mark
+
+/// Link to [m()]
+//~^ ERROR unresolved link to `m`
+//~| NOTE this link resolves to the macro `m`
+//~| HELP add an exclamation mark
+/// and to [m!()]
+
+/// Link to [const@s]
+//~^ ERROR incompatible link kind for `s`
+//~| NOTE this link resolved
+//~| HELP prefix with `static@`
+
+/// Link to [static@c]
+//~^ ERROR incompatible link kind for `c`
+//~| NOTE this link resolved
+//~| HELP prefix with `const@`
+
+/// Link to [fn@c]
+//~^ ERROR incompatible link kind for `c`
+//~| NOTE this link resolved
+//~| HELP prefix with `const@`
+
+/// Link to [c()]
+//~^ ERROR incompatible link kind for `c`
+//~| NOTE this link resolved
+//~| HELP prefix with `const@`
+
+/// Link to [const@f]
+//~^ ERROR incompatible link kind for `f`
+//~| NOTE this link resolved
+//~| HELP add parentheses
+
+/// Link to [fn@std]
+//~^ ERROR unresolved link to `std`
+//~| NOTE this link resolves to the crate `std`
+//~| HELP to link to the crate, prefix with `mod@`
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr
new file mode 100644
index 000000000..ee35749ce
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr
@@ -0,0 +1,153 @@
+error: incompatible link kind for `S`
+ --> $DIR/disambiguator-mismatch.rs:16:14
+ |
+LL | /// Link to [struct@S]
+ | ^^^^^^^^ this link resolved to an enum, which is not a struct
+ |
+note: the lint level is defined here
+ --> $DIR/disambiguator-mismatch.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the enum, prefix with `enum@`
+ |
+LL | /// Link to [enum@S]
+ | ~~~~~
+
+error: incompatible link kind for `S`
+ --> $DIR/disambiguator-mismatch.rs:21:14
+ |
+LL | /// Link to [mod@S]
+ | ^^^^^ this link resolved to an enum, which is not a module
+ |
+help: to link to the enum, prefix with `enum@`
+ |
+LL | /// Link to [enum@S]
+ | ~~~~~
+
+error: incompatible link kind for `S`
+ --> $DIR/disambiguator-mismatch.rs:26:14
+ |
+LL | /// Link to [union@S]
+ | ^^^^^^^ this link resolved to an enum, which is not a union
+ |
+help: to link to the enum, prefix with `enum@`
+ |
+LL | /// Link to [enum@S]
+ | ~~~~~
+
+error: incompatible link kind for `S`
+ --> $DIR/disambiguator-mismatch.rs:31:14
+ |
+LL | /// Link to [trait@S]
+ | ^^^^^^^ this link resolved to an enum, which is not a trait
+ |
+help: to link to the enum, prefix with `enum@`
+ |
+LL | /// Link to [enum@S]
+ | ~~~~~
+
+error: incompatible link kind for `T`
+ --> $DIR/disambiguator-mismatch.rs:36:14
+ |
+LL | /// Link to [struct@T]
+ | ^^^^^^^^ this link resolved to a trait, which is not a struct
+ |
+help: to link to the trait, prefix with `trait@`
+ |
+LL | /// Link to [trait@T]
+ | ~~~~~~
+
+error: incompatible link kind for `m`
+ --> $DIR/disambiguator-mismatch.rs:41:14
+ |
+LL | /// Link to [derive@m]
+ | ^^^^^^^^ this link resolved to a macro, which is not a derive macro
+ |
+help: to link to the macro, add an exclamation mark
+ |
+LL - /// Link to [derive@m]
+LL + /// Link to [m!]
+ |
+
+error: unresolved link to `m`
+ --> $DIR/disambiguator-mismatch.rs:46:14
+ |
+LL | /// Link to [m()]
+ | ^^^ this link resolves to the macro `m`, which is not in the value namespace
+ |
+help: to link to the macro, add an exclamation mark
+ |
+LL | /// Link to [m!()]
+ | +
+
+error: incompatible link kind for `s`
+ --> $DIR/disambiguator-mismatch.rs:52:14
+ |
+LL | /// Link to [const@s]
+ | ^^^^^^^ this link resolved to a static, which is not a constant
+ |
+help: to link to the static, prefix with `static@`
+ |
+LL | /// Link to [static@s]
+ | ~~~~~~~
+
+error: incompatible link kind for `c`
+ --> $DIR/disambiguator-mismatch.rs:57:14
+ |
+LL | /// Link to [static@c]
+ | ^^^^^^^^ this link resolved to a constant, which is not a static
+ |
+help: to link to the constant, prefix with `const@`
+ |
+LL | /// Link to [const@c]
+ | ~~~~~~
+
+error: incompatible link kind for `c`
+ --> $DIR/disambiguator-mismatch.rs:62:14
+ |
+LL | /// Link to [fn@c]
+ | ^^^^ this link resolved to a constant, which is not a function
+ |
+help: to link to the constant, prefix with `const@`
+ |
+LL | /// Link to [const@c]
+ | ~~~~~~
+
+error: incompatible link kind for `c`
+ --> $DIR/disambiguator-mismatch.rs:67:14
+ |
+LL | /// Link to [c()]
+ | ^^^ this link resolved to a constant, which is not a function
+ |
+help: to link to the constant, prefix with `const@`
+ |
+LL - /// Link to [c()]
+LL + /// Link to [const@c]
+ |
+
+error: incompatible link kind for `f`
+ --> $DIR/disambiguator-mismatch.rs:72:14
+ |
+LL | /// Link to [const@f]
+ | ^^^^^^^ this link resolved to a function, which is not a constant
+ |
+help: to link to the function, add parentheses
+ |
+LL - /// Link to [const@f]
+LL + /// Link to [f()]
+ |
+
+error: unresolved link to `std`
+ --> $DIR/disambiguator-mismatch.rs:77:14
+ |
+LL | /// Link to [fn@std]
+ | ^^^^^^ this link resolves to the crate `std`, which is not in the value namespace
+ |
+help: to link to the crate, prefix with `mod@`
+ |
+LL | /// Link to [mod@std]
+ | ~~~~
+
+error: aborting due to 13 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/double-anchor.rs b/src/test/rustdoc-ui/intra-doc/double-anchor.rs
new file mode 100644
index 000000000..a01211c4f
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/double-anchor.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+// regression test for #73264
+// should only give one error
+/// docs [label][with#anchor#error]
+//~^ WARNING multiple anchors
+pub struct S;
diff --git a/src/test/rustdoc-ui/intra-doc/double-anchor.stderr b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr
new file mode 100644
index 000000000..6addb010e
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr
@@ -0,0 +1,12 @@
+warning: `with#anchor#error` contains multiple anchors
+ --> $DIR/double-anchor.rs:5:18
+ |
+LL | /// docs [label][with#anchor#error]
+ | ^^^^^^^^^^^------
+ | |
+ | invalid anchor
+ |
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
new file mode 100644
index 000000000..7a5156e81
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
@@ -0,0 +1,7 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+// check-pass
+#![deny(warnings)]
+
+//! Email me at <hello@localhost>.
+
+//! This should *not* warn: <hello@example.com>.
diff --git a/src/test/rustdoc-ui/intra-doc/errors.rs b/src/test/rustdoc-ui/intra-doc/errors.rs
new file mode 100644
index 000000000..b29f7c29b
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/errors.rs
@@ -0,0 +1,105 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//~^ NOTE lint level is defined
+
+// FIXME: this should say that it was skipped (maybe an allowed by default lint?)
+/// [invalid intra-doc syntax!!]
+
+/// [path::to::nonexistent::module]
+//~^ ERROR unresolved link
+//~| NOTE no item named `path` in scope
+
+/// [path::to::nonexistent::macro!]
+//~^ ERROR unresolved link
+//~| NOTE no item named `path` in scope
+
+/// [type@path::to::nonexistent::type]
+//~^ ERROR unresolved link
+//~| NOTE no item named `path` in scope
+
+/// [std::io::not::here]
+//~^ ERROR unresolved link
+//~| NOTE no item named `not` in module `io`
+
+/// [type@std::io::not::here]
+//~^ ERROR unresolved link
+//~| NOTE no item named `not` in module `io`
+
+/// [std::io::Error::x]
+//~^ ERROR unresolved link
+//~| NOTE the struct `Error` has no field
+
+/// [std::io::ErrorKind::x]
+//~^ ERROR unresolved link
+//~| NOTE the enum `ErrorKind` has no variant
+
+/// [f::A]
+//~^ ERROR unresolved link
+//~| NOTE `f` is a function, not a module
+
+/// [f::A!]
+//~^ ERROR unresolved link
+//~| NOTE `f` is a function, not a module
+
+/// [S::A]
+//~^ ERROR unresolved link
+//~| NOTE struct `S` has no field or associated item
+
+/// [S::fmt]
+//~^ ERROR unresolved link
+//~| NOTE struct `S` has no field or associated item
+
+/// [E::D]
+//~^ ERROR unresolved link
+//~| NOTE enum `E` has no variant or associated item
+
+/// [u8::not_found]
+//~^ ERROR unresolved link
+//~| NOTE the builtin type `u8` has no associated item named `not_found`
+
+/// [std::primitive::u8::not_found]
+//~^ ERROR unresolved link
+//~| NOTE the builtin type `u8` has no associated item named `not_found`
+
+/// [type@Vec::into_iter]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function, add parentheses
+//~| NOTE this link resolves to the associated function `into_iter`
+
+/// [S!]
+//~^ ERROR unresolved link
+//~| HELP to link to the struct, prefix with `struct@`
+//~| NOTE this link resolves to the struct `S`
+pub fn f() {}
+#[derive(Debug)]
+pub struct S;
+
+pub enum E { A, B, C }
+
+/// [type@S::h]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function
+//~| NOTE not in the type namespace
+impl S {
+ pub fn h() {}
+}
+
+/// [type@T::g]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function
+//~| NOTE not in the type namespace
+
+/// [T::h!]
+//~^ ERROR unresolved link
+//~| NOTE `T` has no macro named `h`
+pub trait T {
+ fn g() {}
+}
+
+/// [m()]
+//~^ ERROR unresolved link
+//~| HELP to link to the macro
+//~| NOTE not in the value namespace
+#[macro_export]
+macro_rules! m {
+ () => {};
+}
diff --git a/src/test/rustdoc-ui/intra-doc/errors.stderr b/src/test/rustdoc-ui/intra-doc/errors.stderr
new file mode 100644
index 000000000..9a1896fb0
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/errors.stderr
@@ -0,0 +1,157 @@
+error: unresolved link to `path::to::nonexistent::module`
+ --> $DIR/errors.rs:7:6
+ |
+LL | /// [path::to::nonexistent::module]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/errors.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unresolved link to `path::to::nonexistent::macro`
+ --> $DIR/errors.rs:11:6
+ |
+LL | /// [path::to::nonexistent::macro!]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
+
+error: unresolved link to `path::to::nonexistent::type`
+ --> $DIR/errors.rs:15:6
+ |
+LL | /// [type@path::to::nonexistent::type]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
+
+error: unresolved link to `std::io::not::here`
+ --> $DIR/errors.rs:19:6
+ |
+LL | /// [std::io::not::here]
+ | ^^^^^^^^^^^^^^^^^^ no item named `not` in module `io`
+
+error: unresolved link to `std::io::not::here`
+ --> $DIR/errors.rs:23:6
+ |
+LL | /// [type@std::io::not::here]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `not` in module `io`
+
+error: unresolved link to `std::io::Error::x`
+ --> $DIR/errors.rs:27:6
+ |
+LL | /// [std::io::Error::x]
+ | ^^^^^^^^^^^^^^^^^ the struct `Error` has no field or associated item named `x`
+
+error: unresolved link to `std::io::ErrorKind::x`
+ --> $DIR/errors.rs:31:6
+ |
+LL | /// [std::io::ErrorKind::x]
+ | ^^^^^^^^^^^^^^^^^^^^^ the enum `ErrorKind` has no variant or associated item named `x`
+
+error: unresolved link to `f::A`
+ --> $DIR/errors.rs:35:6
+ |
+LL | /// [f::A]
+ | ^^^^ `f` is a function, not a module or type, and cannot have associated items
+
+error: unresolved link to `f::A`
+ --> $DIR/errors.rs:39:6
+ |
+LL | /// [f::A!]
+ | ^^^^^ `f` is a function, not a module or type, and cannot have associated items
+
+error: unresolved link to `S::A`
+ --> $DIR/errors.rs:43:6
+ |
+LL | /// [S::A]
+ | ^^^^ the struct `S` has no field or associated item named `A`
+
+error: unresolved link to `S::fmt`
+ --> $DIR/errors.rs:47:6
+ |
+LL | /// [S::fmt]
+ | ^^^^^^ the struct `S` has no field or associated item named `fmt`
+
+error: unresolved link to `E::D`
+ --> $DIR/errors.rs:51:6
+ |
+LL | /// [E::D]
+ | ^^^^ the enum `E` has no variant or associated item named `D`
+
+error: unresolved link to `u8::not_found`
+ --> $DIR/errors.rs:55:6
+ |
+LL | /// [u8::not_found]
+ | ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+
+error: unresolved link to `std::primitive::u8::not_found`
+ --> $DIR/errors.rs:59:6
+ |
+LL | /// [std::primitive::u8::not_found]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+
+error: unresolved link to `Vec::into_iter`
+ --> $DIR/errors.rs:63:6
+ |
+LL | /// [type@Vec::into_iter]
+ | ^^^^^^^^^^^^^^^^^^^ this link resolves to the associated function `into_iter`, which is not in the type namespace
+ |
+help: to link to the associated function, add parentheses
+ |
+LL - /// [type@Vec::into_iter]
+LL + /// [Vec::into_iter()]
+ |
+
+error: unresolved link to `S`
+ --> $DIR/errors.rs:68:6
+ |
+LL | /// [S!]
+ | ^^ this link resolves to the struct `S`, which is not in the macro namespace
+ |
+help: to link to the struct, prefix with `struct@`
+ |
+LL - /// [S!]
+LL + /// [struct@S]
+ |
+
+error: unresolved link to `S::h`
+ --> $DIR/errors.rs:78:6
+ |
+LL | /// [type@S::h]
+ | ^^^^^^^^^ this link resolves to the associated function `h`, which is not in the type namespace
+ |
+help: to link to the associated function, add parentheses
+ |
+LL - /// [type@S::h]
+LL + /// [S::h()]
+ |
+
+error: unresolved link to `T::g`
+ --> $DIR/errors.rs:86:6
+ |
+LL | /// [type@T::g]
+ | ^^^^^^^^^ this link resolves to the associated function `g`, which is not in the type namespace
+ |
+help: to link to the associated function, add parentheses
+ |
+LL - /// [type@T::g]
+LL + /// [T::g()]
+ |
+
+error: unresolved link to `T::h`
+ --> $DIR/errors.rs:91:6
+ |
+LL | /// [T::h!]
+ | ^^^^^ the trait `T` has no macro named `h`
+
+error: unresolved link to `m`
+ --> $DIR/errors.rs:98:6
+ |
+LL | /// [m()]
+ | ^^^ this link resolves to the macro `m`, which is not in the value namespace
+ |
+help: to link to the macro, add an exclamation mark
+ |
+LL | /// [m!()]
+ | +
+
+error: aborting due to 20 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs b/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs
new file mode 100644
index 000000000..438c56aa5
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs
@@ -0,0 +1,26 @@
+// check-pass
+// aux-crate:dep1=dep1.rs
+// aux-crate:dep2=dep2.rs
+// aux-crate:dep3=dep3.rs
+// aux-crate:dep4=dep4.rs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub trait Trait {
+ /// [dep1]
+ type Item;
+}
+
+pub struct S {
+ /// [dep2]
+ pub x: usize,
+}
+
+extern "C" {
+ /// [dep3]
+ pub fn printf();
+}
+
+pub enum E {
+ /// [dep4]
+ A
+}
diff --git a/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs
new file mode 100644
index 000000000..3cfac942c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.rs
@@ -0,0 +1,6 @@
+//! [pointer::add]
+//~^ ERROR: experimental
+//! [pointer::wrapping_add]
+//~^ ERROR: experimental
+//! [pointer] // This is explicitly allowed
+//! [reference] // This is explicitly allowed
diff --git a/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr
new file mode 100644
index 000000000..2c946ed48
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/feature-gate-intra-doc-pointers.stderr
@@ -0,0 +1,23 @@
+error[E0658]: linking to associated items of raw pointers is experimental
+ --> $DIR/feature-gate-intra-doc-pointers.rs:1:6
+ |
+LL | //! [pointer::add]
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #80896 <https://github.com/rust-lang/rust/issues/80896> for more information
+ = help: add `#![feature(intra_doc_pointers)]` to the crate attributes to enable
+ = note: rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does
+
+error[E0658]: linking to associated items of raw pointers is experimental
+ --> $DIR/feature-gate-intra-doc-pointers.rs:3:6
+ |
+LL | //! [pointer::wrapping_add]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #80896 <https://github.com/rust-lang/rust/issues/80896> for more information
+ = help: add `#![feature(intra_doc_pointers)]` to the crate attributes to enable
+ = note: rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.rs b/src/test/rustdoc-ui/intra-doc/field-ice.rs
new file mode 100644
index 000000000..c5d501e38
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/field-ice.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//~^NOTE the lint level is defined here
+
+/// [`Foo::bar`]
+/// [`Foo::bar()`]
+//~^ERROR incompatible link kind for `Foo::bar`
+//~|HELP to link to the field, remove the disambiguator
+//~|NOTE this link resolved to a field, which is not a function
+pub struct Foo {
+ pub bar: u8
+}
diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.stderr b/src/test/rustdoc-ui/intra-doc/field-ice.stderr
new file mode 100644
index 000000000..f45a3ca61
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/field-ice.stderr
@@ -0,0 +1,18 @@
+error: incompatible link kind for `Foo::bar`
+ --> $DIR/field-ice.rs:5:7
+ |
+LL | /// [`Foo::bar()`]
+ | ^^^^^^^^^^ this link resolved to a field, which is not a function
+ |
+note: the lint level is defined here
+ --> $DIR/field-ice.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the field, remove the disambiguator
+ |
+LL | /// [`Foo::bar`]
+ | ~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/global-path.rs b/src/test/rustdoc-ui/intra-doc/global-path.rs
new file mode 100644
index 000000000..cc7a5fa1c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/global-path.rs
@@ -0,0 +1,8 @@
+// Doc link path with empty prefix that resolves to "extern prelude" instead of a module.
+
+// check-pass
+// edition:2018
+
+/// [::Unresolved]
+//~^ WARN unresolved link to `::Unresolved`
+pub struct Item;
diff --git a/src/test/rustdoc-ui/intra-doc/global-path.stderr b/src/test/rustdoc-ui/intra-doc/global-path.stderr
new file mode 100644
index 000000000..02379cd6c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/global-path.stderr
@@ -0,0 +1,10 @@
+warning: unresolved link to `::Unresolved`
+ --> $DIR/global-path.rs:6:6
+ |
+LL | /// [::Unresolved]
+ | ^^^^^^^^^^^^ no item named `` in scope
+ |
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs
new file mode 100644
index 000000000..b5470c859
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs
@@ -0,0 +1,25 @@
+#![deny(rustdoc::invalid_html_tags)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub struct ExistentStruct<T>(T);
+
+/// This [test][ExistentStruct<i32>] thing!
+pub struct NoError;
+
+/// This [ExistentStruct<i32>] thing!
+//~^ ERROR unclosed HTML tag `i32`
+pub struct PartialErrorOnlyHtml;
+
+/// This [test][NonExistentStruct<i32>] thing!
+//~^ ERROR unresolved link
+pub struct PartialErrorOnlyResolve;
+
+/// This [NonExistentStruct2<i32>] thing!
+//~^ ERROR unclosed HTML tag `i32`
+//~| ERROR unresolved link
+pub struct YesError;
+
+/// This [NonExistentStruct3<i32>][] thing!
+//~^ ERROR unclosed HTML tag `i32`
+//~| ERROR unresolved link
+pub struct YesErrorCollapsed;
diff --git a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr
new file mode 100644
index 000000000..00fe229da
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr
@@ -0,0 +1,69 @@
+error: unresolved link to `NonExistentStruct`
+ --> $DIR/html-as-generics-intra-doc.rs:13:17
+ |
+LL | /// This [test][NonExistentStruct<i32>] thing!
+ | ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/html-as-generics-intra-doc.rs:2:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `NonExistentStruct2`
+ --> $DIR/html-as-generics-intra-doc.rs:17:11
+ |
+LL | /// This [NonExistentStruct2<i32>] thing!
+ | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `NonExistentStruct3`
+ --> $DIR/html-as-generics-intra-doc.rs:22:11
+ |
+LL | /// This [NonExistentStruct3<i32>][] thing!
+ | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct3` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-intra-doc.rs:9:25
+ |
+LL | /// This [ExistentStruct<i32>] thing!
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/html-as-generics-intra-doc.rs:1:9
+ |
+LL | #![deny(rustdoc::invalid_html_tags)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try marking as source code
+ |
+LL | /// This [`ExistentStruct<i32>`] thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-intra-doc.rs:17:29
+ |
+LL | /// This [NonExistentStruct2<i32>] thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This [`NonExistentStruct2<i32>`] thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-intra-doc.rs:22:29
+ |
+LL | /// This [NonExistentStruct3<i32>][] thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This [`NonExistentStruct3<i32>`][] thing!
+ | + +
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
new file mode 100644
index 000000000..3088bcd46
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
@@ -0,0 +1,3 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//! [static@u8::MIN]
+//~^ ERROR incompatible link kind
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
new file mode 100644
index 000000000..c43cda3eb
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
@@ -0,0 +1,18 @@
+error: incompatible link kind for `u8::MIN`
+ --> $DIR/incompatible-primitive-disambiguator.rs:2:6
+ |
+LL | //! [static@u8::MIN]
+ | ^^^^^^^^^^^^^^ this link resolved to an associated constant, which is not a static
+ |
+note: the lint level is defined here
+ --> $DIR/incompatible-primitive-disambiguator.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the associated constant, prefix with `const@`
+ |
+LL | //! [const@u8::MIN]
+ | ~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs b/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs
new file mode 100644
index 000000000..8490584c1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs
@@ -0,0 +1,26 @@
+// `macro_rules` scopes are respected during doc link resolution.
+
+// compile-flags: --document-private-items
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+mod no_escape {
+ macro_rules! before_but_limited_to_module {
+ () => {};
+ }
+}
+
+/// [before_but_limited_to_module]
+//~^ ERROR unresolved link to `before_but_limited_to_module`
+/// [after]
+//~^ ERROR unresolved link to `after`
+/// [str]
+fn check() {}
+
+macro_rules! after {
+ () => {};
+}
+
+macro_rules! str {
+ () => {};
+}
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
new file mode 100644
index 000000000..8e17323fd
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
@@ -0,0 +1,23 @@
+error: unresolved link to `before_but_limited_to_module`
+ --> $DIR/macro-rules-error.rs:13:6
+ |
+LL | /// [before_but_limited_to_module]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `before_but_limited_to_module` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/macro-rules-error.rs:5:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
+
+error: unresolved link to `after`
+ --> $DIR/macro-rules-error.rs:15:6
+ |
+LL | /// [after]
+ | ^^^^^ no item named `after` in scope
+ |
+ = note: `macro_rules` named `after` exists in this crate, but it is not in scope at this link's location
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules.rs b/src/test/rustdoc-ui/intra-doc/macro-rules.rs
new file mode 100644
index 000000000..3aeb370ef
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules.rs
@@ -0,0 +1,24 @@
+// check-pass
+#![allow(rustdoc::private_intra_doc_links)]
+
+macro_rules! foo {
+ () => {};
+}
+
+/// [foo!]
+pub fn baz() {}
+
+#[macro_use]
+mod macros {
+ macro_rules! escaping {
+ () => {};
+ }
+}
+
+pub mod inner {
+ /// [foo!]
+ /// [escaping]
+ pub fn baz() {
+ foo!();
+ }
+}
diff --git a/src/test/rustdoc-ui/intra-doc/malformed-generics.rs b/src/test/rustdoc-ui/intra-doc/malformed-generics.rs
new file mode 100644
index 000000000..15e02925e
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/malformed-generics.rs
@@ -0,0 +1,19 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! [Vec<] //~ ERROR
+//! [Vec<Box<T] //~ ERROR
+//! [Vec<Box<T>] //~ ERROR
+//! [Vec<Box<T>>>] //~ ERROR
+//! [Vec<T>>>] //~ ERROR
+//! [<Vec] //~ ERROR
+//! [Vec::<] //~ ERROR
+//! [<T>] //~ ERROR
+//! [<invalid syntax>] //~ ERROR
+//! [Vec:<T>:new()] //~ ERROR
+//! [Vec<<T>>] //~ ERROR
+//! [Vec<>] //~ ERROR
+//! [Vec<<>>] //~ ERROR
+
+// FIXME(#74563) support UFCS
+//! [<Vec as IntoIterator>::into_iter] //~ ERROR
+//! [<Vec<T> as IntoIterator>::iter] //~ ERROR
diff --git a/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr
new file mode 100644
index 000000000..5bc0f84e2
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr
@@ -0,0 +1,102 @@
+error: unresolved link to `Vec<`
+ --> $DIR/malformed-generics.rs:3:6
+ |
+LL | //! [Vec<]
+ | ^^^^ unbalanced angle brackets
+ |
+note: the lint level is defined here
+ --> $DIR/malformed-generics.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unresolved link to `Vec<Box<T`
+ --> $DIR/malformed-generics.rs:4:6
+ |
+LL | //! [Vec<Box<T]
+ | ^^^^^^^^^ unbalanced angle brackets
+
+error: unresolved link to `Vec<Box<T>`
+ --> $DIR/malformed-generics.rs:5:6
+ |
+LL | //! [Vec<Box<T>]
+ | ^^^^^^^^^^ unbalanced angle brackets
+
+error: unresolved link to `Vec<Box<T>>>`
+ --> $DIR/malformed-generics.rs:6:6
+ |
+LL | //! [Vec<Box<T>>>]
+ | ^^^^^^^^^^^^ unbalanced angle brackets
+
+error: unresolved link to `Vec<T>>>`
+ --> $DIR/malformed-generics.rs:7:6
+ |
+LL | //! [Vec<T>>>]
+ | ^^^^^^^^ unbalanced angle brackets
+
+error: unresolved link to `<Vec`
+ --> $DIR/malformed-generics.rs:8:6
+ |
+LL | //! [<Vec]
+ | ^^^^ unbalanced angle brackets
+
+error: unresolved link to `Vec::<`
+ --> $DIR/malformed-generics.rs:9:6
+ |
+LL | //! [Vec::<]
+ | ^^^^^^ unbalanced angle brackets
+
+error: unresolved link to `<T>`
+ --> $DIR/malformed-generics.rs:10:6
+ |
+LL | //! [<T>]
+ | ^^^ missing type for generic parameters
+
+error: unresolved link to `<invalid syntax>`
+ --> $DIR/malformed-generics.rs:11:6
+ |
+LL | //! [<invalid syntax>]
+ | ^^^^^^^^^^^^^^^^ missing type for generic parameters
+
+error: unresolved link to `Vec:<T>:new`
+ --> $DIR/malformed-generics.rs:12:6
+ |
+LL | //! [Vec:<T>:new()]
+ | ^^^^^^^^^^^^^ has invalid path separator
+
+error: unresolved link to `Vec<<T>>`
+ --> $DIR/malformed-generics.rs:13:6
+ |
+LL | //! [Vec<<T>>]
+ | ^^^^^^^^ too many angle brackets
+
+error: unresolved link to `Vec<>`
+ --> $DIR/malformed-generics.rs:14:6
+ |
+LL | //! [Vec<>]
+ | ^^^^^ empty angle brackets
+
+error: unresolved link to `Vec<<>>`
+ --> $DIR/malformed-generics.rs:15:6
+ |
+LL | //! [Vec<<>>]
+ | ^^^^^^^ too many angle brackets
+
+error: unresolved link to `<Vec as IntoIterator>::into_iter`
+ --> $DIR/malformed-generics.rs:18:6
+ |
+LL | //! [<Vec as IntoIterator>::into_iter]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
+ |
+ = note: see https://github.com/rust-lang/rust/issues/74563 for more information
+
+error: unresolved link to `<Vec<T> as IntoIterator>::iter`
+ --> $DIR/malformed-generics.rs:19:6
+ |
+LL | //! [<Vec<T> as IntoIterator>::iter]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
+ |
+ = note: see https://github.com/rust-lang/rust/issues/74563 for more information
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
new file mode 100644
index 000000000..587cbad68
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs
@@ -0,0 +1,34 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(intra_doc_pointers)]
+// These are links that could reasonably expected to work, but don't.
+
+// `[]` isn't supported because it had too many false positives.
+//! [X]([T]::not_here)
+//! [Y](&[]::not_here)
+//! [X]([]::not_here)
+//! [Y]([T;N]::not_here)
+
+// These don't work because markdown syntax doesn't allow it.
+//! [[T]::rotate_left] //~ ERROR unresolved link to `T`
+//! [&[]::not_here]
+//![Z]([T; N]::map) //~ ERROR unresolved link to `Z`
+//! [`[T; N]::map`]
+//! [[]::map]
+//! [Z][] //~ ERROR unresolved link to `Z`
+//!
+//! [Z]: [T; N]::map //~ ERROR unresolved link to `Z`
+
+// `()` isn't supported because it had too many false positives.
+//! [()::not_here]
+//! [X]((,)::not_here)
+//! [(,)::not_here]
+
+// FIXME: Associated items on some primitives aren't working, because the impls
+// are part of the compiler instead of being part of the source code.
+//! [unit::eq] //~ ERROR unresolved
+//! [tuple::eq] //~ ERROR unresolved
+//! [fn::eq] //~ ERROR unresolved
+
+// FIXME(#78800): This breaks because it's a blanket impl
+// (I think? Might break for other reasons too.)
+//! [reference::deref] //~ ERROR unresolved
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
new file mode 100644
index 000000000..4828a3044
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
@@ -0,0 +1,63 @@
+error: unresolved link to `T`
+ --> $DIR/non-path-primitives.rs:12:7
+ |
+LL | //! [[T]::rotate_left]
+ | ^ no item named `T` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/non-path-primitives.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Z`
+ --> $DIR/non-path-primitives.rs:14:5
+ |
+LL | //![Z]([T; N]::map)
+ | ^ no item named `Z` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Z`
+ --> $DIR/non-path-primitives.rs:17:6
+ |
+LL | //! [Z][]
+ | ^ no item named `Z` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Z`
+ --> $DIR/non-path-primitives.rs:19:6
+ |
+LL | //! [Z]: [T; N]::map
+ | ^ no item named `Z` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `unit::eq`
+ --> $DIR/non-path-primitives.rs:28:6
+ |
+LL | //! [unit::eq]
+ | ^^^^^^^^ the builtin type `unit` has no associated item named `eq`
+
+error: unresolved link to `tuple::eq`
+ --> $DIR/non-path-primitives.rs:29:6
+ |
+LL | //! [tuple::eq]
+ | ^^^^^^^^^ the builtin type `tuple` has no associated item named `eq`
+
+error: unresolved link to `fn::eq`
+ --> $DIR/non-path-primitives.rs:30:6
+ |
+LL | //! [fn::eq]
+ | ^^^^^^ the builtin type `fn` has no associated item named `eq`
+
+error: unresolved link to `reference::deref`
+ --> $DIR/non-path-primitives.rs:34:6
+ |
+LL | //! [reference::deref]
+ | ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/pointer-reexports-allowed.rs b/src/test/rustdoc-ui/intra-doc/pointer-reexports-allowed.rs
new file mode 100644
index 000000000..8654a8e1b
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/pointer-reexports-allowed.rs
@@ -0,0 +1,4 @@
+// aux-build:pointer-reexports-allowed.rs
+// check-pass
+extern crate inner;
+pub use inner::foo;
diff --git a/src/test/rustdoc-ui/intra-doc/prim-conflict.rs b/src/test/rustdoc-ui/intra-doc/prim-conflict.rs
new file mode 100644
index 000000000..2c1a8b535
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/prim-conflict.rs
@@ -0,0 +1,30 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+//~^ NOTE lint level is defined
+
+/// [char]
+//~^ ERROR both a module and a builtin type
+//~| NOTE ambiguous link
+//~| HELP to link to the module
+//~| HELP to link to the builtin type
+
+/// [type@char]
+//~^ ERROR both a module and a builtin type
+//~| NOTE ambiguous link
+//~| HELP to link to the module
+//~| HELP to link to the builtin type
+
+/// [mod@char] // ok
+/// [prim@char] // ok
+
+/// [struct@char]
+//~^ ERROR incompatible link
+//~| HELP prefix with `mod@`
+//~| NOTE resolved to a module
+pub mod char {}
+
+pub mod inner {
+ //! [struct@char]
+ //~^ ERROR incompatible link
+ //~| HELP prefix with `prim@`
+ //~| NOTE resolved to a builtin type
+}
diff --git a/src/test/rustdoc-ui/intra-doc/prim-conflict.stderr b/src/test/rustdoc-ui/intra-doc/prim-conflict.stderr
new file mode 100644
index 000000000..6ef3b7eab
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/prim-conflict.stderr
@@ -0,0 +1,59 @@
+error: `char` is both a module and a builtin type
+ --> $DIR/prim-conflict.rs:4:6
+ |
+LL | /// [char]
+ | ^^^^ ambiguous link
+ |
+note: the lint level is defined here
+ --> $DIR/prim-conflict.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the module, prefix with `mod@`
+ |
+LL | /// [mod@char]
+ | ++++
+help: to link to the builtin type, prefix with `prim@`
+ |
+LL | /// [prim@char]
+ | +++++
+
+error: `char` is both a module and a builtin type
+ --> $DIR/prim-conflict.rs:10:6
+ |
+LL | /// [type@char]
+ | ^^^^^^^^^ ambiguous link
+ |
+help: to link to the module, prefix with `mod@`
+ |
+LL | /// [mod@char]
+ | ~~~~
+help: to link to the builtin type, prefix with `prim@`
+ |
+LL | /// [prim@char]
+ | ~~~~~
+
+error: incompatible link kind for `char`
+ --> $DIR/prim-conflict.rs:19:6
+ |
+LL | /// [struct@char]
+ | ^^^^^^^^^^^ this link resolved to a module, which is not a struct
+ |
+help: to link to the module, prefix with `mod@`
+ |
+LL | /// [mod@char]
+ | ~~~~
+
+error: incompatible link kind for `char`
+ --> $DIR/prim-conflict.rs:26:10
+ |
+LL | //! [struct@char]
+ | ^^^^^^^^^^^ this link resolved to a builtin type, which is not a struct
+ |
+help: to link to the builtin type, prefix with `prim@`
+ |
+LL | //! [prim@char]
+ | ~~~~~
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs
new file mode 100644
index 000000000..e429e75b2
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+//! [my_module]
+//~^ WARN public documentation for `private_from_crate_level` links to private item `my_module`
+
+mod my_module {}
diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
new file mode 100644
index 000000000..6172cd2e3
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
@@ -0,0 +1,11 @@
+warning: public documentation for `private_from_crate_level` links to private item `my_module`
+ --> $DIR/private-from-crate-level.rs:3:6
+ |
+LL | //! [my_module]
+ | ^^^^^^^^^ this item is private
+ |
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
+ = note: this link will resolve properly if you pass `--document-private-items`
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/private.private.stderr b/src/test/rustdoc-ui/intra-doc/private.private.stderr
new file mode 100644
index 000000000..392321f9c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private.private.stderr
@@ -0,0 +1,27 @@
+warning: public documentation for `DocMe` links to private item `DontDocMe`
+ --> $DIR/private.rs:7:11
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^ this item is private
+ |
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
+ = note: this link resolves only because you passed `--document-private-items`, but will break without
+
+warning: public documentation for `DocMe` links to private item `DontDocMe::f`
+ --> $DIR/private.rs:7:23
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^^^^ this item is private
+ |
+ = note: this link resolves only because you passed `--document-private-items`, but will break without
+
+warning: public documentation for `DocMe` links to private item `DontDocMe::x`
+ --> $DIR/private.rs:7:38
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^^^^ this item is private
+ |
+ = note: this link resolves only because you passed `--document-private-items`, but will break without
+
+warning: 3 warnings emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/private.public.stderr b/src/test/rustdoc-ui/intra-doc/private.public.stderr
new file mode 100644
index 000000000..5d1c34b91
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private.public.stderr
@@ -0,0 +1,27 @@
+warning: public documentation for `DocMe` links to private item `DontDocMe`
+ --> $DIR/private.rs:7:11
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^ this item is private
+ |
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
+ = note: this link will resolve properly if you pass `--document-private-items`
+
+warning: public documentation for `DocMe` links to private item `DontDocMe::f`
+ --> $DIR/private.rs:7:23
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^^^^ this item is private
+ |
+ = note: this link will resolve properly if you pass `--document-private-items`
+
+warning: public documentation for `DocMe` links to private item `DontDocMe::x`
+ --> $DIR/private.rs:7:38
+ |
+LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+ | ^^^^^^^^^^^^ this item is private
+ |
+ = note: this link will resolve properly if you pass `--document-private-items`
+
+warning: 3 warnings emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/private.rs b/src/test/rustdoc-ui/intra-doc/private.rs
new file mode 100644
index 000000000..525332dda
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private.rs
@@ -0,0 +1,18 @@
+// check-pass
+// revisions: public private
+// [private]compile-flags: --document-private-items
+
+// make sure to update `rustdoc/intra-doc/private.rs` if you update this file
+
+/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+//~^ WARNING public documentation for `DocMe` links to private item `DontDocMe`
+//~| WARNING public documentation for `DocMe` links to private item `DontDocMe::x`
+//~| WARNING public documentation for `DocMe` links to private item `DontDocMe::f`
+pub struct DocMe;
+struct DontDocMe {
+ x: usize,
+}
+
+impl DontDocMe {
+ fn f() {}
+}
diff --git a/src/test/rustdoc-ui/intra-doc/span-ice-55723.rs b/src/test/rustdoc-ui/intra-doc/span-ice-55723.rs
new file mode 100644
index 000000000..041ec2932
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/span-ice-55723.rs
@@ -0,0 +1,13 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to
+// attempt to slice in the middle of a multibyte character. See
+// https://github.com/rust-lang/rust/issues/55723
+
+/// ## For example:
+///
+/// (arr[i])
+//~^ ERROR `i`
+pub fn test_ice() {
+ unimplemented!();
+}
diff --git a/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr
new file mode 100644
index 000000000..bf4ab9fdd
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `i`
+ --> $DIR/span-ice-55723.rs:9:10
+ |
+LL | /// (arr[i])
+ | ^ no item named `i` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/span-ice-55723.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/through-proc-macro.rs b/src/test/rustdoc-ui/intra-doc/through-proc-macro.rs
new file mode 100644
index 000000000..7628c3928
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/through-proc-macro.rs
@@ -0,0 +1,18 @@
+// check-pass
+// aux-build:through-proc-macro-aux.rs
+// build-aux-docs
+
+// Ensure rustdoc doesn't panic on this code.
+
+#![warn(rustdoc::broken_intra_doc_links)]
+
+extern crate some_macros;
+
+#[some_macros::second]
+pub enum Boom {
+ /// [Oooops]
+ //~^ WARNING unresolved link to `Oooops`
+ Bam,
+}
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr b/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
new file mode 100644
index 000000000..f0a7ed178
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
@@ -0,0 +1,15 @@
+warning: unresolved link to `Oooops`
+ --> $DIR/through-proc-macro.rs:13:10
+ |
+LL | /// [Oooops]
+ | ^^^^^^ no item named `Oooops` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/through-proc-macro.rs:7:9
+ |
+LL | #![warn(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
new file mode 100644
index 000000000..0aa1e5a41
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
@@ -0,0 +1,14 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+#![deny(warnings)]
+
+//! Linking to [foo@banana] and [`bar@banana!()`].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `bar`
+//! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+//~^ ERROR unknown disambiguator ``
+//~| ERROR unknown disambiguator ``
+//! And with weird backticks: [``foo@hello``] [foo`@`hello].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `foo`
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
new file mode 100644
index 000000000..d280e6497
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -0,0 +1,56 @@
+error: unknown disambiguator `foo`
+ --> $DIR/unknown-disambiguator.rs:4:17
+ |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unknown-disambiguator.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator `bar`
+ --> $DIR/unknown-disambiguator.rs:4:35
+ |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+ | ^^^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator `foo`
+ --> $DIR/unknown-disambiguator.rs:10:34
+ |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+ | ^^^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator `foo`
+ --> $DIR/unknown-disambiguator.rs:10:48
+ |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+ | ^^^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator ``
+ --> $DIR/unknown-disambiguator.rs:7:31
+ |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+ | ^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator ``
+ --> $DIR/unknown-disambiguator.rs:7:57
+ |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+ | ^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs
new file mode 100644
index 000000000..c71e5bee1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs
@@ -0,0 +1,6 @@
+// Regression test for issue #95879.
+
+use unresolved_crate::module::Name; //~ ERROR failed to resolve
+
+/// [Name]
+pub struct S;
diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
new file mode 100644
index 000000000..b54f82006
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
@@ -0,0 +1,13 @@
+error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
+ --> $DIR/unresolved-import-recovery.rs:3:5
+ |
+LL | use unresolved_crate::module::Name;
+ | ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
+ |
+ = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
new file mode 100644
index 000000000..956583093
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
@@ -0,0 +1,5 @@
+// compile-flags: --extern zip=whatever.rlib
+#![deny(rustdoc::broken_intra_doc_links)]
+/// See [zip] crate.
+//~^ ERROR unresolved
+pub struct ArrayZip;
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
new file mode 100644
index 000000000..5c0df1d1b
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `zip`
+ --> $DIR/unused-extern-crate.rs:3:10
+ |
+LL | /// See [zip] crate.
+ | ^^^ no item named `zip` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/unused-extern-crate.rs:2:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/warning-crlf.rs b/src/test/rustdoc-ui/intra-doc/warning-crlf.rs
new file mode 100644
index 000000000..ceb62f6d1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/warning-crlf.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-cr
+// check-pass
+
+// This file checks the spans of intra-link warnings in a file with CRLF line endings. The
+// .gitattributes file in this directory should enforce it.
+
+/// [error]
+pub struct A;
+//~^^ WARNING `error`
+
+///
+/// docs [error1]
+//~^ WARNING `error1`
+
+/// docs [error2]
+///
+pub struct B;
+//~^^^ WARNING `error2`
+
+/**
+ * This is a multi-line comment.
+ *
+ * It also has an [error].
+ */
+pub struct C;
+//~^^^ WARNING `error`
diff --git a/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr
new file mode 100644
index 000000000..d46df9264
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr
@@ -0,0 +1,35 @@
+warning: unresolved link to `error`
+ --> $DIR/warning-crlf.rs:7:6
+ |
+LL | /// [error]
+ | ^^^^^ no item named `error` in scope
+ |
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error1`
+ --> $DIR/warning-crlf.rs:12:11
+ |
+LL | /// docs [error1]
+ | ^^^^^^ no item named `error1` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error2`
+ --> $DIR/warning-crlf.rs:15:11
+ |
+LL | /// docs [error2]
+ | ^^^^^^ no item named `error2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error`
+ --> $DIR/warning-crlf.rs:23:20
+ |
+LL | * It also has an [error].
+ | ^^^^^ no item named `error` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 4 warnings emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/warning.rs b/src/test/rustdoc-ui/intra-doc/warning.rs
new file mode 100644
index 000000000..eab1f0348
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/warning.rs
@@ -0,0 +1,84 @@
+// check-pass
+
+ //! Test with [Foo::baz], [Bar::foo], ...
+//~^ WARNING `Foo::baz`
+//~| WARNING `Bar::foo`
+ //! , [Uniooon::X] and [Qux::Z].
+//~^ WARNING `Uniooon::X`
+//~| WARNING `Qux::Z`
+ //!
+ //! , [Uniooon::X] and [Qux::Z].
+//~^ WARNING `Uniooon::X`
+//~| WARNING `Qux::Z`
+
+ /// [Qux:Y]
+//~^ WARNING `Qux:Y`
+pub struct Foo {
+ pub bar: usize,
+}
+
+/// Foo
+/// bar [BarA] bar //~ WARNING `BarA`
+/// baz
+pub fn a() {}
+
+/**
+ * Foo
+ * bar [BarB] bar //~ WARNING `BarB`
+ * baz
+ */
+pub fn b() {}
+
+/** Foo
+
+bar [BarC] bar //~ WARNING `BarC`
+baz
+
+ let bar_c_1 = 0;
+ let bar_c_2 = 0;
+ let g = [bar_c_1];
+ let h = g[bar_c_2];
+
+*/
+pub fn c() {}
+
+#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `BarD`
+pub fn d() {}
+
+macro_rules! f {
+ ($f:expr) => {
+ #[doc = $f] //~ WARNING `BarF`
+ pub fn f() {}
+ }
+}
+f!("Foo\nbar [BarF] bar\nbaz");
+
+/** # for example,
+ *
+ * time to introduce a link [error]*/ //~ WARNING `error`
+pub struct A;
+
+/**
+ * # for example,
+ *
+ * time to introduce a link [error] //~ WARNING `error`
+ */
+pub struct B;
+
+#[doc = "single line [error]"] //~ WARNING `error`
+pub struct C;
+
+#[doc = "single line with \"escaping\" [error]"] //~ WARNING `error`
+pub struct D;
+
+/// Item docs. //~ WARNING `error`
+#[doc="Hello there!"]
+/// [error]
+pub struct E;
+
+///
+/// docs [error1] //~ WARNING `error1`
+
+/// docs [error2] //~ WARNING `error2`
+///
+pub struct F;
diff --git a/src/test/rustdoc-ui/intra-doc/warning.stderr b/src/test/rustdoc-ui/intra-doc/warning.stderr
new file mode 100644
index 000000000..19399a0df
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/warning.stderr
@@ -0,0 +1,175 @@
+warning: unresolved link to `Foo::baz`
+ --> $DIR/warning.rs:3:23
+ |
+LL | //! Test with [Foo::baz], [Bar::foo], ...
+ | ^^^^^^^^ the struct `Foo` has no field or associated item named `baz`
+ |
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: unresolved link to `Bar::foo`
+ --> $DIR/warning.rs:3:35
+ |
+LL | //! Test with [Foo::baz], [Bar::foo], ...
+ | ^^^^^^^^ no item named `Bar` in scope
+
+warning: unresolved link to `Uniooon::X`
+ --> $DIR/warning.rs:6:13
+ |
+LL | //! , [Uniooon::X] and [Qux::Z].
+ | ^^^^^^^^^^ no item named `Uniooon` in scope
+
+warning: unresolved link to `Qux::Z`
+ --> $DIR/warning.rs:6:30
+ |
+LL | //! , [Uniooon::X] and [Qux::Z].
+ | ^^^^^^ no item named `Qux` in scope
+
+warning: unresolved link to `Uniooon::X`
+ --> $DIR/warning.rs:10:14
+ |
+LL | //! , [Uniooon::X] and [Qux::Z].
+ | ^^^^^^^^^^ no item named `Uniooon` in scope
+
+warning: unresolved link to `Qux::Z`
+ --> $DIR/warning.rs:10:31
+ |
+LL | //! , [Uniooon::X] and [Qux::Z].
+ | ^^^^^^ no item named `Qux` in scope
+
+warning: unresolved link to `Qux:Y`
+ --> $DIR/warning.rs:14:13
+ |
+LL | /// [Qux:Y]
+ | ^^^^^ no item named `Qux:Y` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarA`
+ --> $DIR/warning.rs:21:10
+ |
+LL | /// bar [BarA] bar
+ | ^^^^ no item named `BarA` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarB`
+ --> $DIR/warning.rs:27:9
+ |
+LL | * bar [BarB] bar
+ | ^^^^ no item named `BarB` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarC`
+ --> $DIR/warning.rs:34:6
+ |
+LL | bar [BarC] bar
+ | ^^^^ no item named `BarC` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarD`
+ --> $DIR/warning.rs:45:1
+ |
+LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the link appears in this line:
+
+ bar [BarD] bar
+ ^^^^
+ = note: no item named `BarD` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `BarF`
+ --> $DIR/warning.rs:50:9
+ |
+LL | #[doc = $f]
+ | ^^^^^^^^^^^
+...
+LL | f!("Foo\nbar [BarF] bar\nbaz");
+ | ------------------------------ in this macro invocation
+ |
+ = note: the link appears in this line:
+
+ bar [BarF] bar
+ ^^^^
+ = note: no item named `BarF` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+ = note: this warning originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unresolved link to `error`
+ --> $DIR/warning.rs:58:30
+ |
+LL | * time to introduce a link [error]*/
+ | ^^^^^ no item named `error` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error`
+ --> $DIR/warning.rs:64:30
+ |
+LL | * time to introduce a link [error]
+ | ^^^^^ no item named `error` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error`
+ --> $DIR/warning.rs:68:1
+ |
+LL | #[doc = "single line [error]"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the link appears in this line:
+
+ single line [error]
+ ^^^^^
+ = note: no item named `error` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error`
+ --> $DIR/warning.rs:71:1
+ |
+LL | #[doc = "single line with \"escaping\" [error]"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the link appears in this line:
+
+ single line with "escaping" [error]
+ ^^^^^
+ = note: no item named `error` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error`
+ --> $DIR/warning.rs:74:1
+ |
+LL | / /// Item docs.
+LL | | #[doc="Hello there!"]
+LL | | /// [error]
+ | |___________^
+ |
+ = note: the link appears in this line:
+
+ [error]
+ ^^^^^
+ = note: no item named `error` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error1`
+ --> $DIR/warning.rs:80:11
+ |
+LL | /// docs [error1]
+ | ^^^^^^ no item named `error1` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `error2`
+ --> $DIR/warning.rs:82:11
+ |
+LL | /// docs [error2]
+ | ^^^^^^ no item named `error2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 19 warnings emitted
+