about summary refs log tree commit diff
path: root/tests/rustdoc-ui/lints
diff options
context:
space:
mode:
authorjyn <github@jyn.dev>2023-04-29 04:25:04 -0500
committerjyn <github@jyn.dev>2023-04-29 11:36:19 -0500
commit5da288f842f5616d58dc98338a833addf8a3cb2b (patch)
tree2f8b35318ecc63e80b7483bd2740a7af96c91564 /tests/rustdoc-ui/lints
parent5fa975142f98939222e12e8ca1338185cc7feb1c (diff)
downloadrust-5da288f842f5616d58dc98338a833addf8a3cb2b.tar.gz
rust-5da288f842f5616d58dc98338a833addf8a3cb2b.zip
move lint tests into subdirectories
Diffstat (limited to 'tests/rustdoc-ui/lints')
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.fixed60
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.rs60
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.stderr143
-rw-r--r--tests/rustdoc-ui/lints/check-attr.rs41
-rw-r--r--tests/rustdoc-ui/lints/check-attr.stderr175
-rw-r--r--tests/rustdoc-ui/lints/check-fail.rs23
-rw-r--r--tests/rustdoc-ui/lints/check-fail.stderr56
-rw-r--r--tests/rustdoc-ui/lints/check.rs15
-rw-r--r--tests/rustdoc-ui/lints/check.stderr61
-rw-r--r--tests/rustdoc-ui/lints/deny-missing-docs-crate.rs3
-rw-r--r--tests/rustdoc-ui/lints/deny-missing-docs-crate.stderr22
-rw-r--r--tests/rustdoc-ui/lints/deny-missing-docs-macro.rs8
-rw-r--r--tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr14
-rw-r--r--tests/rustdoc-ui/lints/doc-attr.rs25
-rw-r--r--tests/rustdoc-ui/lints/doc-attr.stderr71
-rw-r--r--tests/rustdoc-ui/lints/doc-spotlight.fixed8
-rw-r--r--tests/rustdoc-ui/lints/doc-spotlight.rs8
-rw-r--r--tests/rustdoc-ui/lints/doc-spotlight.stderr19
-rw-r--r--tests/rustdoc-ui/lints/doc-without-codeblock.rs23
-rw-r--r--tests/rustdoc-ui/lints/doc-without-codeblock.stderr38
-rw-r--r--tests/rustdoc-ui/lints/doc_cfg_hide.rs11
-rw-r--r--tests/rustdoc-ui/lints/doc_cfg_hide.stderr40
-rw-r--r--tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs157
-rw-r--r--tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr28
-rw-r--r--tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs12
-rw-r--r--tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr37
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.rs32
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.stderr78
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-self-closing-tag.rs70
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-self-closing-tag.stderr80
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-tags.rs123
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-tags.stderr104
-rw-r--r--tests/rustdoc-ui/lints/lint-group.rs32
-rw-r--r--tests/rustdoc-ui/lints/lint-group.stderr54
-rw-r--r--tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs101
-rw-r--r--tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr38
-rw-r--r--tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs6
-rw-r--r--tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr12
-rw-r--r--tests/rustdoc-ui/lints/renamed-lint-still-applies.rs10
-rw-r--r--tests/rustdoc-ui/lints/renamed-lint-still-applies.stderr42
-rw-r--r--tests/rustdoc-ui/lints/rustdoc-all-only-stable-lints.rs6
-rw-r--r--tests/rustdoc-ui/lints/unknown-renamed-lints.rs24
-rw-r--r--tests/rustdoc-ui/lints/unknown-renamed-lints.stderr62
-rw-r--r--tests/rustdoc-ui/lints/unused-braces-lint.rs14
-rw-r--r--tests/rustdoc-ui/lints/unused.rs14
45 files changed, 2060 insertions, 0 deletions
diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed
new file mode 100644
index 00000000000..23aa5c44c21
--- /dev/null
+++ b/tests/rustdoc-ui/lints/bare-urls.fixed
@@ -0,0 +1,60 @@
+// run-rustfix
+
+#![deny(rustdoc::bare_urls)]
+
+/// <https://somewhere.com>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com/a>
+//~^ ERROR this URL is not a hyperlink
+/// <https://www.somewhere.com>
+//~^ ERROR this URL is not a hyperlink
+/// <https://www.somewhere.com/a>
+//~^ ERROR this URL is not a hyperlink
+/// <https://subdomain.example.com>
+//~^ ERROR not a hyperlink
+/// <https://somewhere.com?>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com/a?>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com?hello=12>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com/a?hello=12>
+//~^ ERROR this URL is not a hyperlink
+/// <https://example.com?hello=12#xyz>
+//~^ ERROR this URL is not a hyperlink
+/// <https://example.com/a?hello=12#xyz>
+//~^ ERROR this URL is not a hyperlink
+/// <https://example.com#xyz>
+//~^ ERROR this URL is not a hyperlink
+/// <https://example.com/a#xyz>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com?hello=12&bye=11>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com/a?hello=12&bye=11>
+//~^ ERROR this URL is not a hyperlink
+/// <https://somewhere.com?hello=12&bye=11#xyz>
+//~^ ERROR this URL is not a hyperlink
+/// hey! <https://somewhere.com/a?hello=12&bye=11#xyz>
+//~^ ERROR this URL is not a hyperlink
+pub fn c() {}
+
+/// <https://somewhere.com>
+/// [a](http://a.com)
+/// [b]
+///
+/// [b]: http://b.com
+///
+/// ```
+/// This link should not be linted: http://example.com
+///
+/// Nor this one: <http://example.com> or this one: [x](http://example.com)
+/// ```
+///
+/// [should_not.lint](should_not.lint)
+pub fn everything_is_fine_here() {}
+
+#[allow(rustdoc::bare_urls)]
+pub mod foo {
+    /// https://somewhere.com/a?hello=12&bye=11#xyz
+    pub fn bar() {}
+}
diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs
new file mode 100644
index 00000000000..592f57343bc
--- /dev/null
+++ b/tests/rustdoc-ui/lints/bare-urls.rs
@@ -0,0 +1,60 @@
+// run-rustfix
+
+#![deny(rustdoc::bare_urls)]
+
+/// https://somewhere.com
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com/a
+//~^ ERROR this URL is not a hyperlink
+/// https://www.somewhere.com
+//~^ ERROR this URL is not a hyperlink
+/// https://www.somewhere.com/a
+//~^ ERROR this URL is not a hyperlink
+/// https://subdomain.example.com
+//~^ ERROR not a hyperlink
+/// https://somewhere.com?
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com/a?
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com?hello=12
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com/a?hello=12
+//~^ ERROR this URL is not a hyperlink
+/// https://example.com?hello=12#xyz
+//~^ ERROR this URL is not a hyperlink
+/// https://example.com/a?hello=12#xyz
+//~^ ERROR this URL is not a hyperlink
+/// https://example.com#xyz
+//~^ ERROR this URL is not a hyperlink
+/// https://example.com/a#xyz
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com?hello=12&bye=11
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com/a?hello=12&bye=11
+//~^ ERROR this URL is not a hyperlink
+/// https://somewhere.com?hello=12&bye=11#xyz
+//~^ ERROR this URL is not a hyperlink
+/// hey! https://somewhere.com/a?hello=12&bye=11#xyz
+//~^ ERROR this URL is not a hyperlink
+pub fn c() {}
+
+/// <https://somewhere.com>
+/// [a](http://a.com)
+/// [b]
+///
+/// [b]: http://b.com
+///
+/// ```
+/// This link should not be linted: http://example.com
+///
+/// Nor this one: <http://example.com> or this one: [x](http://example.com)
+/// ```
+///
+/// [should_not.lint](should_not.lint)
+pub fn everything_is_fine_here() {}
+
+#[allow(rustdoc::bare_urls)]
+pub mod foo {
+    /// https://somewhere.com/a?hello=12&bye=11#xyz
+    pub fn bar() {}
+}
diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr
new file mode 100644
index 00000000000..ccf52cd0b93
--- /dev/null
+++ b/tests/rustdoc-ui/lints/bare-urls.stderr
@@ -0,0 +1,143 @@
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:5:5
+   |
+LL | /// https://somewhere.com
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+note: the lint level is defined here
+  --> $DIR/bare-urls.rs:3:9
+   |
+LL | #![deny(rustdoc::bare_urls)]
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:7:5
+   |
+LL | /// https://somewhere.com/a
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:9:5
+   |
+LL | /// https://www.somewhere.com
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://www.somewhere.com>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:11:5
+   |
+LL | /// https://www.somewhere.com/a
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://www.somewhere.com/a>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:13:5
+   |
+LL | /// https://subdomain.example.com
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://subdomain.example.com>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:15:5
+   |
+LL | /// https://somewhere.com?
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:17:5
+   |
+LL | /// https://somewhere.com/a?
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:19:5
+   |
+LL | /// https://somewhere.com?hello=12
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:21:5
+   |
+LL | /// https://somewhere.com/a?hello=12
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:23:5
+   |
+LL | /// https://example.com?hello=12#xyz
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com?hello=12#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:25:5
+   |
+LL | /// https://example.com/a?hello=12#xyz
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com/a?hello=12#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:27:5
+   |
+LL | /// https://example.com#xyz
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:29:5
+   |
+LL | /// https://example.com/a#xyz
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com/a#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:31:5
+   |
+LL | /// https://somewhere.com?hello=12&bye=11
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12&bye=11>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:33:5
+   |
+LL | /// https://somewhere.com/a?hello=12&bye=11
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12&bye=11>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:35:5
+   |
+LL | /// https://somewhere.com?hello=12&bye=11#xyz
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12&bye=11#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:37:10
+   |
+LL | /// hey! https://somewhere.com/a?hello=12&bye=11#xyz
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12&bye=11#xyz>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: aborting due to 17 previous errors
+
diff --git a/tests/rustdoc-ui/lints/check-attr.rs b/tests/rustdoc-ui/lints/check-attr.rs
new file mode 100644
index 00000000000..0b3f7bedda5
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check-attr.rs
@@ -0,0 +1,41 @@
+#![deny(rustdoc::invalid_codeblock_attributes)]
+
+/// foo
+//~^ ERROR
+//~^^ ERROR
+//~^^^ ERROR
+///
+/// ```compile-fail,compilefail,comPile_fail
+/// boo
+/// ```
+pub fn foo() {}
+
+/// bar
+//~^ ERROR
+//~^^ ERROR
+//~^^^ ERROR
+///
+/// ```should-panic,shouldpanic,sHould_panic
+/// boo
+/// ```
+pub fn bar() {}
+
+/// foobar
+//~^ ERROR
+//~^^ ERROR
+//~^^^ ERROR
+///
+/// ```no-run,norun,no_Run
+/// boo
+/// ```
+pub fn foobar() {}
+
+/// b
+//~^ ERROR
+//~^^ ERROR
+//~^^^ ERROR
+///
+/// ```test-harness,testharness,teSt_harness
+/// boo
+/// ```
+pub fn b() {}
diff --git a/tests/rustdoc-ui/lints/check-attr.stderr b/tests/rustdoc-ui/lints/check-attr.stderr
new file mode 100644
index 00000000000..f66e63ab727
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check-attr.stderr
@@ -0,0 +1,175 @@
+error: unknown attribute `compile-fail`. Did you mean `compile_fail`?
+  --> $DIR/check-attr.rs:3:1
+   |
+LL | / /// foo
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+note: the lint level is defined here
+  --> $DIR/check-attr.rs:1:9
+   |
+LL | #![deny(rustdoc::invalid_codeblock_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unknown attribute `compilefail`. Did you mean `compile_fail`?
+  --> $DIR/check-attr.rs:3:1
+   |
+LL | / /// foo
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+
+error: unknown attribute `comPile_fail`. Did you mean `compile_fail`?
+  --> $DIR/check-attr.rs:3:1
+   |
+LL | / /// foo
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+
+error: unknown attribute `should-panic`. Did you mean `should_panic`?
+  --> $DIR/check-attr.rs:13:1
+   |
+LL | / /// bar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `shouldpanic`. Did you mean `should_panic`?
+  --> $DIR/check-attr.rs:13:1
+   |
+LL | / /// bar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `sHould_panic`. Did you mean `should_panic`?
+  --> $DIR/check-attr.rs:13:1
+   |
+LL | / /// bar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `no-run`. Did you mean `no_run`?
+  --> $DIR/check-attr.rs:23:1
+   |
+LL | / /// foobar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `norun`. Did you mean `no_run`?
+  --> $DIR/check-attr.rs:23:1
+   |
+LL | / /// foobar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `no_Run`. Did you mean `no_run`?
+  --> $DIR/check-attr.rs:23:1
+   |
+LL | / /// foobar
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `test-harness`. Did you mean `test_harness`?
+  --> $DIR/check-attr.rs:33:1
+   |
+LL | / /// b
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-attr.rs:33:1
+   |
+LL | / /// b
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: unknown attribute `teSt_harness`. Did you mean `test_harness`?
+  --> $DIR/check-attr.rs:33:1
+   |
+LL | / /// b
+LL | |
+LL | |
+LL | |
+...  |
+LL | | /// boo
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/rustdoc-ui/lints/check-fail.rs b/tests/rustdoc-ui/lints/check-fail.rs
new file mode 100644
index 00000000000..02632b4ce7d
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check-fail.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z unstable-options --check
+
+#![feature(rustdoc_missing_doc_code_examples)]
+#![deny(missing_docs)]
+#![deny(rustdoc::missing_doc_code_examples)]
+#![deny(rustdoc::all)]
+
+//! ```rust,testharness
+//~^ ERROR
+//! let x = 12;
+//! ```
+
+pub fn foo() {}
+//~^ ERROR
+//~^^ ERROR
+
+/// hello
+//~^ ERROR
+///
+/// ```rust,testharness
+/// let x = 12;
+/// ```
+pub fn bar() {}
diff --git a/tests/rustdoc-ui/lints/check-fail.stderr b/tests/rustdoc-ui/lints/check-fail.stderr
new file mode 100644
index 00000000000..f05e457af64
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check-fail.stderr
@@ -0,0 +1,56 @@
+error: missing documentation for a function
+  --> $DIR/check-fail.rs:13:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:4:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/check-fail.rs:13:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:5:9
+   |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-fail.rs:8:1
+   |
+LL | / //! ```rust,testharness
+LL | |
+LL | | //! let x = 12;
+LL | | //! ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:6:9
+   |
+LL | #![deny(rustdoc::all)]
+   |         ^^^^^^^^^^^^
+   = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-fail.rs:17:1
+   |
+LL | / /// hello
+LL | |
+LL | | ///
+LL | | /// ```rust,testharness
+LL | | /// let x = 12;
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/rustdoc-ui/lints/check.rs b/tests/rustdoc-ui/lints/check.rs
new file mode 100644
index 00000000000..e389a81bb33
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check.rs
@@ -0,0 +1,15 @@
+// check-pass
+// compile-flags: -Z unstable-options --check
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+
+#![feature(rustdoc_missing_doc_code_examples)]
+//~^ WARN
+//~^^ WARN
+
+#![warn(missing_docs)]
+#![warn(rustdoc::missing_doc_code_examples)]
+#![warn(rustdoc::all)]
+
+pub fn foo() {}
+//~^ WARN
+//~^^ WARN
diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr
new file mode 100644
index 00000000000..c5ed5d0c3ef
--- /dev/null
+++ b/tests/rustdoc-ui/lints/check.stderr
@@ -0,0 +1,61 @@
+warning: missing documentation for the crate
+  --> $DIR/check.rs:5:1
+   |
+LL | / #![feature(rustdoc_missing_doc_code_examples)]
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | pub fn foo() {}
+   | |_______________^
+   |
+note: the lint level is defined here
+  --> $DIR/check.rs:9:9
+   |
+LL | #![warn(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/check.rs:13:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+
+warning: no documentation found for this crate's top-level module
+   |
+   = help: The following guide may be of use:
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
+note: the lint level is defined here
+  --> $DIR/check.rs:11:9
+   |
+LL | #![warn(rustdoc::all)]
+   |         ^^^^^^^^^^^^
+   = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
+
+warning: missing code example in this documentation
+  --> $DIR/check.rs:5:1
+   |
+LL | / #![feature(rustdoc_missing_doc_code_examples)]
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | pub fn foo() {}
+   | |_______________^
+   |
+note: the lint level is defined here
+  --> $DIR/check.rs:10:9
+   |
+LL | #![warn(rustdoc::missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: missing code example in this documentation
+  --> $DIR/check.rs:13:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^^^^
+
+warning: 5 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/deny-missing-docs-crate.rs b/tests/rustdoc-ui/lints/deny-missing-docs-crate.rs
new file mode 100644
index 00000000000..b74eba3f66b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/deny-missing-docs-crate.rs
@@ -0,0 +1,3 @@
+#![deny(missing_docs)] //~ ERROR
+
+pub struct Foo; //~ ERROR
diff --git a/tests/rustdoc-ui/lints/deny-missing-docs-crate.stderr b/tests/rustdoc-ui/lints/deny-missing-docs-crate.stderr
new file mode 100644
index 00000000000..5025b0b0ca8
--- /dev/null
+++ b/tests/rustdoc-ui/lints/deny-missing-docs-crate.stderr
@@ -0,0 +1,22 @@
+error: missing documentation for the crate
+  --> $DIR/deny-missing-docs-crate.rs:1:1
+   |
+LL | / #![deny(missing_docs)]
+LL | |
+LL | | pub struct Foo;
+   | |_______________^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-missing-docs-crate.rs:1:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing documentation for a struct
+  --> $DIR/deny-missing-docs-crate.rs:3:1
+   |
+LL | pub struct Foo;
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/lints/deny-missing-docs-macro.rs b/tests/rustdoc-ui/lints/deny-missing-docs-macro.rs
new file mode 100644
index 00000000000..b1c1253176b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/deny-missing-docs-macro.rs
@@ -0,0 +1,8 @@
+//! foo
+
+#![deny(missing_docs)]
+
+#[macro_export]
+macro_rules! foo { //~ ERROR
+    () => {}
+}
diff --git a/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr b/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr
new file mode 100644
index 00000000000..0867b08183e
--- /dev/null
+++ b/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr
@@ -0,0 +1,14 @@
+error: missing documentation for a macro
+  --> $DIR/deny-missing-docs-macro.rs:6:1
+   |
+LL | macro_rules! foo {
+   | ^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-missing-docs-macro.rs:3:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/lints/doc-attr.rs b/tests/rustdoc-ui/lints/doc-attr.rs
new file mode 100644
index 00000000000..980d1c0e207
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-attr.rs
@@ -0,0 +1,25 @@
+#![crate_type = "lib"]
+#![deny(warnings)]
+#![doc(as_ptr)]
+//~^ ERROR unknown `doc` attribute
+//~^^ WARN
+
+#[doc(as_ptr)]
+//~^ ERROR unknown `doc` attribute
+//~^^ WARN
+pub fn foo() {}
+
+#[doc(123)]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+#[doc("hello", "bar")]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+//~| ERROR invalid `doc` attribute
+//~| WARN
+#[doc(foo::bar, crate::bar::baz = "bye")]
+//~^ ERROR unknown `doc` attribute
+//~| WARN
+//~| ERROR unknown `doc` attribute
+//~| WARN
+fn bar() {}
diff --git a/tests/rustdoc-ui/lints/doc-attr.stderr b/tests/rustdoc-ui/lints/doc-attr.stderr
new file mode 100644
index 00000000000..68df2771fd7
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-attr.stderr
@@ -0,0 +1,71 @@
+error: unknown `doc` attribute `as_ptr`
+  --> $DIR/doc-attr.rs:7:7
+   |
+LL | #[doc(as_ptr)]
+   |       ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+note: the lint level is defined here
+  --> $DIR/doc-attr.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:12:7
+   |
+LL | #[doc(123)]
+   |       ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:7
+   |
+LL | #[doc("hello", "bar")]
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:16
+   |
+LL | #[doc("hello", "bar")]
+   |                ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `foo::bar`
+  --> $DIR/doc-attr.rs:20:7
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |       ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `crate::bar::baz`
+  --> $DIR/doc-attr.rs:20:17
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `as_ptr`
+  --> $DIR/doc-attr.rs:3:8
+   |
+LL | #![doc(as_ptr)]
+   |        ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/rustdoc-ui/lints/doc-spotlight.fixed b/tests/rustdoc-ui/lints/doc-spotlight.fixed
new file mode 100644
index 00000000000..4b58778eacd
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-spotlight.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+#![deny(warnings)]
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+//~^ ERROR unknown `doc` attribute `spotlight`
+//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+trait MyTrait {}
diff --git a/tests/rustdoc-ui/lints/doc-spotlight.rs b/tests/rustdoc-ui/lints/doc-spotlight.rs
new file mode 100644
index 00000000000..16e38724580
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-spotlight.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+#![deny(warnings)]
+#![feature(doc_notable_trait)]
+
+#[doc(spotlight)]
+//~^ ERROR unknown `doc` attribute `spotlight`
+//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+trait MyTrait {}
diff --git a/tests/rustdoc-ui/lints/doc-spotlight.stderr b/tests/rustdoc-ui/lints/doc-spotlight.stderr
new file mode 100644
index 00000000000..58612327ff9
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-spotlight.stderr
@@ -0,0 +1,19 @@
+error: unknown `doc` attribute `spotlight`
+  --> $DIR/doc-spotlight.rs:5:7
+   |
+LL | #[doc(spotlight)]
+   |       ^^^^^^^^^ help: use `notable_trait` instead
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
+   = note: `doc(spotlight)` is now a no-op
+note: the lint level is defined here
+  --> $DIR/doc-spotlight.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.rs b/tests/rustdoc-ui/lints/doc-without-codeblock.rs
new file mode 100644
index 00000000000..86d7c83d335
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-without-codeblock.rs
@@ -0,0 +1,23 @@
+#![feature(rustdoc_missing_doc_code_examples)] //~ ERROR missing code example in this documentation
+#![deny(rustdoc::missing_doc_code_examples)]
+
+/// Some docs.
+//~^ ERROR missing code example in this documentation
+pub struct Foo;
+
+/// And then, the princess died.
+//~^ ERROR missing code example in this documentation
+pub mod foo {
+    /// Or maybe not because she saved herself!
+    //~^ ERROR missing code example in this documentation
+    pub fn bar() {}
+}
+
+// This impl is here to ensure the lint isn't emitted for foreign traits implementations.
+impl std::ops::Neg for Foo {
+    type Output = Self;
+
+    fn neg(self) -> Self::Output {
+        Self
+    }
+}
diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.stderr b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr
new file mode 100644
index 00000000000..ebf2a2d54f7
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr
@@ -0,0 +1,38 @@
+error: missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:1:1
+   |
+LL | / #![feature(rustdoc_missing_doc_code_examples)]
+LL | | #![deny(rustdoc::missing_doc_code_examples)]
+LL | |
+LL | | /// Some docs.
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: the lint level is defined here
+  --> $DIR/doc-without-codeblock.rs:2:9
+   |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:8:1
+   |
+LL | /// And then, the princess died.
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:11:5
+   |
+LL |     /// Or maybe not because she saved herself!
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:4:1
+   |
+LL | /// Some docs.
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.rs b/tests/rustdoc-ui/lints/doc_cfg_hide.rs
new file mode 100644
index 00000000000..5d8791748a0
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc_cfg_hide.rs
@@ -0,0 +1,11 @@
+#![feature(doc_cfg_hide)]
+#![deny(warnings)]
+
+#![doc(cfg_hide = "test")] //~ ERROR
+//~^ WARN
+#![doc(cfg_hide)] //~ ERROR
+//~^ WARN
+
+#[doc(cfg_hide(doc))] //~ ERROR
+//~^ WARN
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
new file mode 100644
index 00000000000..b7e8870fdf5
--- /dev/null
+++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
@@ -0,0 +1,40 @@
+error: this attribute can only be applied at the crate level
+  --> $DIR/doc_cfg_hide.rs:9:7
+   |
+LL | #[doc(cfg_hide(doc))]
+   |       ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+note: the lint level is defined here
+  --> $DIR/doc_cfg_hide.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+help: to apply to the crate, use an inner attribute
+   |
+LL | #![doc(cfg_hide(doc))]
+   |  +
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+  --> $DIR/doc_cfg_hide.rs:4:8
+   |
+LL | #![doc(cfg_hide = "test")]
+   |        ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+  --> $DIR/doc_cfg_hide.rs:6:8
+   |
+LL | #![doc(cfg_hide)]
+   |        ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs
new file mode 100644
index 00000000000..0901ac3640f
--- /dev/null
+++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs
@@ -0,0 +1,157 @@
+// check-pass
+#![feature(lint_reasons)]
+
+//! This file tests the `#[expect]` attribute implementation for tool lints. The same
+//! file is used to test clippy and rustdoc. Any changes to this file should be synced
+//! to the other test files as well.
+//!
+//! Expectations:
+//! * rustc: only rustc lint expectations are emitted
+//! * clippy: rustc and Clippy's expectations are emitted
+//! * rustdoc: only rustdoc lint expectations are emitted
+//!
+//! This test can't cover every lint from Clippy, rustdoc and potentially other
+//! tools that will be developed. This therefore only tests a small subset of lints
+
+#![expect(rustdoc::missing_crate_level_docs)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+
+mod rustc_ok {
+    //! See <https://doc.rust-lang.org/rustc/lints/index.html>
+
+    #[expect(dead_code)]
+    pub fn rustc_lints() {
+        let x = 42.0;
+
+        #[expect(illegal_floating_point_literal_pattern)]
+        match x {
+            5.0 => {}
+            6.0 => {}
+            _ => {}
+        }
+    }
+}
+
+mod rustc_warn {
+    //! See <https://doc.rust-lang.org/rustc/lints/index.html>
+
+    #[expect(dead_code)]
+    pub fn rustc_lints() {
+        let x = 42;
+
+        #[expect(illegal_floating_point_literal_pattern)]
+        match x {
+            5 => {}
+            6 => {}
+            _ => {}
+        }
+    }
+}
+
+pub mod rustdoc_ok {
+    //! See <https://doc.rust-lang.org/rustdoc/lints.html>
+
+    #[expect(rustdoc::broken_intra_doc_links)]
+    /// I want to link to [`Nonexistent`] but it doesn't exist!
+    pub fn foo() {}
+
+    #[expect(rustdoc::invalid_html_tags)]
+    /// <h1>
+    pub fn bar() {}
+
+    #[expect(rustdoc::bare_urls)]
+    /// http://example.org
+    pub fn baz() {}
+}
+
+pub mod rustdoc_warn {
+    //! See <https://doc.rust-lang.org/rustdoc/lints.html>
+
+    #[expect(rustdoc::broken_intra_doc_links)]
+    //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+    /// I want to link to [`bar`] but it doesn't exist!
+    pub fn foo() {}
+
+    #[expect(rustdoc::invalid_html_tags)]
+    //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+    /// <h1></h1>
+    pub fn bar() {}
+
+    #[expect(rustdoc::bare_urls)]
+    //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+    /// <http://example.org>
+    pub fn baz() {}
+}
+
+mod clippy_ok {
+    //! See <https://rust-lang.github.io/rust-clippy/master/index.html>
+
+    #[expect(clippy::almost_swapped)]
+    fn foo() {
+        let mut a = 0;
+        let mut b = 9;
+        a = b;
+        b = a;
+    }
+
+    #[expect(clippy::bytes_nth)]
+    fn bar() {
+        let _ = "Hello".bytes().nth(3);
+    }
+
+    #[expect(clippy::if_same_then_else)]
+    fn baz() {
+        let _ = if true {
+            42
+        } else {
+            42
+        };
+    }
+
+    #[expect(clippy::logic_bug)]
+    fn burger() {
+        let a = false;
+        let b = true;
+
+        if a && b || a {}
+    }
+}
+
+mod clippy_warn {
+    //! See <https://rust-lang.github.io/rust-clippy/master/index.html>
+
+    #[expect(clippy::almost_swapped)]
+    fn foo() {
+        let mut a = 0;
+        let mut b = 9;
+        a = b;
+    }
+
+    #[expect(clippy::bytes_nth)]
+    fn bar() {
+        let _ = "Hello".as_bytes().get(3);
+    }
+
+    #[expect(clippy::if_same_then_else)]
+    fn baz() {
+        let _ = if true {
+            33
+        } else {
+            42
+        };
+    }
+
+    #[expect(clippy::logic_bug)]
+    fn burger() {
+        let a = false;
+        let b = true;
+        let c = false;
+
+        if a && b || c {}
+    }
+}
+
+fn main() {
+    rustc_warn::rustc_lints();
+}
diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr
new file mode 100644
index 00000000000..efc5f349f4f
--- /dev/null
+++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr
@@ -0,0 +1,28 @@
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect-tool-lint-rfc-2383.rs:16:11
+   |
+LL | #![expect(rustdoc::missing_crate_level_docs)]
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect-tool-lint-rfc-2383.rs:71:14
+   |
+LL |     #[expect(rustdoc::broken_intra_doc_links)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect-tool-lint-rfc-2383.rs:76:14
+   |
+LL |     #[expect(rustdoc::invalid_html_tags)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect-tool-lint-rfc-2383.rs:81:14
+   |
+LL |     #[expect(rustdoc::bare_urls)]
+   |              ^^^^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs
new file mode 100644
index 00000000000..c34ea0567a9
--- /dev/null
+++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs
@@ -0,0 +1,12 @@
+#![deny(unknown_lints)]
+//~^ NOTE defined here
+#![allow(rustdoc::missing_doc_code_examples)]
+//~^ ERROR unknown lint
+//~| ERROR unknown lint
+//~| ERROR unknown lint
+//~| NOTE lint is unstable
+//~| NOTE lint is unstable
+//~| NOTE lint is unstable
+//~| NOTE see issue
+//~| NOTE see issue
+//~| NOTE see issue
diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr
new file mode 100644
index 00000000000..326dcfe3bde
--- /dev/null
+++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr
@@ -0,0 +1,37 @@
+error: unknown lint: `rustdoc::missing_doc_code_examples`
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
+   |
+LL | #![allow(rustdoc::missing_doc_code_examples)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `rustdoc::missing_doc_code_examples` lint is unstable
+   = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
+   = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
+note: the lint level is defined here
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9
+   |
+LL | #![deny(unknown_lints)]
+   |         ^^^^^^^^^^^^^
+
+error: unknown lint: `rustdoc::missing_doc_code_examples`
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
+   |
+LL | #![allow(rustdoc::missing_doc_code_examples)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `rustdoc::missing_doc_code_examples` lint is unstable
+   = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
+   = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
+
+error: unknown lint: `rustdoc::missing_doc_code_examples`
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
+   |
+LL | #![allow(rustdoc::missing_doc_code_examples)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `rustdoc::missing_doc_code_examples` lint is unstable
+   = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
+   = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
new file mode 100644
index 00000000000..c231e43b35c
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
@@ -0,0 +1,32 @@
+#![crate_type = "lib"]
+#![deny(warnings)]
+
+#[doc(test(no_crate_inject))]
+//~^ ERROR can only be applied at the crate level
+//~| WARN is being phased out
+//~| HELP to apply to the crate, use an inner attribute
+//~| SUGGESTION !
+#[doc(inline)]
+//~^ ERROR can only be applied to a `use` item
+//~| WARN is being phased out
+pub fn foo() {}
+
+pub mod bar {
+    #![doc(test(no_crate_inject))]
+    //~^ ERROR can only be applied at the crate level
+    //~| WARN is being phased out
+
+    #[doc(test(no_crate_inject))]
+    //~^ ERROR can only be applied at the crate level
+    //~| WARN is being phased out
+    #[doc(inline)]
+    //~^ ERROR can only be applied to a `use` item
+    //~| WARN is being phased out
+    pub fn baz() {}
+}
+
+#[doc(inline)]
+#[doc(no_inline)]
+//~^^ ERROR conflicting doc inlining attributes
+//~|  HELP remove one of the conflicting attributes
+pub use bar::baz;
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
new file mode 100644
index 00000000000..b23b8ded867
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
@@ -0,0 +1,78 @@
+error: this attribute can only be applied at the crate level
+  --> $DIR/invalid-doc-attr.rs:4:7
+   |
+LL | #[doc(test(no_crate_inject))]
+   |       ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+note: the lint level is defined here
+  --> $DIR/invalid-doc-attr.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+help: to apply to the crate, use an inner attribute
+   |
+LL | #![doc(test(no_crate_inject))]
+   |  +
+
+error: this attribute can only be applied to a `use` item
+  --> $DIR/invalid-doc-attr.rs:9:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^ only applicable on `use` items
+...
+LL | pub fn foo() {}
+   | ------------ not a `use` item
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+error: this attribute can only be applied at the crate level
+  --> $DIR/invalid-doc-attr.rs:15:12
+   |
+LL |     #![doc(test(no_crate_inject))]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+
+error: conflicting doc inlining attributes
+  --> $DIR/invalid-doc-attr.rs:28:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^ this attribute...
+LL | #[doc(no_inline)]
+   |       ^^^^^^^^^ ...conflicts with this attribute
+   |
+   = help: remove one of the conflicting attributes
+
+error: this attribute can only be applied at the crate level
+  --> $DIR/invalid-doc-attr.rs:19:11
+   |
+LL |     #[doc(test(no_crate_inject))]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+
+error: this attribute can only be applied to a `use` item
+  --> $DIR/invalid-doc-attr.rs:22:11
+   |
+LL |     #[doc(inline)]
+   |           ^^^^^^ only applicable on `use` items
+...
+LL |     pub fn baz() {}
+   |     ------------ not a `use` item
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.rs b/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.rs
new file mode 100644
index 00000000000..d973a53cbc7
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.rs
@@ -0,0 +1,70 @@
+#![deny(rustdoc::invalid_html_tags)]
+
+/// <p/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct A;
+
+/// <p style/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct B;
+
+/// <p style=""/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct C;
+
+/// <p style="x"/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct D;
+
+/// <p style="x/></p>
+//~^ ERROR unclosed quoted HTML attribute
+pub struct E;
+
+/// <p style='x/></p>
+//~^ ERROR unclosed quoted HTML attribute
+pub struct F;
+
+/// <p style="x/"></p>
+pub struct G;
+
+/// <p style="x/"/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct H;
+
+/// <p / >
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct I;
+
+/// <br/>
+pub struct J;
+
+/// <a href=/></a>
+pub struct K;
+
+/// <a href=//></a>
+pub struct L;
+
+/// <a href="/"/>
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct M;
+
+/// <a href=x />
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct N;
+
+/// <a href= />
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct O;
+
+/// <a href=x/></a>
+pub struct P;
+
+/// <svg><rect width=1 height=1 /></svg>
+pub struct Q;
+
+/// <svg><rect width=1 height=/></svg>
+//~^ ERROR unclosed HTML tag `rect`
+pub struct R;
+
+/// <svg / q>
+pub struct S;
diff --git a/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.stderr b/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.stderr
new file mode 100644
index 00000000000..e45edfb43ff
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-html-self-closing-tag.stderr
@@ -0,0 +1,80 @@
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:3:5
+   |
+LL | /// <p/>
+   |     ^^
+   |
+note: the lint level is defined here
+  --> $DIR/invalid-html-self-closing-tag.rs:1:9
+   |
+LL | #![deny(rustdoc::invalid_html_tags)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:7:5
+   |
+LL | /// <p style/>
+   |     ^^
+
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:11:5
+   |
+LL | /// <p style=""/>
+   |     ^^
+
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:15:5
+   |
+LL | /// <p style="x"/>
+   |     ^^
+
+error: unclosed quoted HTML attribute on tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:19:14
+   |
+LL | /// <p style="x/></p>
+   |              ^
+
+error: unclosed quoted HTML attribute on tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:23:14
+   |
+LL | /// <p style='x/></p>
+   |              ^
+
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:30:5
+   |
+LL | /// <p style="x/"/>
+   |     ^^
+
+error: invalid self-closing HTML tag `p`
+  --> $DIR/invalid-html-self-closing-tag.rs:34:5
+   |
+LL | /// <p / >
+   |     ^^
+
+error: invalid self-closing HTML tag `a`
+  --> $DIR/invalid-html-self-closing-tag.rs:47:5
+   |
+LL | /// <a href="/"/>
+   |     ^^
+
+error: invalid self-closing HTML tag `a`
+  --> $DIR/invalid-html-self-closing-tag.rs:51:5
+   |
+LL | /// <a href=x />
+   |     ^^
+
+error: invalid self-closing HTML tag `a`
+  --> $DIR/invalid-html-self-closing-tag.rs:55:5
+   |
+LL | /// <a href= />
+   |     ^^
+
+error: unclosed HTML tag `rect`
+  --> $DIR/invalid-html-self-closing-tag.rs:65:10
+   |
+LL | /// <svg><rect width=1 height=/></svg>
+   |          ^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.rs b/tests/rustdoc-ui/lints/invalid-html-tags.rs
new file mode 100644
index 00000000000..317f1fd1d46
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.rs
@@ -0,0 +1,123 @@
+#![deny(rustdoc::invalid_html_tags)]
+
+//! <p>💩<p>
+//~^ ERROR unclosed HTML tag `p`
+//~^^ ERROR unclosed HTML tag `p`
+
+/// <img><input>
+/// <script>
+/// <img><input>
+/// </script>
+/// <unknown>
+//~^ ERROR unclosed HTML tag `unknown`
+/// < ok
+/// <script>
+//~^ ERROR unclosed HTML tag `script`
+pub fn foo() {}
+
+/// <h1>
+///   <h2>
+//~^ ERROR unclosed HTML tag `h2`
+///     <h3>
+//~^ ERROR unclosed HTML tag `h3`
+/// </h1>
+/// </hello>
+//~^ ERROR unopened HTML tag `hello`
+pub fn bar() {}
+
+/// <div>
+///    <br/> <p>
+//~^ ERROR unclosed HTML tag `p`
+/// </div>
+pub fn a() {}
+
+/// <div>
+///   <p>
+///      <div></div>
+///   </p>
+/// </div>
+pub fn b() {}
+
+/// <div style="hello">
+//~^ ERROR unclosed HTML tag `div`
+///   <h3>
+//~^ ERROR unclosed HTML tag `h3`
+/// <script
+//~^ ERROR unclosed HTML tag `script`
+pub fn c() {}
+
+// Unclosed tags shouldn't warn if they are nested inside a <script> elem.
+/// <script>
+///   <h3><div>
+/// </script>
+/// <script>
+///   <div>
+///     <p>
+///   </div>
+/// </script>
+pub fn d() {}
+
+// Unclosed tags shouldn't warn if they are nested inside a <style> elem.
+/// <style>
+///   <h3><div>
+/// </style>
+/// <stYle>
+///   <div>
+///     <p>
+///   </div>
+/// </style>
+pub fn e() {}
+
+// Closing tags need to have ">" at the end, otherwise it's not a closing tag!
+/// <div></div >
+/// <div></div
+//~^ ERROR unclosed HTML tag `div`
+pub fn f() {}
+
+/// <!---->
+/// <!-- -->
+/// <!-- <div> -->
+/// <!-- <!-- -->
+pub fn g() {}
+
+/// <!--
+/// -->
+pub fn h() {}
+
+/// <!--
+//~^ ERROR Unclosed HTML comment
+pub fn i() {}
+
+/// hello
+///
+/// ```
+/// uiapp.run(&env::args().collect::<Vec<_>>());
+/// ```
+pub fn j() {}
+
+// Check that nested codeblocks are working as well
+/// hello
+///
+/// ``````markdown
+/// normal markdown
+///
+/// ```
+/// uiapp.run(&env::args().collect::<Vec<_>>());
+/// ```
+///
+/// <Vec<_> shouldn't warn!
+/// ``````
+pub fn k() {}
+
+/// Web Components style <dashed-tags>
+//~^ ERROR unclosed HTML tag `dashed-tags`
+/// Web Components style </unopened-tag>
+//~^ ERROR unopened HTML tag `unopened-tag`
+pub fn m() {}
+
+/// backslashed \<a href="">
+pub fn no_error_1() {}
+
+/// backslashed \<<a href="">
+//~^ ERROR unclosed HTML tag `a`
+pub fn p() {}
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.stderr b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
new file mode 100644
index 00000000000..9c2bfcf2c3d
--- /dev/null
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
@@ -0,0 +1,104 @@
+error: unclosed HTML tag `p`
+  --> $DIR/invalid-html-tags.rs:3:5
+   |
+LL | //! <p>💩<p>
+   |     ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/invalid-html-tags.rs:1:9
+   |
+LL | #![deny(rustdoc::invalid_html_tags)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unclosed HTML tag `p`
+  --> $DIR/invalid-html-tags.rs:3:9
+   |
+LL | //! <p>💩<p>
+   |          ^^^
+
+error: unclosed HTML tag `unknown`
+  --> $DIR/invalid-html-tags.rs:11:5
+   |
+LL | /// <unknown>
+   |     ^^^^^^^^^
+
+error: unclosed HTML tag `script`
+  --> $DIR/invalid-html-tags.rs:14:5
+   |
+LL | /// <script>
+   |     ^^^^^^^^
+
+error: unclosed HTML tag `h2`
+  --> $DIR/invalid-html-tags.rs:19:7
+   |
+LL | ///   <h2>
+   |       ^^^^
+
+error: unclosed HTML tag `h3`
+  --> $DIR/invalid-html-tags.rs:21:9
+   |
+LL | ///     <h3>
+   |         ^^^^
+
+error: unopened HTML tag `hello`
+  --> $DIR/invalid-html-tags.rs:24:5
+   |
+LL | /// </hello>
+   |     ^^^^^^^^
+
+error: unclosed HTML tag `p`
+  --> $DIR/invalid-html-tags.rs:29:14
+   |
+LL | ///    <br/> <p>
+   |              ^^^
+
+error: unclosed HTML tag `div`
+  --> $DIR/invalid-html-tags.rs:41:5
+   |
+LL | /// <div style="hello">
+   |     ^^^^
+
+error: unclosed HTML tag `h3`
+  --> $DIR/invalid-html-tags.rs:43:7
+   |
+LL | ///   <h3>
+   |       ^^^^
+
+error: unclosed HTML tag `script`
+  --> $DIR/invalid-html-tags.rs:45:5
+   |
+LL | /// <script
+   |     ^^^^^^
+
+error: unclosed HTML tag `div`
+  --> $DIR/invalid-html-tags.rs:73:5
+   |
+LL | /// <div></div
+   |     ^^^^^
+
+error: Unclosed HTML comment
+  --> $DIR/invalid-html-tags.rs:87:5
+   |
+LL | /// <!--
+   |     ^^^
+
+error: unopened HTML tag `unopened-tag`
+  --> $DIR/invalid-html-tags.rs:114:26
+   |
+LL | /// Web Components style </unopened-tag>
+   |                          ^^^^^^^^^^^^^^^
+
+error: unclosed HTML tag `dashed-tags`
+  --> $DIR/invalid-html-tags.rs:112:26
+   |
+LL | /// Web Components style <dashed-tags>
+   |                          ^^^^^^^^^^^^^
+
+error: unclosed HTML tag `a`
+  --> $DIR/invalid-html-tags.rs:121:19
+   |
+LL | /// backslashed \<<a href="">
+   |                   ^^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/rustdoc-ui/lints/lint-group.rs b/tests/rustdoc-ui/lints/lint-group.rs
new file mode 100644
index 00000000000..ad88157f64f
--- /dev/null
+++ b/tests/rustdoc-ui/lints/lint-group.rs
@@ -0,0 +1,32 @@
+#![feature(rustdoc_missing_doc_code_examples)]
+
+//! Documenting the kinds of lints emitted by rustdoc.
+//!
+//! ```
+//! println!("sup");
+//! ```
+
+#![deny(rustdoc::missing_doc_code_examples)]
+#![deny(rustdoc::all)]
+
+/// what up, let's make an [error]
+///
+/// ```
+/// println!("sup");
+/// ```
+pub fn link_error() {} //~^^^^^ ERROR unresolved link to `error`
+
+/// wait, this doesn't have a doctest?
+pub fn no_doctest() {} //~^ ERROR missing code example in this documentation
+
+/// wait, this *does* have a doctest?
+///
+/// ```
+/// println!("sup");
+/// ```
+fn private_doctest() {} //~^^^^^ ERROR documentation test in private item
+
+/// <unknown>
+//~^ ERROR unclosed HTML tag `unknown`
+//~^^ ERROR missing code example
+pub fn c() {}
diff --git a/tests/rustdoc-ui/lints/lint-group.stderr b/tests/rustdoc-ui/lints/lint-group.stderr
new file mode 100644
index 00000000000..7ff09fcc45a
--- /dev/null
+++ b/tests/rustdoc-ui/lints/lint-group.stderr
@@ -0,0 +1,54 @@
+error: missing code example in this documentation
+  --> $DIR/lint-group.rs:19:1
+   |
+LL | /// wait, this doesn't have a doctest?
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-group.rs:9:9
+   |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: documentation test in private item
+  --> $DIR/lint-group.rs:22:1
+   |
+LL | / /// wait, this *does* have a doctest?
+LL | | ///
+LL | | /// ```
+LL | | /// println!("sup");
+LL | | /// ```
+   | |_______^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-group.rs:10:9
+   |
+LL | #![deny(rustdoc::all)]
+   |         ^^^^^^^^^^^^
+   = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]`
+
+error: missing code example in this documentation
+  --> $DIR/lint-group.rs:29:1
+   |
+LL | /// <unknown>
+   | ^^^^^^^^^^^^^
+
+error: unresolved link to `error`
+  --> $DIR/lint-group.rs:12:29
+   |
+LL | /// what up, let's make an [error]
+   |                             ^^^^^ no item named `error` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
+
+error: unclosed HTML tag `unknown`
+  --> $DIR/lint-group.rs:29:5
+   |
+LL | /// <unknown>
+   |     ^^^^^^^^^
+   |
+   = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc::all)]`
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs
new file mode 100644
index 00000000000..40f35728d79
--- /dev/null
+++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs
@@ -0,0 +1,101 @@
+#![feature(rustdoc_missing_doc_code_examples)]
+#![deny(missing_docs)]
+#![deny(rustdoc::missing_doc_code_examples)]
+
+//! crate level doc
+//! ```
+//! println!("hello"):
+//! ```
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+pub fn test() {
+}
+
+#[allow(missing_docs)]
+pub mod module1 { //~ ERROR
+}
+
+#[allow(rustdoc::missing_doc_code_examples)]
+/// doc
+pub mod module2 {
+
+  /// doc
+  pub fn test() {}
+}
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+pub mod module3 {
+
+  /// doc
+  //~^ ERROR
+  pub fn test() {}
+}
+
+/// Doc, but no code example and it's fine!
+pub const Const: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub static Static: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub type Type = u32;
+
+/// Doc
+//~^ ERROR
+pub struct Struct {
+    /// Doc, but no code example and it's fine!
+    pub field: u32,
+}
+
+/// Doc
+//~^ ERROR
+pub enum Enum {
+    /// Doc, but no code example and it's fine!
+    X,
+}
+
+/// Doc
+//~^ ERROR
+#[repr(C)]
+pub union Union {
+    /// Doc, but no code example and it's fine!
+    a: i32,
+    /// Doc, but no code example and it's fine!
+    b: f32,
+}
+
+// no code example and it's fine!
+impl Clone for Struct {
+    fn clone(&self) -> Self {
+        Self { field: self.field }
+    }
+}
+
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+#[derive(Clone)]
+pub struct NiceStruct;
+
+#[doc(hidden)]
+pub mod foo {
+    pub fn bar() {}
+}
+
+fn babar() {}
+
+
+mod fofoo {
+    pub fn tadam() {}
+}
diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr
new file mode 100644
index 00000000000..f9331250154
--- /dev/null
+++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr
@@ -0,0 +1,38 @@
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:20:1
+   |
+LL | pub mod module1 {
+   | ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-missing-doc-code-example.rs:3:9
+   |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:38:3
+   |
+LL |   /// doc
+   |   ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:50:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:57:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:64:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs
new file mode 100644
index 00000000000..a186410acf4
--- /dev/null
+++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs
@@ -0,0 +1,6 @@
+// error-pattern: no documentation found
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+#![deny(rustdoc::missing_crate_level_docs)]
+//^~ NOTE defined here
+
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr
new file mode 100644
index 00000000000..fb3a5e415df
--- /dev/null
+++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr
@@ -0,0 +1,12 @@
+error: no documentation found for this crate's top-level module
+   |
+   = help: The following guide may be of use:
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
+note: the lint level is defined here
+  --> $DIR/no-crate-level-doc-lint.rs:3:9
+   |
+LL | #![deny(rustdoc::missing_crate_level_docs)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/lints/renamed-lint-still-applies.rs b/tests/rustdoc-ui/lints/renamed-lint-still-applies.rs
new file mode 100644
index 00000000000..a4d3a4b4971
--- /dev/null
+++ b/tests/rustdoc-ui/lints/renamed-lint-still-applies.rs
@@ -0,0 +1,10 @@
+// compile-args: --crate-type lib
+#![deny(broken_intra_doc_links)]
+//~^ WARNING renamed to `rustdoc::broken_intra_doc_links`
+//! [x]
+//~^ ERROR unresolved link
+
+#![deny(rustdoc::non_autolinks)]
+//~^ WARNING renamed to `rustdoc::bare_urls`
+//! http://example.com
+//~^ ERROR not a hyperlink
diff --git a/tests/rustdoc-ui/lints/renamed-lint-still-applies.stderr b/tests/rustdoc-ui/lints/renamed-lint-still-applies.stderr
new file mode 100644
index 00000000000..ee9b67cb91b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/renamed-lint-still-applies.stderr
@@ -0,0 +1,42 @@
+warning: lint `broken_intra_doc_links` has been renamed to `rustdoc::broken_intra_doc_links`
+  --> $DIR/renamed-lint-still-applies.rs:2:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links`
+   |
+   = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls`
+  --> $DIR/renamed-lint-still-applies.rs:7:9
+   |
+LL | #![deny(rustdoc::non_autolinks)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
+
+error: unresolved link to `x`
+  --> $DIR/renamed-lint-still-applies.rs:4:6
+   |
+LL | //! [x]
+   |      ^ no item named `x` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+note: the lint level is defined here
+  --> $DIR/renamed-lint-still-applies.rs:2:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: this URL is not a hyperlink
+  --> $DIR/renamed-lint-still-applies.rs:9:5
+   |
+LL | //! http://example.com
+   |     ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.com>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+note: the lint level is defined here
+  --> $DIR/renamed-lint-still-applies.rs:7:9
+   |
+LL | #![deny(rustdoc::non_autolinks)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/rustdoc-all-only-stable-lints.rs b/tests/rustdoc-ui/lints/rustdoc-all-only-stable-lints.rs
new file mode 100644
index 00000000000..e106d06aff5
--- /dev/null
+++ b/tests/rustdoc-ui/lints/rustdoc-all-only-stable-lints.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+// Ensure `rustdoc::all` only affects stable lints. See #106289.
+
+#![deny(unknown_lints)]
+#![allow(rustdoc::all)]
diff --git a/tests/rustdoc-ui/lints/unknown-renamed-lints.rs b/tests/rustdoc-ui/lints/unknown-renamed-lints.rs
new file mode 100644
index 00000000000..ddf03dd079f
--- /dev/null
+++ b/tests/rustdoc-ui/lints/unknown-renamed-lints.rs
@@ -0,0 +1,24 @@
+#![deny(unknown_lints)]
+//~^ NOTE lint level is defined
+#![deny(renamed_and_removed_lints)]
+//~^ NOTE lint level is defined
+#![deny(x)]
+//~^ ERROR unknown lint
+#![deny(rustdoc::x)]
+//~^ ERROR unknown lint: `rustdoc::x`
+#![deny(intra_doc_link_resolution_failure)]
+//~^ ERROR renamed to `rustdoc::broken_intra_doc_links`
+#![deny(non_autolinks)]
+//~^ ERROR renamed to `rustdoc::bare_urls`
+#![deny(rustdoc::non_autolinks)]
+//~^ ERROR renamed to `rustdoc::bare_urls`
+
+#![deny(private_doc_tests)]
+//~^ ERROR renamed to `rustdoc::private_doc_tests`
+
+#![deny(rustdoc)]
+//~^ ERROR removed: use `rustdoc::all` instead
+
+// Explicitly don't try to handle this case, it was never valid
+#![deny(rustdoc::intra_doc_link_resolution_failure)]
+//~^ ERROR unknown lint
diff --git a/tests/rustdoc-ui/lints/unknown-renamed-lints.stderr b/tests/rustdoc-ui/lints/unknown-renamed-lints.stderr
new file mode 100644
index 00000000000..bf529b9f8e2
--- /dev/null
+++ b/tests/rustdoc-ui/lints/unknown-renamed-lints.stderr
@@ -0,0 +1,62 @@
+error: unknown lint: `x`
+  --> $DIR/unknown-renamed-lints.rs:5:9
+   |
+LL | #![deny(x)]
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-renamed-lints.rs:1:9
+   |
+LL | #![deny(unknown_lints)]
+   |         ^^^^^^^^^^^^^
+
+error: unknown lint: `rustdoc::x`
+  --> $DIR/unknown-renamed-lints.rs:7:9
+   |
+LL | #![deny(rustdoc::x)]
+   |         ^^^^^^^^^^ help: did you mean: `rustdoc::all`
+
+error: lint `intra_doc_link_resolution_failure` has been renamed to `rustdoc::broken_intra_doc_links`
+  --> $DIR/unknown-renamed-lints.rs:9:9
+   |
+LL | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links`
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-renamed-lints.rs:3:9
+   |
+LL | #![deny(renamed_and_removed_lints)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: lint `non_autolinks` has been renamed to `rustdoc::bare_urls`
+  --> $DIR/unknown-renamed-lints.rs:11:9
+   |
+LL | #![deny(non_autolinks)]
+   |         ^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
+
+error: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls`
+  --> $DIR/unknown-renamed-lints.rs:13:9
+   |
+LL | #![deny(rustdoc::non_autolinks)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
+
+error: lint `private_doc_tests` has been renamed to `rustdoc::private_doc_tests`
+  --> $DIR/unknown-renamed-lints.rs:16:9
+   |
+LL | #![deny(private_doc_tests)]
+   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::private_doc_tests`
+
+error: lint `rustdoc` has been removed: use `rustdoc::all` instead
+  --> $DIR/unknown-renamed-lints.rs:19:9
+   |
+LL | #![deny(rustdoc)]
+   |         ^^^^^^^
+
+error: unknown lint: `rustdoc::intra_doc_link_resolution_failure`
+  --> $DIR/unknown-renamed-lints.rs:23:9
+   |
+LL | #![deny(rustdoc::intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/rustdoc-ui/lints/unused-braces-lint.rs b/tests/rustdoc-ui/lints/unused-braces-lint.rs
new file mode 100644
index 00000000000..be0e31e4be2
--- /dev/null
+++ b/tests/rustdoc-ui/lints/unused-braces-lint.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+// This tests the bug in #70814, where the unused_braces lint triggered on the following code
+// without providing a span.
+
+#![deny(unused_braces)]
+
+fn main() {
+    {
+        {
+            use std;
+        }
+    }
+}
diff --git a/tests/rustdoc-ui/lints/unused.rs b/tests/rustdoc-ui/lints/unused.rs
new file mode 100644
index 00000000000..702b24c36c5
--- /dev/null
+++ b/tests/rustdoc-ui/lints/unused.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+// This test purpose is to check that unused_imports lint isn't fired
+// by rustdoc. Why would it? Because when rustdoc is running, it uses
+// "everybody-loops" which replaces parts of code with "loop {}" to get
+// huge performance improvements.
+
+#![deny(unused_imports)]
+
+use std::fs::File;
+
+pub fn f() {
+    let _: File;
+}