summaryrefslogtreecommitdiffstats
path: root/src/test/rustdoc-ui
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/rustdoc-ui
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/rustdoc-ui')
-rw-r--r--src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs16
-rw-r--r--src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr15
-rw-r--r--src/test/rustdoc-ui/assoc-item-not-in-scope.rs22
-rw-r--r--src/test/rustdoc-ui/assoc-item-not-in-scope.stderr14
-rw-r--r--src/test/rustdoc-ui/auxiliary/empty-fn.rs3
-rw-r--r--src/test/rustdoc-ui/auxiliary/extern_macros.rs7
-rw-r--r--src/test/rustdoc-ui/auxiliary/issue-61592.rs3
-rw-r--r--src/test/rustdoc-ui/auxiliary/module_macro_doc.rs1
-rw-r--r--src/test/rustdoc-ui/auxiliary/overflow.rs20
-rw-r--r--src/test/rustdoc-ui/auxiliary/panic-item.rs17
-rw-r--r--src/test/rustdoc-ui/bare-urls.fixed60
-rw-r--r--src/test/rustdoc-ui/bare-urls.rs60
-rw-r--r--src/test/rustdoc-ui/bare-urls.stderr143
-rw-r--r--src/test/rustdoc-ui/block-doc-comment.rs17
-rw-r--r--src/test/rustdoc-ui/block-doc-comment.stdout5
-rw-r--r--src/test/rustdoc-ui/bounded-hr-lifetime.rs9
-rw-r--r--src/test/rustdoc-ui/bounded-hr-lifetime.stderr10
-rw-r--r--src/test/rustdoc-ui/c-help.rs6
-rw-r--r--src/test/rustdoc-ui/c-help.stdout51
-rw-r--r--src/test/rustdoc-ui/cfg-test.rs31
-rw-r--r--src/test/rustdoc-ui/cfg-test.stdout7
-rw-r--r--src/test/rustdoc-ui/check-attr-test.rs31
-rw-r--r--src/test/rustdoc-ui/check-attr-test.stderr151
-rw-r--r--src/test/rustdoc-ui/check-attr.rs41
-rw-r--r--src/test/rustdoc-ui/check-attr.stderr175
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.rs12
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.stderr11
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.stdout6
-rw-r--r--src/test/rustdoc-ui/check-cfg-unstable.rs2
-rw-r--r--src/test/rustdoc-ui/check-cfg-unstable.stderr2
-rw-r--r--src/test/rustdoc-ui/check-cfg.rs7
-rw-r--r--src/test/rustdoc-ui/check-cfg.stderr10
-rw-r--r--src/test/rustdoc-ui/check-doc-alias-attr-location.rs23
-rw-r--r--src/test/rustdoc-ui/check-doc-alias-attr-location.stderr26
-rw-r--r--src/test/rustdoc-ui/check-doc-alias-attr.rs28
-rw-r--r--src/test/rustdoc-ui/check-doc-alias-attr.stderr108
-rw-r--r--src/test/rustdoc-ui/check-fail.rs21
-rw-r--r--src/test/rustdoc-ui/check-fail.stderr52
-rw-r--r--src/test/rustdoc-ui/check.rs12
-rw-r--r--src/test/rustdoc-ui/check.stderr55
-rw-r--r--src/test/rustdoc-ui/commandline-argfile-badutf8.args2
-rw-r--r--src/test/rustdoc-ui/commandline-argfile-badutf8.rs12
-rw-r--r--src/test/rustdoc-ui/commandline-argfile-badutf8.stderr2
-rw-r--r--src/test/rustdoc-ui/commandline-argfile-missing.rs14
-rw-r--r--src/test/rustdoc-ui/commandline-argfile-missing.stderr2
-rw-r--r--src/test/rustdoc-ui/commandline-argfile.args2
-rw-r--r--src/test/rustdoc-ui/commandline-argfile.rs13
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.rs41
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.stderr20
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/basic.rs50
-rw-r--r--src/test/rustdoc-ui/coverage/basic.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/doc-examples-json.rs13
-rw-r--r--src/test/rustdoc-ui/coverage/doc-examples-json.stdout1
-rw-r--r--src/test/rustdoc-ui/coverage/doc-examples.rs27
-rw-r--r--src/test/rustdoc-ui/coverage/doc-examples.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/empty.rs4
-rw-r--r--src/test/rustdoc-ui/coverage/empty.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple-documented.rs37
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple.rs18
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/enums.rs22
-rw-r--r--src/test/rustdoc-ui/coverage/enums.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/exotic.rs15
-rw-r--r--src/test/rustdoc-ui/coverage/exotic.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/html.rs4
-rw-r--r--src/test/rustdoc-ui/coverage/html.stderr2
-rw-r--r--src/test/rustdoc-ui/coverage/json.rs65
-rw-r--r--src/test/rustdoc-ui/coverage/json.stdout1
-rw-r--r--src/test/rustdoc-ui/coverage/private.rs21
-rw-r--r--src/test/rustdoc-ui/coverage/private.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/statics-consts.rs23
-rw-r--r--src/test/rustdoc-ui/coverage/statics-consts.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/traits.rs38
-rw-r--r--src/test/rustdoc-ui/coverage/traits.stdout7
-rw-r--r--src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs4
-rw-r--r--src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr15
-rw-r--r--src/test/rustdoc-ui/deny-missing-docs-crate.rs3
-rw-r--r--src/test/rustdoc-ui/deny-missing-docs-crate.stderr22
-rw-r--r--src/test/rustdoc-ui/deny-missing-docs-macro.rs8
-rw-r--r--src/test/rustdoc-ui/deny-missing-docs-macro.stderr14
-rw-r--r--src/test/rustdoc-ui/deprecated-attrs.rs16
-rw-r--r--src/test/rustdoc-ui/deprecated-attrs.stderr34
-rw-r--r--src/test/rustdoc-ui/deref-generic.rs15
-rw-r--r--src/test/rustdoc-ui/diagnostic-width.rs5
-rw-r--r--src/test/rustdoc-ui/diagnostic-width.stderr15
-rw-r--r--src/test/rustdoc-ui/display-output.rs15
-rw-r--r--src/test/rustdoc-ui/display-output.stdout43
-rw-r--r--src/test/rustdoc-ui/doc-alias-assoc-const.rs21
-rw-r--r--src/test/rustdoc-ui/doc-alias-assoc-const.stderr8
-rw-r--r--src/test/rustdoc-ui/doc-alias-crate-level.rs4
-rw-r--r--src/test/rustdoc-ui/doc-alias-crate-level.stderr14
-rw-r--r--src/test/rustdoc-ui/doc-alias-same-name.rs4
-rw-r--r--src/test/rustdoc-ui/doc-alias-same-name.stderr8
-rw-r--r--src/test/rustdoc-ui/doc-attr.rs25
-rw-r--r--src/test/rustdoc-ui/doc-attr.stderr71
-rw-r--r--src/test/rustdoc-ui/doc-cfg.rs9
-rw-r--r--src/test/rustdoc-ui/doc-cfg.stderr26
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-attr.rs11
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout6
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs12
-rw-r--r--src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.stdout6
-rw-r--r--src/test/rustdoc-ui/doc-include-suggestion.rs10
-rw-r--r--src/test/rustdoc-ui/doc-include-suggestion.stderr12
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.fixed8
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.rs8
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.stderr19
-rw-r--r--src/test/rustdoc-ui/doc-test-attr-pass.rs8
-rw-r--r--src/test/rustdoc-ui/doc-test-attr.rs14
-rw-r--r--src/test/rustdoc-ui/doc-test-attr.stderr34
-rw-r--r--src/test/rustdoc-ui/doc-test-doctest-feature.rs13
-rw-r--r--src/test/rustdoc-ui/doc-test-doctest-feature.stdout6
-rw-r--r--src/test/rustdoc-ui/doc-test-rustdoc-feature.rs15
-rw-r--r--src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout6
-rw-r--r--src/test/rustdoc-ui/doc-without-codeblock.rs22
-rw-r--r--src/test/rustdoc-ui/doc-without-codeblock.stderr38
-rw-r--r--src/test/rustdoc-ui/doctest-edition.rs16
-rw-r--r--src/test/rustdoc-ui/doctest-edition.stderr22
-rw-r--r--src/test/rustdoc-ui/doctest-multiline-crate-attribute.rs10
-rw-r--r--src/test/rustdoc-ui/doctest-multiline-crate-attribute.stdout6
-rw-r--r--src/test/rustdoc-ui/doctest-output.rs28
-rw-r--r--src/test/rustdoc-ui/doctest-output.stdout8
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/README.md7
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/async.rs7
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/closure.rs5
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs23
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs7
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs6
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs6
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs28
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs10
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs10
-rw-r--r--src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs157
-rw-r--r--src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr28
-rw-r--r--src/test/rustdoc-ui/failed-doctest-compile-fail.rs12
-rw-r--r--src/test/rustdoc-ui/failed-doctest-compile-fail.stdout14
-rw-r--r--src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs18
-rw-r--r--src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout24
-rw-r--r--src/test/rustdoc-ui/failed-doctest-missing-codes.rs12
-rw-r--r--src/test/rustdoc-ui/failed-doctest-missing-codes.stdout25
-rw-r--r--src/test/rustdoc-ui/failed-doctest-output-windows.rs28
-rw-r--r--src/test/rustdoc-ui/failed-doctest-output-windows.stdout39
-rw-r--r--src/test/rustdoc-ui/failed-doctest-output.rs28
-rw-r--r--src/test/rustdoc-ui/failed-doctest-output.stdout39
-rw-r--r--src/test/rustdoc-ui/failed-doctest-should-panic.rs12
-rw-r--r--src/test/rustdoc-ui/failed-doctest-should-panic.stdout14
-rw-r--r--src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs7
-rw-r--r--src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr14
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.rs6
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.stderr2
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt.rs6
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt.stderr2
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt2.rs6
-rw-r--r--src/test/rustdoc-ui/generate-link-to-definition-opt2.stderr2
-rw-r--r--src/test/rustdoc-ui/ignore-block-help.rs10
-rw-r--r--src/test/rustdoc-ui/ignore-block-help.stderr19
-rw-r--r--src/test/rustdoc-ui/impl-fn-nesting.rs49
-rw-r--r--src/test/rustdoc-ui/impl-fn-nesting.stderr66
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs15
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr17
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs7
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr17
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type.rs4
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type.stderr17
-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
-rw-r--r--src/test/rustdoc-ui/invalid-cfg.rs4
-rw-r--r--src/test/rustdoc-ui/invalid-cfg.stderr14
-rw-r--r--src/test/rustdoc-ui/invalid-doc-attr.rs32
-rw-r--r--src/test/rustdoc-ui/invalid-doc-attr.stderr78
-rw-r--r--src/test/rustdoc-ui/invalid-html-tags.rs116
-rw-r--r--src/test/rustdoc-ui/invalid-html-tags.stderr98
-rw-r--r--src/test/rustdoc-ui/invalid-keyword.rs4
-rw-r--r--src/test/rustdoc-ui/invalid-keyword.stderr8
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.rs101
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.stderr154
-rw-r--r--src/test/rustdoc-ui/invalid-theme-name.rs3
-rw-r--r--src/test/rustdoc-ui/invalid-theme-name.stderr4
-rw-r--r--src/test/rustdoc-ui/issue-58473-2.rs12
-rw-r--r--src/test/rustdoc-ui/issue-58473.rs10
-rw-r--r--src/test/rustdoc-ui/issue-61592-2.rs10
-rw-r--r--src/test/rustdoc-ui/issue-61592-2.stderr12
-rw-r--r--src/test/rustdoc-ui/issue-61592.rs8
-rw-r--r--src/test/rustdoc-ui/issue-61592.stderr11
-rw-r--r--src/test/rustdoc-ui/issue-61732.rs4
-rw-r--r--src/test/rustdoc-ui/issue-61732.stderr13
-rw-r--r--src/test/rustdoc-ui/issue-74134.private.stderr11
-rw-r--r--src/test/rustdoc-ui/issue-74134.public.stderr11
-rw-r--r--src/test/rustdoc-ui/issue-74134.rs41
-rw-r--r--src/test/rustdoc-ui/issue-79465.rs3
-rw-r--r--src/test/rustdoc-ui/issue-79465.stderr15
-rw-r--r--src/test/rustdoc-ui/issue-79467.rs8
-rw-r--r--src/test/rustdoc-ui/issue-79467.stderr9
-rw-r--r--src/test/rustdoc-ui/issue-79494.rs5
-rw-r--r--src/test/rustdoc-ui/issue-79494.stderr12
-rw-r--r--src/test/rustdoc-ui/issue-80992.rs11
-rw-r--r--src/test/rustdoc-ui/issue-80992.stdout6
-rw-r--r--src/test/rustdoc-ui/issue-81662-shortness.rs12
-rw-r--r--src/test/rustdoc-ui/issue-81662-shortness.stdout16
-rw-r--r--src/test/rustdoc-ui/issue-83883-describe-lints.rs10
-rw-r--r--src/test/rustdoc-ui/issue-83883-describe-lints.stdout24
-rw-r--r--src/test/rustdoc-ui/issue-91134.rs14
-rw-r--r--src/test/rustdoc-ui/issue-91134.stdout6
-rw-r--r--src/test/rustdoc-ui/issue-91713.rs3
-rw-r--r--src/test/rustdoc-ui/issue-91713.stderr5
-rw-r--r--src/test/rustdoc-ui/issue-91713.stdout29
-rw-r--r--src/test/rustdoc-ui/issue-98690.rs10
-rw-r--r--src/test/rustdoc-ui/issue-98690.stderr1
-rw-r--r--src/test/rustdoc-ui/lint-group.rs29
-rw-r--r--src/test/rustdoc-ui/lint-group.stderr50
-rw-r--r--src/test/rustdoc-ui/lint-missing-doc-code-example.rs100
-rw-r--r--src/test/rustdoc-ui/lint-missing-doc-code-example.stderr38
-rw-r--r--src/test/rustdoc-ui/macro-docs.rs12
-rw-r--r--src/test/rustdoc-ui/macro-docs.stderr20
-rw-r--r--src/test/rustdoc-ui/macro-docs.stdout0
-rw-r--r--src/test/rustdoc-ui/no-crate-level-doc-lint.rs6
-rw-r--r--src/test/rustdoc-ui/no-crate-level-doc-lint.stderr12
-rw-r--r--src/test/rustdoc-ui/no-run-flag-error.rs6
-rw-r--r--src/test/rustdoc-ui/no-run-flag-error.stderr2
-rw-r--r--src/test/rustdoc-ui/no-run-flag.rs38
-rw-r--r--src/test/rustdoc-ui/no-run-flag.stdout12
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.rs12
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.stderr18
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.stdout6
-rw-r--r--src/test/rustdoc-ui/nocapture.rs10
-rw-r--r--src/test/rustdoc-ui/nocapture.stderr1
-rw-r--r--src/test/rustdoc-ui/nocapture.stdout7
-rw-r--r--src/test/rustdoc-ui/normalize-cycle.rs25
-rw-r--r--src/test/rustdoc-ui/normalize-overflow.rs3
-rw-r--r--src/test/rustdoc-ui/output-format-html-stable.rs4
-rw-r--r--src/test/rustdoc-ui/private-doc-test.rs12
-rw-r--r--src/test/rustdoc-ui/private-item-doc-test.rs11
-rw-r--r--src/test/rustdoc-ui/private-item-doc-test.stderr18
-rw-r--r--src/test/rustdoc-ui/private-public-item-doc-test.rs11
-rw-r--r--src/test/rustdoc-ui/private-public-item-doc-test.stderr18
-rw-r--r--src/test/rustdoc-ui/pub-export-lint.rs5
-rw-r--r--src/test/rustdoc-ui/pub-export-lint.stderr15
-rw-r--r--src/test/rustdoc-ui/public-reexported-item-doc-test.rs16
-rw-r--r--src/test/rustdoc-ui/range-pattern.rs3
-rw-r--r--src/test/rustdoc-ui/recursive-deref-ice.rs19
-rw-r--r--src/test/rustdoc-ui/reference-link-reports-error-once.rs20
-rw-r--r--src/test/rustdoc-ui/reference-link-reports-error-once.stderr63
-rw-r--r--src/test/rustdoc-ui/reference-links.rs6
-rw-r--r--src/test/rustdoc-ui/reference-links.stderr14
-rw-r--r--src/test/rustdoc-ui/renamed-lint-still-applies.rs10
-rw-r--r--src/test/rustdoc-ui/renamed-lint-still-applies.stderr42
-rw-r--r--src/test/rustdoc-ui/run-directory.correct.stdout6
-rw-r--r--src/test/rustdoc-ui/run-directory.incorrect.stdout6
-rw-r--r--src/test/rustdoc-ui/run-directory.rs23
-rw-r--r--src/test/rustdoc-ui/rustc-check-passes.rs4
-rw-r--r--src/test/rustdoc-ui/rustc-check-passes.stderr9
-rw-r--r--src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs7
-rw-r--r--src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr14
-rw-r--r--src/test/rustdoc-ui/scrape-examples-ice.rs4
-rw-r--r--src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs1
-rw-r--r--src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr2
-rw-r--r--src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs1
-rw-r--r--src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr2
-rw-r--r--src/test/rustdoc-ui/search-index-generics-recursion-bug-issue-59502.rs11
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs38
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr38
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.fixed32
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.rs32
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.stderr73
-rw-r--r--src/test/rustdoc-ui/test-compile-fail1.rs8
-rw-r--r--src/test/rustdoc-ui/test-compile-fail1.stderr14
-rw-r--r--src/test/rustdoc-ui/test-compile-fail2.rs3
-rw-r--r--src/test/rustdoc-ui/test-compile-fail2.stderr8
-rw-r--r--src/test/rustdoc-ui/test-compile-fail3.rs3
-rw-r--r--src/test/rustdoc-ui/test-compile-fail3.stderr9
-rw-r--r--src/test/rustdoc-ui/test-no_std.rs13
-rw-r--r--src/test/rustdoc-ui/test-no_std.stdout6
-rw-r--r--src/test/rustdoc-ui/test-type.rs26
-rw-r--r--src/test/rustdoc-ui/test-type.stdout10
-rw-r--r--src/test/rustdoc-ui/tuple-variadic-check.rs15
-rw-r--r--src/test/rustdoc-ui/tuple-variadic-check.stderr8
-rw-r--r--src/test/rustdoc-ui/unknown-renamed-lints.rs24
-rw-r--r--src/test/rustdoc-ui/unknown-renamed-lints.stderr64
-rw-r--r--src/test/rustdoc-ui/unparseable-doc-test.rs11
-rw-r--r--src/test/rustdoc-ui/unparseable-doc-test.stdout23
-rw-r--r--src/test/rustdoc-ui/unused-braces-lint.rs14
-rw-r--r--src/test/rustdoc-ui/unused-extern-crate.rs3
-rw-r--r--src/test/rustdoc-ui/unused.rs14
-rw-r--r--src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs1
-rw-r--r--src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr2
-rw-r--r--src/test/rustdoc-ui/wasm-safe.rs5
-rw-r--r--src/test/rustdoc-ui/z-help.rs6
-rw-r--r--src/test/rustdoc-ui/z-help.stdout200
354 files changed, 7890 insertions, 0 deletions
diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs
new file mode 100644
index 000000000..e58bba640
--- /dev/null
+++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs
@@ -0,0 +1,16 @@
+// This test ensures that rustdoc does not panic on inherented associated types
+// that are referred to without fully-qualified syntax.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+pub struct Struct;
+
+impl Struct {
+ pub type AssocTy = usize;
+ pub const AssocConst: Self::AssocTy = 42;
+ //~^ ERROR ambiguous associated type
+ //~| HELP use fully-qualified syntax
+ //~| ERROR ambiguous associated type
+ //~| HELP use fully-qualified syntax
+}
diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr
new file mode 100644
index 000000000..b963b722f
--- /dev/null
+++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr
@@ -0,0 +1,15 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
+ |
+LL | pub const AssocConst: Self::AssocTy = 42;
+ | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+ --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
+ |
+LL | pub const AssocConst: Self::AssocTy = 42;
+ | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/rustdoc-ui/assoc-item-not-in-scope.rs b/src/test/rustdoc-ui/assoc-item-not-in-scope.rs
new file mode 100644
index 000000000..0976515f4
--- /dev/null
+++ b/src/test/rustdoc-ui/assoc-item-not-in-scope.rs
@@ -0,0 +1,22 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+#[derive(Debug)]
+/// Link to [`S::fmt`]
+//~^ ERROR unresolved link
+pub struct S;
+
+pub mod inner {
+ use std::fmt::Debug;
+ use super::S;
+
+ /// Link to [`S::fmt`]
+ pub fn f() {}
+}
+
+pub mod ambiguous {
+ use std::fmt::{Display, Debug};
+ use super::S;
+
+ /// Link to [`S::fmt`]
+ pub fn f() {}
+}
diff --git a/src/test/rustdoc-ui/assoc-item-not-in-scope.stderr b/src/test/rustdoc-ui/assoc-item-not-in-scope.stderr
new file mode 100644
index 000000000..04594ad41
--- /dev/null
+++ b/src/test/rustdoc-ui/assoc-item-not-in-scope.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `S::fmt`
+ --> $DIR/assoc-item-not-in-scope.rs:4:15
+ |
+LL | /// Link to [`S::fmt`]
+ | ^^^^^^ the struct `S` has no field or associated item named `fmt`
+ |
+note: the lint level is defined here
+ --> $DIR/assoc-item-not-in-scope.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/auxiliary/empty-fn.rs b/src/test/rustdoc-ui/auxiliary/empty-fn.rs
new file mode 100644
index 000000000..877810f15
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/empty-fn.rs
@@ -0,0 +1,3 @@
+// no-prefer-dynamic
+#![crate_type = "lib"]
+pub fn empty() {}
diff --git a/src/test/rustdoc-ui/auxiliary/extern_macros.rs b/src/test/rustdoc-ui/auxiliary/extern_macros.rs
new file mode 100644
index 000000000..ee1fec4c5
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/extern_macros.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! attrs_on_struct {
+ ( $( #[$attr:meta] )* ) => {
+ $( #[$attr] )*
+ pub struct ExpandedStruct;
+ }
+}
diff --git a/src/test/rustdoc-ui/auxiliary/issue-61592.rs b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
new file mode 100644
index 000000000..57a365b3f
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/issue-61592.rs
@@ -0,0 +1,3 @@
+#![crate_name = "foo"]
+
+pub trait Foo {}
diff --git a/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs b/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs
new file mode 100644
index 000000000..9d6b52b95
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs
@@ -0,0 +1 @@
+//! [`long_cat`] is really long
diff --git a/src/test/rustdoc-ui/auxiliary/overflow.rs b/src/test/rustdoc-ui/auxiliary/overflow.rs
new file mode 100644
index 000000000..ff65936be
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/overflow.rs
@@ -0,0 +1,20 @@
+pub struct B0;
+pub struct B1;
+use std::ops::Shl;
+use std::ops::Sub;
+pub type Shleft<A, B> = <A as Shl<B>>::Output;
+pub type Sub1<A> = <A as Sub<B1>>::Output;
+pub struct UInt<U, B> {
+ pub(crate) msb: U,
+ pub(crate) lsb: B,
+}
+impl<U, B, Ur, Br> Shl<UInt<Ur, Br>> for UInt<U, B>
+where
+ UInt<Ur, Br>: Sub<B1>,
+ UInt<UInt<U, B>, B0>: Shl<Sub1<UInt<Ur, Br>>>,
+{
+ type Output = Shleft<UInt<UInt<U, B>, B0>, Sub1<UInt<Ur, Br>>>;
+ fn shl(self, rhs: UInt<Ur, Br>) -> Self::Output {
+ unimplemented!()
+ }
+}
diff --git a/src/test/rustdoc-ui/auxiliary/panic-item.rs b/src/test/rustdoc-ui/auxiliary/panic-item.rs
new file mode 100644
index 000000000..17b26850d
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/panic-item.rs
@@ -0,0 +1,17 @@
+// no-prefer-dynamic
+#![crate_type = "lib"]
+#![no_std]
+#![feature(lang_items)]
+
+use core::panic::PanicInfo;
+use core::sync::atomic::{self, Ordering};
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+ loop {
+ atomic::compiler_fence(Ordering::SeqCst);
+ }
+}
+
+#[lang = "eh_personality"]
+fn foo() {}
diff --git a/src/test/rustdoc-ui/bare-urls.fixed b/src/test/rustdoc-ui/bare-urls.fixed
new file mode 100644
index 000000000..23aa5c44c
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/bare-urls.rs b/src/test/rustdoc-ui/bare-urls.rs
new file mode 100644
index 000000000..592f57343
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/bare-urls.stderr b/src/test/rustdoc-ui/bare-urls.stderr
new file mode 100644
index 000000000..7097a8ddf
--- /dev/null
+++ b/src/test/rustdoc-ui/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: the lint level is defined here
+ --> $DIR/bare-urls.rs:3:9
+ |
+LL | #![deny(rustdoc::bare_urls)]
+ | ^^^^^^^^^^^^^^^^^^
+ = note: bare URLs are not automatically turned into clickable links
+
+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/src/test/rustdoc-ui/block-doc-comment.rs b/src/test/rustdoc-ui/block-doc-comment.rs
new file mode 100644
index 000000000..ce529916e
--- /dev/null
+++ b/src/test/rustdoc-ui/block-doc-comment.rs
@@ -0,0 +1,17 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// This test ensures that no code block is detected in the doc comments.
+
+pub mod Wormhole {
+ /** # Returns
+ *
+ */
+ pub fn foofoo() {}
+ /**
+ * # Returns
+ *
+ */
+ pub fn barbar() {}
+}
diff --git a/src/test/rustdoc-ui/block-doc-comment.stdout b/src/test/rustdoc-ui/block-doc-comment.stdout
new file mode 100644
index 000000000..7326c0a25
--- /dev/null
+++ b/src/test/rustdoc-ui/block-doc-comment.stdout
@@ -0,0 +1,5 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.rs b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
new file mode 100644
index 000000000..b2e000b97
--- /dev/null
+++ b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
@@ -0,0 +1,9 @@
+// This test ensures that rustdoc doesn't panic on higher-ranked lifetimes
+// with bounds, because an error should have already been emitted by rustc.
+
+pub fn hrlt<'b, 'c>()
+where
+ for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+ //~^ ERROR lifetime bounds cannot be used in this context
+{
+}
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.stderr b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
new file mode 100644
index 000000000..d8fcd6cb4
--- /dev/null
+++ b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
@@ -0,0 +1,10 @@
+error: lifetime bounds cannot be used in this context
+ --> $DIR/bounded-hr-lifetime.rs:6:13
+ |
+LL | for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+ | ^^ ^^
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/rustdoc-ui/c-help.rs b/src/test/rustdoc-ui/c-help.rs
new file mode 100644
index 000000000..e166edf8b
--- /dev/null
+++ b/src/test/rustdoc-ui/c-help.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Chelp
+// check-stdout
+// regex-error-pattern: -C\s+incremental
+
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/c-help.stdout b/src/test/rustdoc-ui/c-help.stdout
new file mode 100644
index 000000000..75b2e2a2a
--- /dev/null
+++ b/src/test/rustdoc-ui/c-help.stdout
@@ -0,0 +1,51 @@
+ -C ar=val -- this option is deprecated and does nothing
+ -C code-model=val -- choose the code model to use (`rustc --print code-models` for details)
+ -C codegen-units=val -- divide crate into N units to optimize in parallel
+ -C control-flow-guard=val -- use Windows Control Flow Guard (default: no)
+ -C debug-assertions=val -- explicitly enable the `cfg(debug_assertions)` directive
+ -C debuginfo=val -- debug info emission level (0 = no debug info, 1 = line tables only, 2 = full debug info with variable and type information; default: 0)
+ -C default-linker-libraries=val -- allow the linker to link its default libraries (default: no)
+ -C embed-bitcode=val -- emit bitcode in rlibs (default: yes)
+ -C extra-filename=val -- extra data to put in each output filename
+ -C force-frame-pointers=val -- force use of the frame pointers
+ -C force-unwind-tables=val -- force use of unwind tables
+ -C incremental=val -- enable incremental compilation
+ -C inline-threshold=val -- set the threshold for inlining a function
+ -C instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+ `=all` (implicit value)
+ `=except-unused-generics`
+ `=except-unused-functions`
+ `=off` (default)
+ -C link-arg=val -- a single extra argument to append to the linker invocation (can be used several times)
+ -C link-args=val -- extra arguments to append to the linker invocation (space separated)
+ -C link-dead-code=val -- keep dead code at link time (useful for code coverage) (default: no)
+ -C link-self-contained=val -- control whether to link Rust provided C objects/libraries or rely
+ on C toolchain installed in the system
+ -C linker=val -- system linker to link outputs with
+ -C linker-flavor=val -- linker flavor
+ -C linker-plugin-lto=val -- generate build artifacts that are compatible with linker-based LTO
+ -C llvm-args=val -- a list of arguments to pass to LLVM (space separated)
+ -C lto=val -- perform LLVM link-time optimizations
+ -C metadata=val -- metadata to mangle symbol names with
+ -C no-prepopulate-passes=val -- give an empty list of passes to the pass manager
+ -C no-redzone=val -- disable the use of the redzone
+ -C no-stack-check=val -- this option is deprecated and does nothing
+ -C no-vectorize-loops=val -- disable loop vectorization optimization passes
+ -C no-vectorize-slp=val -- disable LLVM's SLP vectorization pass
+ -C opt-level=val -- optimization level (0-3, s, or z; default: 0)
+ -C overflow-checks=val -- use overflow checks for integer arithmetic
+ -C panic=val -- panic strategy to compile crate with
+ -C passes=val -- a list of extra LLVM passes to run (space separated)
+ -C prefer-dynamic=val -- prefer dynamic linking to static linking (default: no)
+ -C profile-generate=val -- compile the program with profiling instrumentation
+ -C profile-use=val -- use the given `.profdata` file for profile-guided optimization
+ -C relocation-model=val -- control generation of position-independent code (PIC) (`rustc --print relocation-models` for details)
+ -C remark=val -- print remarks for these optimization passes (space separated, or "all")
+ -C rpath=val -- set rpath values in libs/exes (default: no)
+ -C save-temps=val -- save all temporary output files during compilation (default: no)
+ -C soft-float=val -- use soft float ABI (*eabihf targets only) (default: no)
+ -C split-debuginfo=val -- how to handle split-debuginfo, a platform-specific option
+ -C strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+ -C symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+ -C target-cpu=val -- select target processor (`rustc --print target-cpus` for details)
+ -C target-feature=val -- target specific attributes. (`rustc --print target-features` for details). This feature is unsafe.
diff --git a/src/test/rustdoc-ui/cfg-test.rs b/src/test/rustdoc-ui/cfg-test.rs
new file mode 100644
index 000000000..d4ca92585
--- /dev/null
+++ b/src/test/rustdoc-ui/cfg-test.rs
@@ -0,0 +1,31 @@
+// check-pass
+// compile-flags:--test --test-args --test-threads=1
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// Crates like core have doctests gated on `cfg(not(test))` so we need to make
+// sure `cfg(test)` is not active when running `rustdoc --test`.
+
+/// this doctest will be ignored:
+///
+/// ```
+/// assert!(false);
+/// ```
+#[cfg(test)]
+pub struct Foo;
+
+/// this doctest will be tested:
+///
+/// ```
+/// assert!(true);
+/// ```
+#[cfg(not(test))]
+pub struct Foo;
+
+/// this doctest will be tested, but will not appear in documentation:
+///
+/// ```
+/// assert!(true)
+/// ```
+#[cfg(doctest)]
+pub struct Bar;
diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout
new file mode 100644
index 000000000..2960ff8d3
--- /dev/null
+++ b/src/test/rustdoc-ui/cfg-test.stdout
@@ -0,0 +1,7 @@
+
+running 2 tests
+test $DIR/cfg-test.rs - Bar (line 27) ... ok
+test $DIR/cfg-test.rs - Foo (line 19) ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/check-attr-test.rs b/src/test/rustdoc-ui/check-attr-test.rs
new file mode 100644
index 000000000..e95547014
--- /dev/null
+++ b/src/test/rustdoc-ui/check-attr-test.rs
@@ -0,0 +1,31 @@
+// compile-flags:--test
+
+#![deny(rustdoc::invalid_codeblock_attributes)]
+
+/// foo
+///
+/// ```compile-fail,compilefail,comPile_fail
+/// boo
+/// ```
+pub fn foo() {}
+
+/// bar
+///
+/// ```should-panic,shouldpanic,shOuld_panic
+/// boo
+/// ```
+pub fn bar() {}
+
+/// foobar
+///
+/// ```no-run,norun,nO_run
+/// boo
+/// ```
+pub fn foobar() {}
+
+/// b
+///
+/// ```test-harness,testharness,tesT_harness
+/// boo
+/// ```
+pub fn b() {}
diff --git a/src/test/rustdoc-ui/check-attr-test.stderr b/src/test/rustdoc-ui/check-attr-test.stderr
new file mode 100644
index 000000000..b1fa9edf0
--- /dev/null
+++ b/src/test/rustdoc-ui/check-attr-test.stderr
@@ -0,0 +1,151 @@
+error: unknown attribute `compile-fail`. Did you mean `compile_fail`?
+ --> $DIR/check-attr-test.rs:5:1
+ |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+ | |_______^
+ |
+note: the lint level is defined here
+ --> $DIR/check-attr-test.rs:3:9
+ |
+3 | #![deny(rustdoc::invalid_codeblock_attributes)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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 `compilefail`. Did you mean `compile_fail`?
+ --> $DIR/check-attr-test.rs:5:1
+ |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:5:1
+ |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:12:1
+ |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:12:1
+ |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:12:1
+ |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:19:1
+ |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:19:1
+ |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:19:1
+ |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:26:1
+ |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:26:1
+ |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+ | |_______^
+ |
+ = 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-test.rs:26:1
+ |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+ | |_______^
+ |
+ = 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/src/test/rustdoc-ui/check-attr.rs b/src/test/rustdoc-ui/check-attr.rs
new file mode 100644
index 000000000..0b3f7bedd
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/check-attr.stderr b/src/test/rustdoc-ui/check-attr.stderr
new file mode 100644
index 000000000..370b804c5
--- /dev/null
+++ b/src/test/rustdoc-ui/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 | | /// ```
+ | |_______^
+ |
+note: the lint level is defined here
+ --> $DIR/check-attr.rs:1:9
+ |
+LL | #![deny(rustdoc::invalid_codeblock_attributes)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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 `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/src/test/rustdoc-ui/check-cfg-test.rs b/src/test/rustdoc-ui/check-cfg-test.rs
new file mode 100644
index 000000000..626cc8387
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options
+// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// The doctest will produce a warning because feature invalid is unexpected
+/// ```
+/// #[cfg(feature = "invalid")]
+/// assert!(false);
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/check-cfg-test.stderr b/src/test/rustdoc-ui/check-cfg-test.stderr
new file mode 100644
index 000000000..dc25205da
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+ --> $DIR/check-cfg-test.rs:9:7
+ |
+LL | #[cfg(feature = "invalid")]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unexpected_cfgs)]` on by default
+ = note: expected values for `feature` are: test
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/check-cfg-test.stdout b/src/test/rustdoc-ui/check-cfg-test.stdout
new file mode 100644
index 000000000..b7db49bcf
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/check-cfg-test.rs - Foo (line 8) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/check-cfg-unstable.rs b/src/test/rustdoc-ui/check-cfg-unstable.rs
new file mode 100644
index 000000000..5c500ce6c
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-unstable.rs
@@ -0,0 +1,2 @@
+// check-fail
+// compile-flags: --check-cfg=names()
diff --git a/src/test/rustdoc-ui/check-cfg-unstable.stderr b/src/test/rustdoc-ui/check-cfg-unstable.stderr
new file mode 100644
index 000000000..9b27c2bc0
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-unstable.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `check-cfg`
+
diff --git a/src/test/rustdoc-ui/check-cfg.rs b/src/test/rustdoc-ui/check-cfg.rs
new file mode 100644
index 000000000..fa8789ad3
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: --check-cfg=names() -Z unstable-options
+
+/// uniz is nor a builtin nor pass as arguments so is unexpected
+#[cfg(uniz)]
+//~^ WARNING unexpected `cfg` condition name
+pub struct Bar;
diff --git a/src/test/rustdoc-ui/check-cfg.stderr b/src/test/rustdoc-ui/check-cfg.stderr
new file mode 100644
index 000000000..1db8e1d91
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+ --> $DIR/check-cfg.rs:5:7
+ |
+LL | #[cfg(uniz)]
+ | ^^^^ help: did you mean: `unix`
+ |
+ = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr-location.rs b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
new file mode 100644
index 000000000..6de1960e2
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
@@ -0,0 +1,23 @@
+pub struct Bar;
+pub trait Foo {
+ type X;
+ fn foo() -> Self::X;
+}
+
+#[doc(alias = "foo")] //~ ERROR
+extern "C" {}
+
+#[doc(alias = "bar")] //~ ERROR
+impl Bar {
+ #[doc(alias = "const")]
+ pub const A: u32 = 0;
+}
+
+#[doc(alias = "foobar")] //~ ERROR
+impl Foo for Bar {
+ #[doc(alias = "assoc")] //~ ERROR
+ type X = i32;
+ fn foo() -> Self::X {
+ 0
+ }
+}
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr b/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr
new file mode 100644
index 000000000..85c951623
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr
@@ -0,0 +1,26 @@
+error: `#[doc(alias = "...")]` isn't allowed on foreign module
+ --> $DIR/check-doc-alias-attr-location.rs:7:7
+ |
+LL | #[doc(alias = "foo")]
+ | ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+ --> $DIR/check-doc-alias-attr-location.rs:10:7
+ |
+LL | #[doc(alias = "bar")]
+ | ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+ --> $DIR/check-doc-alias-attr-location.rs:16:7
+ |
+LL | #[doc(alias = "foobar")]
+ | ^^^^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
+ --> $DIR/check-doc-alias-attr-location.rs:18:11
+ |
+LL | #[doc(alias = "assoc")]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.rs b/src/test/rustdoc-ui/check-doc-alias-attr.rs
new file mode 100644
index 000000000..719b98604
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr.rs
@@ -0,0 +1,28 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "foo")] // ok!
+#[doc(alias("bar", "baz"))] // ok!
+pub struct Bar;
+
+#[doc(alias)] //~ ERROR
+#[doc(alias = 0)] //~ ERROR
+#[doc(alias = "\"")] //~ ERROR
+#[doc(alias = "\n")] //~ ERROR
+#[doc(alias = "
+")] //~^ ERROR
+#[doc(alias = "\t")] //~ ERROR
+#[doc(alias = " hello")] //~ ERROR
+#[doc(alias = "hello ")] //~ ERROR
+#[doc(alias = "")] //~ ERROR
+pub struct Foo;
+
+#[doc(alias(0))] //~ ERROR
+#[doc(alias("\""))] //~ ERROR
+#[doc(alias("\n"))] //~ ERROR
+#[doc(alias("
+"))] //~^ ERROR
+#[doc(alias("\t"))] //~ ERROR
+#[doc(alias(" hello"))] //~ ERROR
+#[doc(alias("hello "))] //~ ERROR
+#[doc(alias(""))] //~ ERROR
+pub struct Foo2;
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
new file mode 100644
index 000000000..250568be3
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
@@ -0,0 +1,108 @@
+error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
+ --> $DIR/check-doc-alias-attr.rs:7:7
+ |
+LL | #[doc(alias)]
+ | ^^^^^
+
+error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
+ --> $DIR/check-doc-alias-attr.rs:8:7
+ |
+LL | #[doc(alias = 0)]
+ | ^^^^^^^^^
+
+error: '"' character isn't allowed in `#[doc(alias = "...")]`
+ --> $DIR/check-doc-alias-attr.rs:9:15
+ |
+LL | #[doc(alias = "\"")]
+ | ^^^^
+
+error: '\n' character isn't allowed in `#[doc(alias = "...")]`
+ --> $DIR/check-doc-alias-attr.rs:10:15
+ |
+LL | #[doc(alias = "\n")]
+ | ^^^^
+
+error: '\n' character isn't allowed in `#[doc(alias = "...")]`
+ --> $DIR/check-doc-alias-attr.rs:11:15
+ |
+LL | #[doc(alias = "
+ | _______________^
+LL | | ")]
+ | |_^
+
+error: '\t' character isn't allowed in `#[doc(alias = "...")]`
+ --> $DIR/check-doc-alias-attr.rs:13:15
+ |
+LL | #[doc(alias = "\t")]
+ | ^^^^
+
+error: `#[doc(alias = "...")]` cannot start or end with ' '
+ --> $DIR/check-doc-alias-attr.rs:14:15
+ |
+LL | #[doc(alias = " hello")]
+ | ^^^^^^^^
+
+error: `#[doc(alias = "...")]` cannot start or end with ' '
+ --> $DIR/check-doc-alias-attr.rs:15:15
+ |
+LL | #[doc(alias = "hello ")]
+ | ^^^^^^^^
+
+error: `#[doc(alias = "...")]` attribute cannot have empty value
+ --> $DIR/check-doc-alias-attr.rs:16:15
+ |
+LL | #[doc(alias = "")]
+ | ^^
+
+error: `#[doc(alias("a"))]` expects string literals
+ --> $DIR/check-doc-alias-attr.rs:19:13
+ |
+LL | #[doc(alias(0))]
+ | ^
+
+error: '"' character isn't allowed in `#[doc(alias("..."))]`
+ --> $DIR/check-doc-alias-attr.rs:20:13
+ |
+LL | #[doc(alias("\""))]
+ | ^^^^
+
+error: '\n' character isn't allowed in `#[doc(alias("..."))]`
+ --> $DIR/check-doc-alias-attr.rs:21:13
+ |
+LL | #[doc(alias("\n"))]
+ | ^^^^
+
+error: '\n' character isn't allowed in `#[doc(alias("..."))]`
+ --> $DIR/check-doc-alias-attr.rs:22:13
+ |
+LL | #[doc(alias("
+ | _____________^
+LL | | "))]
+ | |_^
+
+error: '\t' character isn't allowed in `#[doc(alias("..."))]`
+ --> $DIR/check-doc-alias-attr.rs:24:13
+ |
+LL | #[doc(alias("\t"))]
+ | ^^^^
+
+error: `#[doc(alias("..."))]` cannot start or end with ' '
+ --> $DIR/check-doc-alias-attr.rs:25:13
+ |
+LL | #[doc(alias(" hello"))]
+ | ^^^^^^^^
+
+error: `#[doc(alias("..."))]` cannot start or end with ' '
+ --> $DIR/check-doc-alias-attr.rs:26:13
+ |
+LL | #[doc(alias("hello "))]
+ | ^^^^^^^^
+
+error: `#[doc(alias("..."))]` attribute cannot have empty value
+ --> $DIR/check-doc-alias-attr.rs:27:13
+ |
+LL | #[doc(alias(""))]
+ | ^^
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/rustdoc-ui/check-fail.rs b/src/test/rustdoc-ui/check-fail.rs
new file mode 100644
index 000000000..2355d6a3d
--- /dev/null
+++ b/src/test/rustdoc-ui/check-fail.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Z unstable-options --check
+
+#![deny(missing_docs)]
+#![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/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr
new file mode 100644
index 000000000..5d46dc720
--- /dev/null
+++ b/src/test/rustdoc-ui/check-fail.stderr
@@ -0,0 +1,52 @@
+error: missing documentation for a function
+ --> $DIR/check-fail.rs:11:1
+ |
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/check-fail.rs:3:9
+ |
+LL | #![deny(missing_docs)]
+ | ^^^^^^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/check-fail.rs:11:1
+ |
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/check-fail.rs:4:9
+ |
+LL | #![deny(rustdoc::all)]
+ | ^^^^^^^^^^^^
+ = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]`
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+ --> $DIR/check-fail.rs:6:1
+ |
+LL | / //! ```rust,testharness
+LL | |
+LL | | //! let x = 12;
+LL | | //! ```
+ | |_______^
+ |
+ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
+ = 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-fail.rs:15: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/src/test/rustdoc-ui/check.rs b/src/test/rustdoc-ui/check.rs
new file mode 100644
index 000000000..2b44ba24b
--- /dev/null
+++ b/src/test/rustdoc-ui/check.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags: -Z unstable-options --check
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+
+#![warn(missing_docs)]
+//~^ WARN
+//~^^ WARN
+#![warn(rustdoc::all)]
+
+pub fn foo() {}
+//~^ WARN
+//~^^ WARN
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
new file mode 100644
index 000000000..06e607fbe
--- /dev/null
+++ b/src/test/rustdoc-ui/check.stderr
@@ -0,0 +1,55 @@
+warning: missing documentation for the crate
+ --> $DIR/check.rs:5:1
+ |
+LL | / #![warn(missing_docs)]
+LL | |
+LL | |
+LL | | #![warn(rustdoc::all)]
+LL | |
+LL | | pub fn foo() {}
+ | |_______________^
+ |
+note: the lint level is defined here
+ --> $DIR/check.rs:5:9
+ |
+LL | #![warn(missing_docs)]
+ | ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+ --> $DIR/check.rs:10:1
+ |
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^
+
+warning: no documentation found for this crate's top-level module
+ |
+note: the lint level is defined here
+ --> $DIR/check.rs:8:9
+ |
+LL | #![warn(rustdoc::all)]
+ | ^^^^^^^^^^^^
+ = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
+ = help: The following guide may be of use:
+ https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
+
+warning: missing code example in this documentation
+ --> $DIR/check.rs:5:1
+ |
+LL | / #![warn(missing_docs)]
+LL | |
+LL | |
+LL | | #![warn(rustdoc::all)]
+LL | |
+LL | | pub fn foo() {}
+ | |_______________^
+ |
+ = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
+
+warning: missing code example in this documentation
+ --> $DIR/check.rs:10:1
+ |
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^^^^
+
+warning: 5 warnings emitted
+
diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.args b/src/test/rustdoc-ui/commandline-argfile-badutf8.args
new file mode 100644
index 000000000..c070b0c24
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.args
@@ -0,0 +1,2 @@
+--cfg
+unbroken€ \ No newline at end of file
diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.rs b/src/test/rustdoc-ui/commandline-argfile-badutf8.rs
new file mode 100644
index 000000000..e2984e3ca
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.rs
@@ -0,0 +1,12 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr b/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr
new file mode 100644
index 000000000..9af6fc0a5
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr
@@ -0,0 +1,2 @@
+error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args
+
diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.rs b/src/test/rustdoc-ui/commandline-argfile-missing.rs
new file mode 100644
index 000000000..5a6465bd0
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile-missing.rs
@@ -0,0 +1,14 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.stderr b/src/test/rustdoc-ui/commandline-argfile-missing.stderr
new file mode 100644
index 000000000..179ad8310
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile-missing.stderr
@@ -0,0 +1,2 @@
+error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
diff --git a/src/test/rustdoc-ui/commandline-argfile.args b/src/test/rustdoc-ui/commandline-argfile.args
new file mode 100644
index 000000000..972938bf6
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile.args
@@ -0,0 +1,2 @@
+--cfg
+unbroken \ No newline at end of file
diff --git a/src/test/rustdoc-ui/commandline-argfile.rs b/src/test/rustdoc-ui/commandline-argfile.rs
new file mode 100644
index 000000000..cc8c8722c
--- /dev/null
+++ b/src/test/rustdoc-ui/commandline-argfile.rs
@@ -0,0 +1,13 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// check-pass
+// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
new file mode 100644
index 000000000..c771c09da
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
@@ -0,0 +1,41 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! Make sure to have some docs on your crate root
+
+#[allow(missing_docs)]
+pub mod mod_foo {
+ pub struct Bar;
+}
+
+/// This is a struct with an `#[allow(missing_docs)]`
+pub struct AllowTheMissingDocs {
+ #[allow(missing_docs)]
+ pub empty_str: String,
+
+ /// This has
+ #[allow(missing_docs)]
+ /// but also has documentation comments
+ pub hello: usize,
+
+ /// The doc id just to create a boilerplate comment
+ pub doc_id: Vec<u8>,
+}
+
+/// A function that has a documentation
+pub fn this_is_func() {}
+
+#[allow(missing_docs)]
+pub struct DemoStruct {
+ something: usize,
+}
+
+#[allow(missing_docs)]
+pub mod bar {
+ #[warn(missing_docs)]
+ pub struct Bar { //~ WARN
+ pub f: u32, //~ WARN
+ }
+
+ pub struct NeedsNoDocs;
+}
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr b/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr
new file mode 100644
index 000000000..3d5b512d1
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr
@@ -0,0 +1,20 @@
+warning: missing documentation for a struct
+ --> $DIR/allow_missing_docs.rs:36:5
+ |
+LL | pub struct Bar {
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/allow_missing_docs.rs:35:12
+ |
+LL | #[warn(missing_docs)]
+ | ^^^^^^^^^^^^
+
+warning: missing documentation for a struct field
+ --> $DIR/allow_missing_docs.rs:37:9
+ |
+LL | pub f: u32,
+ | ^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
new file mode 100644
index 000000000..17e8ee9e2
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...i/coverage/allow_missing_docs.rs | 5 | 71.4% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 5 | 71.4% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/basic.rs b/src/test/rustdoc-ui/coverage/basic.rs
new file mode 100644
index 000000000..6c26b751c
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/basic.rs
@@ -0,0 +1,50 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+#![feature(extern_types)]
+
+//! Make sure to have some docs on your crate root
+
+/// This struct is documented, but its fields are not.
+///
+/// However, one field is private, so it shouldn't show in the total.
+pub struct SomeStruct {
+ pub some_field: usize,
+ other_field: usize,
+}
+
+impl SomeStruct {
+ /// Method with docs
+ pub fn this_fn(&self) {}
+
+ // Method without docs
+ pub fn other_method(&self) {}
+}
+
+// struct without docs
+pub struct OtherStruct;
+
+// function with no docs
+pub fn some_fn() {}
+
+/// Function with docs
+pub fn other_fn() {}
+
+pub enum SomeEnum {
+ /// Some of these variants are documented...
+ VarOne,
+ /// ...but some of them are not.
+ VarTwo,
+ // (like this one)
+ VarThree,
+}
+
+/// There's a macro here, too
+#[macro_export]
+macro_rules! some_macro {
+ () => {};
+}
+
+extern "C" {
+ pub type ExternType;
+}
diff --git a/src/test/rustdoc-ui/coverage/basic.stdout b/src/test/rustdoc-ui/coverage/basic.stdout
new file mode 100644
index 000000000..3c602b3da
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/basic.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/basic.rs | 7 | 50.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 7 | 50.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.rs b/src/test/rustdoc-ui/coverage/doc-examples-json.rs
new file mode 100644
index 000000000..1da181379
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/doc-examples-json.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags:-Z unstable-options --output-format json --show-coverage
+
+// This check ensures that only one doc example is counted since they're "optional" on
+// certain items.
+
+/// ```
+/// let x = 12;
+/// ```
+pub const Foo: u32 = 0;
+
+/// doc
+pub const Bar: u32 = 0;
diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.stdout b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout
new file mode 100644
index 000000000..92f585569
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout
@@ -0,0 +1 @@
+{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}}
diff --git a/src/test/rustdoc-ui/coverage/doc-examples.rs b/src/test/rustdoc-ui/coverage/doc-examples.rs
new file mode 100644
index 000000000..cd718f8a3
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/doc-examples.rs
@@ -0,0 +1,27 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! This test ensure that only rust code examples are counted.
+
+/// Doc
+///
+/// ```
+/// let x = 2;
+/// ```
+pub struct Foo;
+
+/// Doc
+///
+/// ```text
+/// yolo
+/// ```
+pub trait Bar {}
+
+/// Doc
+///
+/// ```ignore (just for the sake of this test)
+/// let x = 2;
+/// ```
+pub fn foo<T: Bar, D: ::std::fmt::Debug>(a: Foo, b: u32, c: T, d: D) -> u32 {
+ 0
+}
diff --git a/src/test/rustdoc-ui/coverage/doc-examples.stdout b/src/test/rustdoc-ui/coverage/doc-examples.stdout
new file mode 100644
index 000000000..8188740f8
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/doc-examples.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 25.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 4 | 100.0% | 1 | 25.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/empty.rs b/src/test/rustdoc-ui/coverage/empty.rs
new file mode 100644
index 000000000..55a87e9d9
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/empty.rs
@@ -0,0 +1,4 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+// an empty crate still has one item to document: the crate root
diff --git a/src/test/rustdoc-ui/coverage/empty.stdout b/src/test/rustdoc-ui/coverage/empty.stdout
new file mode 100644
index 000000000..890a7d56e
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/empty.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/empty.rs | 0 | 0.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 0 | 0.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs
new file mode 100644
index 000000000..e9c165b19
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs
@@ -0,0 +1,37 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+// The point of this test is to ensure that the number of "documented" items
+// is higher than in `enum-tuple.rs`.
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+ /// VarOne.
+ VarOne(
+ /// hello!
+ String,
+ ),
+ /// Var Two.
+ VarTwo(
+ /// Hello
+ String,
+ /// Bis repetita.
+ String,
+ ),
+}
+
+/// Struct.
+pub struct ThisStruct(
+ /// hello
+ u32,
+);
+
+/// Struct.
+pub struct ThisStruct2(
+ /// hello
+ u32,
+ /// Bis repetita.
+ u8,
+);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout
new file mode 100644
index 000000000..82c98f43f
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...overage/enum-tuple-documented.rs | 9 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 9 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.rs b/src/test/rustdoc-ui/coverage/enum-tuple.rs
new file mode 100644
index 000000000..5fb205450
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple.rs
@@ -0,0 +1,18 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+ /// No need to document the field if there is only one in a tuple variant!
+ VarOne(String),
+ /// But if there is more than one... still fine!
+ VarTwo(String, String),
+}
+
+/// Struct.
+pub struct ThisStruct(u32);
+
+/// Struct.
+pub struct ThisStruct2(u32, u8);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.stdout b/src/test/rustdoc-ui/coverage/enum-tuple.stdout
new file mode 100644
index 000000000..a3377d59c
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...ustdoc-ui/coverage/enum-tuple.rs | 6 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 6 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enums.rs b/src/test/rustdoc-ui/coverage/enums.rs
new file mode 100644
index 000000000..a4ae36d68
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enums.rs
@@ -0,0 +1,22 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+ /// this variant has some weird stuff going on
+ VarOne {
+ /// like, it has some named fields inside
+ field_one: usize,
+ // (these show up as struct fields)
+ field_two: usize,
+ },
+ /// here's another variant for you
+ VarTwo(String),
+ // but not all of them need to be documented as thoroughly
+ VarThree,
+}
+
+/// uninhabited enums? sure, let's throw one of those around
+pub enum OtherEnum {}
diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout
new file mode 100644
index 000000000..64c012c1f
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enums.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 6 | 75.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/exotic.rs b/src/test/rustdoc-ui/coverage/exotic.rs
new file mode 100644
index 000000000..72b70d698
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/exotic.rs
@@ -0,0 +1,15 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+#![feature(rustdoc_internals)]
+
+//! the features only used in std also have entries in the table, so make sure those get pulled out
+//! properly as well
+
+/// woo, check it out, we can write our own primitive docs lol
+#[doc(primitive="unit")]
+mod prim_unit {}
+
+/// keywords? sure, pile them on
+#[doc(keyword="where")]
+mod where_keyword {}
diff --git a/src/test/rustdoc-ui/coverage/exotic.stdout b/src/test/rustdoc-ui/coverage/exotic.stdout
new file mode 100644
index 000000000..27798b813
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/exotic.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...st/rustdoc-ui/coverage/exotic.rs | 3 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 3 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/html.rs b/src/test/rustdoc-ui/coverage/html.rs
new file mode 100644
index 000000000..181cb4c50
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/html.rs
@@ -0,0 +1,4 @@
+// compile-flags:-Z unstable-options --output-format html --show-coverage
+
+/// Foo
+pub struct Xo;
diff --git a/src/test/rustdoc-ui/coverage/html.stderr b/src/test/rustdoc-ui/coverage/html.stderr
new file mode 100644
index 000000000..adca375d4
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/html.stderr
@@ -0,0 +1,2 @@
+error: html output format isn't supported for the --show-coverage option
+
diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs
new file mode 100644
index 000000000..a591cd5db
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/json.rs
@@ -0,0 +1,65 @@
+// check-pass
+// compile-flags:-Z unstable-options --output-format json --show-coverage
+
+pub mod foo {
+ /// Hello!
+ pub struct Foo;
+ /// Bar
+ pub enum Bar { A }
+}
+
+/// X
+pub struct X;
+
+/// Bar
+///
+/// ```
+/// let x = 12;
+/// ```
+pub mod bar {
+ /// bar
+ pub struct Bar;
+ /// X
+ pub enum X {
+ /// ```
+ /// let x = "should be ignored!";
+ /// ```
+ Y
+ }
+}
+
+/// yolo
+///
+/// ```text
+/// should not be counted as a code example!
+/// ```
+pub enum Yolo { X }
+
+impl Yolo {
+ /// ```
+ /// let x = "should be ignored!";
+ /// ```
+ pub const Const: u32 = 0;
+}
+
+pub struct Xo<T: Clone> {
+ /// ```
+ /// let x = "should be ignored!";
+ /// ```
+ x: T,
+}
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub static StaticFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub const ConstFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub type TypeFoo = u32;
diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout
new file mode 100644
index 000000000..c2be73ce3
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/json.stdout
@@ -0,0 +1 @@
+{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}}
diff --git a/src/test/rustdoc-ui/coverage/private.rs b/src/test/rustdoc-ui/coverage/private.rs
new file mode 100644
index 000000000..2a0271727
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/private.rs
@@ -0,0 +1,21 @@
+// compile-flags:-Z unstable-options --show-coverage --document-private-items
+// check-pass
+
+#![allow(unused)]
+
+//! when `--document-private-items` is passed, nothing is safe. everything must have docs or your
+//! score will suffer the consequences
+
+mod this_mod {
+ fn private_fn() {}
+}
+
+/// See, our public items have docs!
+pub struct SomeStruct {
+ /// Look, all perfectly documented!
+ pub field: usize,
+ other: usize,
+}
+
+/// Nothing shady going on here. Just a bunch of well-documented code. (cough)
+pub fn public_fn() {}
diff --git a/src/test/rustdoc-ui/coverage/private.stdout b/src/test/rustdoc-ui/coverage/private.stdout
new file mode 100644
index 000000000..37a0f5187
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/private.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...t/rustdoc-ui/coverage/private.rs | 4 | 57.1% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 4 | 57.1% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/statics-consts.rs b/src/test/rustdoc-ui/coverage/statics-consts.rs
new file mode 100644
index 000000000..5a35260fa
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/statics-consts.rs
@@ -0,0 +1,23 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! gotta make sure we can count statics and consts correctly, too
+
+/// static like electricity, right?
+pub static THIS_STATIC: usize = 0;
+
+/// (it's not electricity, is it)
+pub const THIS_CONST: usize = 1;
+
+/// associated consts show up separately, but let's throw them in as well
+pub trait SomeTrait {
+ /// just like that, yeah
+ const ASSOC_CONST: usize;
+}
+
+pub struct SomeStruct;
+
+impl SomeStruct {
+ /// wait, structs can have them too, can't forget those
+ pub const ASSOC_CONST: usize = 100;
+}
diff --git a/src/test/rustdoc-ui/coverage/statics-consts.stdout b/src/test/rustdoc-ui/coverage/statics-consts.stdout
new file mode 100644
index 000000000..dbea3a3ea
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/statics-consts.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...oc-ui/coverage/statics-consts.rs | 6 | 85.7% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 6 | 85.7% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/traits.rs b/src/test/rustdoc-ui/coverage/traits.rs
new file mode 100644
index 000000000..daa08ec25
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/traits.rs
@@ -0,0 +1,38 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+#![feature(trait_alias)]
+#![feature(type_alias_impl_trait)]
+
+/// look at this trait right here
+pub trait ThisTrait {
+ /// that's a trait all right
+ fn right_here(&self);
+
+ /// even the provided functions show up as trait methods
+ fn aww_yeah(&self) {}
+
+ /// gotta check those associated types, they're slippery
+ type SomeType;
+}
+
+/// so what happens if we take some struct...
+#[derive(Clone)]
+pub struct SomeStruct;
+
+/// ...and slap this trait on it?
+impl ThisTrait for SomeStruct {
+ /// nothing! trait impls are totally ignored in this calculation, sorry.
+ fn right_here(&self) {}
+
+ type SomeType = String;
+}
+
+/// but what about those aliases? i hear they're pretty exotic
+pub trait MyAlias = ThisTrait + Send + Sync;
+
+/// woah, getting all opaque in here
+pub type ThisExists = impl ThisTrait;
+
+/// why don't we get a little more concrete
+pub fn defines() -> ThisExists { SomeStruct {} }
diff --git a/src/test/rustdoc-ui/coverage/traits.stdout b/src/test/rustdoc-ui/coverage/traits.stdout
new file mode 100644
index 000000000..5053d0209
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/traits.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...st/rustdoc-ui/coverage/traits.rs | 8 | 88.9% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 8 | 88.9% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs
new file mode 100644
index 000000000..09da124b1
--- /dev/null
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs
@@ -0,0 +1,4 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [v2] //~ ERROR
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
new file mode 100644
index 000000000..67d9c3989
--- /dev/null
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `v2`
+ --> $DIR/deny-intra-link-resolution-failure.rs:3:6
+ |
+LL | /// [v2]
+ | ^^ no item named `v2` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/deny-intra-link-resolution-failure.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/deny-missing-docs-crate.rs b/src/test/rustdoc-ui/deny-missing-docs-crate.rs
new file mode 100644
index 000000000..b74eba3f6
--- /dev/null
+++ b/src/test/rustdoc-ui/deny-missing-docs-crate.rs
@@ -0,0 +1,3 @@
+#![deny(missing_docs)] //~ ERROR
+
+pub struct Foo; //~ ERROR
diff --git a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr
new file mode 100644
index 000000000..5025b0b0c
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/deny-missing-docs-macro.rs b/src/test/rustdoc-ui/deny-missing-docs-macro.rs
new file mode 100644
index 000000000..b1c125317
--- /dev/null
+++ b/src/test/rustdoc-ui/deny-missing-docs-macro.rs
@@ -0,0 +1,8 @@
+//! foo
+
+#![deny(missing_docs)]
+
+#[macro_export]
+macro_rules! foo { //~ ERROR
+ () => {}
+}
diff --git a/src/test/rustdoc-ui/deny-missing-docs-macro.stderr b/src/test/rustdoc-ui/deny-missing-docs-macro.stderr
new file mode 100644
index 000000000..0867b0818
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/deprecated-attrs.rs b/src/test/rustdoc-ui/deprecated-attrs.rs
new file mode 100644
index 000000000..4f6a14fc2
--- /dev/null
+++ b/src/test/rustdoc-ui/deprecated-attrs.rs
@@ -0,0 +1,16 @@
+// check-pass
+// compile-flags: --passes unknown-pass
+// error-pattern: the `passes` flag no longer functions
+
+#![doc(no_default_passes)]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| HELP no longer functions; you may want to use `#![doc(document_private_items)]`
+#![doc(passes = "collapse-docs unindent-comments")]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| HELP no longer functions; you may want to use `#![doc(document_private_items)]`
+#![doc(plugins = "xxx")]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| WARNING no longer functions; see CVE
diff --git a/src/test/rustdoc-ui/deprecated-attrs.stderr b/src/test/rustdoc-ui/deprecated-attrs.stderr
new file mode 100644
index 000000000..45b20ce70
--- /dev/null
+++ b/src/test/rustdoc-ui/deprecated-attrs.stderr
@@ -0,0 +1,34 @@
+warning: the `passes` flag no longer functions
+ |
+ = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+ = help: you may want to use --document-private-items
+
+warning: the `#![doc(no_default_passes)]` attribute is deprecated
+ --> $DIR/deprecated-attrs.rs:5:8
+ |
+LL | #![doc(no_default_passes)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+ = help: `#![doc(no_default_passes)]` no longer functions; you may want to use `#![doc(document_private_items)]`
+
+warning: the `#![doc(passes = "...")]` attribute is deprecated
+ --> $DIR/deprecated-attrs.rs:9:8
+ |
+LL | #![doc(passes = "collapse-docs unindent-comments")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+ = help: `#![doc(passes = "...")]` no longer functions; you may want to use `#![doc(document_private_items)]`
+
+warning: the `#![doc(plugins = "...")]` attribute is deprecated
+ --> $DIR/deprecated-attrs.rs:13:8
+ |
+LL | #![doc(plugins = "xxx")]
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+ = warning: `#![doc(plugins = "...")]` no longer functions; see CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>
+
+warning: 3 warnings emitted
+
diff --git a/src/test/rustdoc-ui/deref-generic.rs b/src/test/rustdoc-ui/deref-generic.rs
new file mode 100644
index 000000000..bc64beb1b
--- /dev/null
+++ b/src/test/rustdoc-ui/deref-generic.rs
@@ -0,0 +1,15 @@
+// check-pass
+// #81395: Fix ICE when recursing into Deref target only differing in type args
+
+pub struct Generic<T>(T);
+
+impl<'a> std::ops::Deref for Generic<&'a mut ()> {
+ type Target = Generic<&'a ()>;
+ fn deref(&self) -> &Self::Target {
+ unimplemented!()
+ }
+}
+
+impl<'a> Generic<&'a ()> {
+ pub fn some_method(&self) {}
+}
diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs
new file mode 100644
index 000000000..61961d5ec
--- /dev/null
+++ b/src/test/rustdoc-ui/diagnostic-width.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Zunstable-options --diagnostic-width=10
+#![deny(rustdoc::bare_urls)]
+
+/// This is a long line that contains a http://link.com
+pub struct Foo; //~^ ERROR
diff --git a/src/test/rustdoc-ui/diagnostic-width.stderr b/src/test/rustdoc-ui/diagnostic-width.stderr
new file mode 100644
index 000000000..fed049d2b
--- /dev/null
+++ b/src/test/rustdoc-ui/diagnostic-width.stderr
@@ -0,0 +1,15 @@
+error: this URL is not a hyperlink
+ --> $DIR/diagnostic-width.rs:4:41
+ |
+LL | ... a http://link.com
+ | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://link.com>`
+ |
+note: the lint level is defined here
+ --> $DIR/diagnostic-width.rs:2:9
+ |
+LL | ...ny(rustdoc::bare_url...
+ | ^^^^^^^^^^^^^^^^^^
+ = note: bare URLs are not automatically turned into clickable links
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/display-output.rs b/src/test/rustdoc-ui/display-output.rs
new file mode 100644
index 000000000..ec27a9f6b
--- /dev/null
+++ b/src/test/rustdoc-ui/display-output.rs
@@ -0,0 +1,15 @@
+// Test that `--show-output` has an effect and `allow(unused)` can be overridden.
+
+// check-pass
+// edition:2018
+// compile-flags:--test --test-args=--show-output
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// #![warn(unused)]
+/// let x = 12;
+///
+/// fn foo(x: &dyn std::fmt::Display) {}
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout
new file mode 100644
index 000000000..ad25d1ce5
--- /dev/null
+++ b/src/test/rustdoc-ui/display-output.stdout
@@ -0,0 +1,43 @@
+
+running 1 test
+test $DIR/display-output.rs - foo (line 9) ... ok
+
+successes:
+
+---- $DIR/display-output.rs - foo (line 9) stdout ----
+warning: unused variable: `x`
+ --> $DIR/display-output.rs:11:5
+ |
+LL | let x = 12;
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+ |
+note: the lint level is defined here
+ --> $DIR/display-output.rs:9:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `x`
+ --> $DIR/display-output.rs:13:8
+ |
+LL | fn foo(x: &dyn std::fmt::Display) {}
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+warning: function `foo` is never used
+ --> $DIR/display-output.rs:13:4
+ |
+LL | fn foo(x: &dyn std::fmt::Display) {}
+ | ^^^
+ |
+ = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+
+warning: 3 warnings emitted
+
+
+
+successes:
+ $DIR/display-output.rs - foo (line 9)
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doc-alias-assoc-const.rs b/src/test/rustdoc-ui/doc-alias-assoc-const.rs
new file mode 100644
index 000000000..d95324734
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-assoc-const.rs
@@ -0,0 +1,21 @@
+#![feature(trait_alias)]
+
+pub struct Foo;
+
+pub trait Bar {
+ const BAZ: u8;
+}
+
+impl Bar for Foo {
+ #[doc(alias = "CONST_BAZ")] //~ ERROR
+ const BAZ: u8 = 0;
+}
+
+impl Foo {
+ #[doc(alias = "CONST_FOO")] // ok!
+ pub const FOO: u8 = 0;
+
+ pub fn bar() -> u8 {
+ Self::FOO
+ }
+}
diff --git a/src/test/rustdoc-ui/doc-alias-assoc-const.stderr b/src/test/rustdoc-ui/doc-alias-assoc-const.stderr
new file mode 100644
index 000000000..cbca40e13
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-assoc-const.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block
+ --> $DIR/doc-alias-assoc-const.rs:10:11
+ |
+LL | #[doc(alias = "CONST_BAZ")]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.rs b/src/test/rustdoc-ui/doc-alias-crate-level.rs
new file mode 100644
index 000000000..70618ac01
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.rs
@@ -0,0 +1,4 @@
+#![doc(alias = "crate-level-not-working")] //~ ERROR
+
+#[doc(alias = "shouldn't work!")] //~ ERROR
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
new file mode 100644
index 000000000..fc8095e03
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
@@ -0,0 +1,14 @@
+error: '\'' character isn't allowed in `#[doc(alias = "...")]`
+ --> $DIR/doc-alias-crate-level.rs:3:15
+ |
+LL | #[doc(alias = "shouldn't work!")]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute
+ --> $DIR/doc-alias-crate-level.rs:1:8
+ |
+LL | #![doc(alias = "crate-level-not-working")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.rs b/src/test/rustdoc-ui/doc-alias-same-name.rs
new file mode 100644
index 000000000..da97c2676
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "Foo")] //~ ERROR
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.stderr b/src/test/rustdoc-ui/doc-alias-same-name.stderr
new file mode 100644
index 000000000..5ba09a2ea
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` is the same as the item's name
+ --> $DIR/doc-alias-same-name.rs:3:7
+ |
+LL | #[doc(alias = "Foo")]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/doc-attr.rs b/src/test/rustdoc-ui/doc-attr.rs
new file mode 100644
index 000000000..980d1c0e2
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr
new file mode 100644
index 000000000..cc2494c92
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-attr.stderr
@@ -0,0 +1,71 @@
+error: unknown `doc` attribute `as_ptr`
+ --> $DIR/doc-attr.rs:7:7
+ |
+LL | #[doc(as_ptr)]
+ | ^^^^^^
+ |
+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)]`
+ = 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: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/src/test/rustdoc-ui/doc-cfg.rs b/src/test/rustdoc-ui/doc-cfg.rs
new file mode 100644
index 000000000..354d76bc3
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-cfg.rs
@@ -0,0 +1,9 @@
+#![feature(doc_cfg)]
+
+#[doc(cfg(), cfg(foo, bar))]
+//~^ ERROR
+//~^^ ERROR
+#[doc(cfg(foo), cfg(bar))] // ok!
+#[doc(cfg())] //~ ERROR
+#[doc(cfg(foo, bar))] //~ ERROR
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc-cfg.stderr b/src/test/rustdoc-ui/doc-cfg.stderr
new file mode 100644
index 000000000..b379f6feb
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-cfg.stderr
@@ -0,0 +1,26 @@
+error: `cfg` predicate is not specified
+ --> $DIR/doc-cfg.rs:3:7
+ |
+LL | #[doc(cfg(), cfg(foo, bar))]
+ | ^^^^^
+
+error: multiple `cfg` predicates are specified
+ --> $DIR/doc-cfg.rs:3:23
+ |
+LL | #[doc(cfg(), cfg(foo, bar))]
+ | ^^^
+
+error: `cfg` predicate is not specified
+ --> $DIR/doc-cfg.rs:7:7
+ |
+LL | #[doc(cfg())]
+ | ^^^^^
+
+error: multiple `cfg` predicates are specified
+ --> $DIR/doc-cfg.rs:8:16
+ |
+LL | #[doc(cfg(foo, bar))]
+ | ^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs b/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs
new file mode 100644
index 000000000..97259f782
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-attr.rs
@@ -0,0 +1,11 @@
+// Regression test for #97440: Multiline inner attribute triggers ICE during doctest
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+//! ```rust
+//! #![deny(
+//! unused_parens,
+//! )]
+//! ```
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout b/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout
new file mode 100644
index 000000000..e47edbd2a
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-attr.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-comment-multi-line-attr.rs - (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs b/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs
new file mode 100644
index 000000000..b2a8133c9
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+/// ```
+/// # #![cfg_attr(not(dox), deny(missing_abi,
+/// # non_ascii_idents))]
+///
+/// pub struct Bar;
+/// ```
+pub struct Bar;
diff --git a/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.stdout b/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.stdout
new file mode 100644
index 000000000..bf3521e4f
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-comment-multi-line-cfg-attr.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-comment-multi-line-cfg-attr.rs - Bar (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.rs b/src/test/rustdoc-ui/doc-include-suggestion.rs
new file mode 100644
index 000000000..0c0100735
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-include-suggestion.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#[doc(include = "external-cross-doc.md")]
+//~^ WARNING unknown `doc` attribute `include`
+//~| HELP use `doc = include_str!` instead
+// FIXME(#85497): make this a deny instead so it's more clear what's happening
+//~| NOTE on by default
+//~| WARNING previously accepted
+//~| NOTE see issue #82730
+pub struct NeedMoreDocs;
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.stderr b/src/test/rustdoc-ui/doc-include-suggestion.stderr
new file mode 100644
index 000000000..870b7efa2
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-include-suggestion.stderr
@@ -0,0 +1,12 @@
+warning: unknown `doc` attribute `include`
+ --> $DIR/doc-include-suggestion.rs:3:7
+ |
+LL | #[doc(include = "external-cross-doc.md")]
+ | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
+ |
+ = note: `#[warn(invalid_doc_attributes)]` on by default
+ = 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>
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/doc-spotlight.fixed b/src/test/rustdoc-ui/doc-spotlight.fixed
new file mode 100644
index 000000000..4b58778ea
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/doc-spotlight.rs b/src/test/rustdoc-ui/doc-spotlight.rs
new file mode 100644
index 000000000..16e387245
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/doc-spotlight.stderr b/src/test/rustdoc-ui/doc-spotlight.stderr
new file mode 100644
index 000000000..8e7831139
--- /dev/null
+++ b/src/test/rustdoc-ui/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
+ |
+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)]`
+ = 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
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/doc-test-attr-pass.rs b/src/test/rustdoc-ui/doc-test-attr-pass.rs
new file mode 100644
index 000000000..12608f244
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-attr-pass.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![crate_type = "lib"]
+#![deny(invalid_doc_attributes)]
+#![doc(test(no_crate_inject))]
+#![doc(test(attr(deny(warnings))))]
+
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc-test-attr.rs b/src/test/rustdoc-ui/doc-test-attr.rs
new file mode 100644
index 000000000..46178ad86
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-attr.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+#![deny(invalid_doc_attributes)]
+
+#![doc(test)]
+//~^ ERROR `#[doc(test(...)]` takes a list of attributes
+//~^^ WARN this was previously accepted by the compiler
+#![doc(test = "hello")]
+//~^ ERROR `#[doc(test(...)]` takes a list of attributes
+//~^^ WARN this was previously accepted by the compiler
+#![doc(test(a))]
+//~^ ERROR unknown `doc(test)` attribute `a`
+//~^^ WARN this was previously accepted by the compiler
+
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc-test-attr.stderr b/src/test/rustdoc-ui/doc-test-attr.stderr
new file mode 100644
index 000000000..7f5e2d6bc
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-attr.stderr
@@ -0,0 +1,34 @@
+error: `#[doc(test(...)]` takes a list of attributes
+ --> $DIR/doc-test-attr.rs:4:8
+ |
+LL | #![doc(test)]
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/doc-test-attr.rs:2:9
+ |
+LL | #![deny(invalid_doc_attributes)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = 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(test(...)]` takes a list of attributes
+ --> $DIR/doc-test-attr.rs:7:8
+ |
+LL | #![doc(test = "hello")]
+ | ^^^^^^^^^^^^^^
+ |
+ = 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(test)` attribute `a`
+ --> $DIR/doc-test-attr.rs:10:13
+ |
+LL | #![doc(test(a))]
+ | ^
+ |
+ = 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/src/test/rustdoc-ui/doc-test-doctest-feature.rs b/src/test/rustdoc-ui/doc-test-doctest-feature.rs
new file mode 100644
index 000000000..0b79aaece
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-doctest-feature.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// Make sure `cfg(doctest)` is set when finding doctests but not inside
+// the doctests.
+
+/// ```
+/// assert!(!cfg!(doctest));
+/// ```
+#[cfg(doctest)]
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-test-doctest-feature.stdout b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout
new file mode 100644
index 000000000..d7de1f105
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-test-doctest-feature.rs - Foo (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs b/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs
new file mode 100644
index 000000000..bf334c67e
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs
@@ -0,0 +1,15 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+#![feature(doc_cfg)]
+
+// Make sure `cfg(doc)` is set when finding doctests but not inside the doctests.
+
+/// ```
+/// #![feature(doc_cfg)]
+/// assert!(!cfg!(doc));
+/// ```
+#[cfg(doc)]
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout b/src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout
new file mode 100644
index 000000000..5b07fc4c8
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-test-rustdoc-feature.rs - Foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doc-without-codeblock.rs b/src/test/rustdoc-ui/doc-without-codeblock.rs
new file mode 100644
index 000000000..315fca195
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-without-codeblock.rs
@@ -0,0 +1,22 @@
+#![deny(rustdoc::missing_doc_code_examples)] //~ ERROR missing code example in this documentation
+
+/// 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/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr
new file mode 100644
index 000000000..1c1380441
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr
@@ -0,0 +1,38 @@
+error: missing code example in this documentation
+ --> $DIR/doc-without-codeblock.rs:1:1
+ |
+LL | / #![deny(rustdoc::missing_doc_code_examples)]
+LL | |
+LL | | /// Some docs.
+LL | |
+... |
+LL | | }
+LL | | }
+ | |_^
+ |
+note: the lint level is defined here
+ --> $DIR/doc-without-codeblock.rs:1:9
+ |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/doc-without-codeblock.rs:7:1
+ |
+LL | /// And then, the princess died.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/doc-without-codeblock.rs:10:5
+ |
+LL | /// Or maybe not because she saved herself!
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/doc-without-codeblock.rs:3:1
+ |
+LL | /// Some docs.
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/doctest-edition.rs b/src/test/rustdoc-ui/doctest-edition.rs
new file mode 100644
index 000000000..b0787be97
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-edition.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![deny(rustdoc::invalid_rust_codeblocks)]
+//~^ NOTE lint level is defined here
+
+// By default, rustdoc should use the edition of the crate.
+//! ```
+//! foo'b'
+//! ```
+//~^^^ ERROR could not parse
+//~| NOTE prefix `foo` is unknown
+
+// Rustdoc should respect `edition2018` when highlighting syntax.
+//! ```edition2018
+//! foo'b'
+//! ```
diff --git a/src/test/rustdoc-ui/doctest-edition.stderr b/src/test/rustdoc-ui/doctest-edition.stderr
new file mode 100644
index 000000000..1643d6053
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-edition.stderr
@@ -0,0 +1,22 @@
+error: could not parse code block as Rust code
+ --> $DIR/doctest-edition.rs:7:5
+ |
+LL | //! ```
+ | _____^
+LL | | //! foo'b'
+LL | | //! ```
+ | |_______^
+ |
+note: the lint level is defined here
+ --> $DIR/doctest-edition.rs:3:9
+ |
+LL | #![deny(rustdoc::invalid_rust_codeblocks)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: error from rustc: prefix `foo` is unknown
+help: mark blocks that do not contain Rust code as text
+ |
+LL | //! ```text
+ | ++++
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/doctest-multiline-crate-attribute.rs b/src/test/rustdoc-ui/doctest-multiline-crate-attribute.rs
new file mode 100644
index 000000000..a30472ac5
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-multiline-crate-attribute.rs
@@ -0,0 +1,10 @@
+// compile-flags:--test --test-args=--test-threads=1
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+/// ```
+/// #![deprecated(since = "5.2", note = "foo was rarely used. \
+/// Users should instead use bar")]
+/// ```
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/doctest-multiline-crate-attribute.stdout b/src/test/rustdoc-ui/doctest-multiline-crate-attribute.stdout
new file mode 100644
index 000000000..07a4f657d
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-multiline-crate-attribute.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doctest-multiline-crate-attribute.rs - f (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/doctest-output.rs b/src/test/rustdoc-ui/doctest-output.rs
new file mode 100644
index 000000000..2670fa572
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-output.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// aux-build:extern_macros.rs
+// compile-flags:--test --test-args=--test-threads=1
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+//! ```
+//! assert_eq!(1 + 1, 2);
+//! ```
+
+extern crate extern_macros as macros;
+
+use macros::attrs_on_struct;
+
+pub mod foo {
+
+ /// ```
+ /// assert_eq!(1 + 1, 2);
+ /// ```
+ pub fn bar() {}
+}
+
+attrs_on_struct! {
+ /// ```
+ /// assert!(true);
+ /// ```
+}
diff --git a/src/test/rustdoc-ui/doctest-output.stdout b/src/test/rustdoc-ui/doctest-output.stdout
new file mode 100644
index 000000000..35b0e366f
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-output.stdout
@@ -0,0 +1,8 @@
+
+running 3 tests
+test $DIR/doctest-output.rs - (line 8) ... ok
+test $DIR/doctest-output.rs - ExpandedStruct (line 24) ... ok
+test $DIR/doctest-output.rs - foo::bar (line 18) ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/README.md b/src/test/rustdoc-ui/error-in-impl-trait/README.md
new file mode 100644
index 000000000..1176a4a8c
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/README.md
@@ -0,0 +1,7 @@
+Each of these needs to be in a separate file,
+because the `delay_span_bug` ICE in rustdoc won't be triggerred
+if even a single other error was emitted.
+
+However, conceptually they are all testing basically the same thing.
+See https://github.com/rust-lang/rust/pull/73566#issuecomment-653689128
+for more details.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/async.rs b/src/test/rustdoc-ui/error-in-impl-trait/async.rs
new file mode 100644
index 000000000..cda53bff0
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/async.rs
@@ -0,0 +1,7 @@
+// edition:2018
+// check-pass
+
+/// Should compile fine
+pub async fn a() -> u32 {
+ error::_in::async_fn()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs
new file mode 100644
index 000000000..f1fd85bb2
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs
@@ -0,0 +1,5 @@
+// check-pass
+// manually desugared version of an `async fn` (but with a closure instead of a generator)
+pub fn a() -> impl Fn() -> u32 {
+ || content::doesnt::matter()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs
new file mode 100644
index 000000000..ed62f0208
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs
@@ -0,0 +1,23 @@
+// check-pass
+// edition:2018
+trait ValidTrait {}
+
+/// This has docs
+pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]> {
+ loop {}
+}
+
+pub trait Trait<const N: usize> {}
+impl Trait<1> for u8 {}
+impl Trait<2> for u8 {}
+impl<const N: usize> Trait<N> for [u8; N] {}
+
+/// This also has docs
+pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
+ loop {}
+}
+
+/// Document all the functions
+pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
+ loop {}
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs
new file mode 100644
index 000000000..dcec379d4
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs
@@ -0,0 +1,7 @@
+// check-pass
+trait ValidTrait {}
+
+/// This has docs
+pub fn f() -> impl ValidTrait {
+ Vec::<DoesNotExist>::new()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs
new file mode 100644
index 000000000..b935b0832
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs
@@ -0,0 +1,6 @@
+// check-pass
+pub trait ValidTrait {}
+/// This returns impl trait
+pub fn g() -> impl ValidTrait {
+ (|| error::_in::impl_trait::alias::nested::closure())()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
new file mode 100644
index 000000000..701126f87
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
@@ -0,0 +1,6 @@
+// check-pass
+pub trait ValidTrait {}
+/// This returns impl trait
+pub fn g() -> impl ValidTrait {
+ error::_in::impl_trait()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs b/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs
new file mode 100644
index 000000000..248575d35
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// check-pass
+
+mod windows {
+ pub trait WinFoo {
+ fn foo(&self) {}
+ }
+
+ impl WinFoo for () {}
+}
+
+#[cfg(any(windows, doc))]
+use windows::*;
+
+mod unix {
+ pub trait UnixFoo {
+ fn foo(&self) {}
+ }
+
+ impl UnixFoo for () {}
+}
+
+#[cfg(any(unix, doc))]
+use unix::*;
+
+async fn bar() {
+ ().foo()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs
new file mode 100644
index 000000000..31dd786cb
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs
@@ -0,0 +1,10 @@
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+pub trait ValidTrait {}
+type ImplTrait = impl ValidTrait;
+
+/// This returns impl trait, but using a type alias
+pub fn h() -> ImplTrait {
+ (|| error::_in::impl_trait::alias::nested::closure())()
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
new file mode 100644
index 000000000..c18a024af
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
@@ -0,0 +1,10 @@
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+pub trait ValidTrait {}
+type ImplTrait = impl ValidTrait;
+
+/// This returns impl trait, but using a type alias
+pub fn h() -> ImplTrait {
+ error::_in::impl_trait::alias()
+}
diff --git a/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs
new file mode 100644
index 000000000..0901ac364
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr
new file mode 100644
index 000000000..efc5f349f
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/failed-doctest-compile-fail.rs b/src/test/rustdoc-ui/failed-doctest-compile-fail.rs
new file mode 100644
index 000000000..6f2ff5d70
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-compile-fail.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```compile_fail
+/// println!("Hello");
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
new file mode 100644
index 000000000..af3a90a74
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
@@ -0,0 +1,14 @@
+
+running 1 test
+test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) - compile fail ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-compile-fail.rs - Foo (line 9) stdout ----
+Test compiled successfully, but it's marked `compile_fail`.
+
+failures:
+ $DIR/failed-doctest-compile-fail.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs
new file mode 100644
index 000000000..16d737106
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs
@@ -0,0 +1,18 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// <https://github.com/rust-lang/rust/issues/91014>
+///
+/// ```rust
+/// struct S {}; // unexpected semicolon after struct def
+///
+/// fn main() {
+/// assert_eq!(0, 1);
+/// }
+/// ```
+mod m {}
diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout
new file mode 100644
index 000000000..61468b6c7
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ----
+error: expected item, found `;`
+ --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12
+ |
+LL | struct S {}; // unexpected semicolon after struct def
+ | ^ help: remove this semicolon
+ |
+ = help: braced struct declarations are not followed by a semicolon
+
+error: aborting due to previous error
+
+Couldn't compile the test.
+
+failures:
+ $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/failed-doctest-missing-codes.rs b/src/test/rustdoc-ui/failed-doctest-missing-codes.rs
new file mode 100644
index 000000000..57b70b478
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-missing-codes.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```compile_fail,E0004
+/// let x: () = 5i32;
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
new file mode 100644
index 000000000..bacbb47b5
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
@@ -0,0 +1,25 @@
+
+running 1 test
+test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) - compile fail ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-missing-codes.rs - Foo (line 9) stdout ----
+error[E0308]: mismatched types
+ --> $DIR/failed-doctest-missing-codes.rs:10:13
+ |
+LL | let x: () = 5i32;
+ | -- ^^^^ expected `()`, found `i32`
+ | |
+ | expected due to this
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
+Some expected error codes were not found: ["E0004"]
+
+failures:
+ $DIR/failed-doctest-missing-codes.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/failed-doctest-output-windows.rs b/src/test/rustdoc-ui/failed-doctest-output-windows.rs
new file mode 100644
index 000000000..4cd9993d8
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-output-windows.rs
@@ -0,0 +1,28 @@
+// only-windows
+// There's a parallel generic version of this test for non-windows platforms.
+
+// Issue #51162: A failed doctest was not printing its stdout/stderr
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test --test-args --test-threads=1
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+// doctest fails at runtime
+/// ```
+/// println!("stdout 1");
+/// eprintln!("stderr 1");
+/// println!("stdout 2");
+/// eprintln!("stderr 2");
+/// panic!("oh no");
+/// ```
+pub struct SomeStruct;
+
+// doctest fails at compile time
+/// ```
+/// no
+/// ```
+pub struct OtherStruct;
diff --git a/src/test/rustdoc-ui/failed-doctest-output-windows.stdout b/src/test/rustdoc-ui/failed-doctest-output-windows.stdout
new file mode 100644
index 000000000..6c147054d
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-output-windows.stdout
@@ -0,0 +1,39 @@
+
+running 2 tests
+test $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25) ... FAILED
+test $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25) stdout ----
+error[E0425]: cannot find value `no` in this scope
+ --> $DIR/failed-doctest-output-windows.rs:26:1
+ |
+LL | no
+ | ^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
+Couldn't compile the test.
+---- $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15) stdout ----
+Test executable failed (exit code: 101).
+
+stdout:
+stdout 1
+stdout 2
+
+stderr:
+stderr 1
+stderr 2
+thread 'main' panicked at 'oh no', $DIR/failed-doctest-output-windows.rs:7:1
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+
+failures:
+ $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25)
+ $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15)
+
+test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs
new file mode 100644
index 000000000..42de954d0
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-output.rs
@@ -0,0 +1,28 @@
+// ignore-windows
+// There's a parallel version of this test for Windows.
+
+// Issue #51162: A failed doctest was not printing its stdout/stderr
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test --test-args --test-threads=1
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+// doctest fails at runtime
+/// ```
+/// println!("stdout 1");
+/// eprintln!("stderr 1");
+/// println!("stdout 2");
+/// eprintln!("stderr 2");
+/// panic!("oh no");
+/// ```
+pub struct SomeStruct;
+
+// doctest fails at compile time
+/// ```
+/// no
+/// ```
+pub struct OtherStruct;
diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout
new file mode 100644
index 000000000..630198a56
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-output.stdout
@@ -0,0 +1,39 @@
+
+running 2 tests
+test $DIR/failed-doctest-output.rs - OtherStruct (line 25) ... FAILED
+test $DIR/failed-doctest-output.rs - SomeStruct (line 15) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-output.rs - OtherStruct (line 25) stdout ----
+error[E0425]: cannot find value `no` in this scope
+ --> $DIR/failed-doctest-output.rs:26:1
+ |
+LL | no
+ | ^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
+Couldn't compile the test.
+---- $DIR/failed-doctest-output.rs - SomeStruct (line 15) stdout ----
+Test executable failed (exit status: 101).
+
+stdout:
+stdout 1
+stdout 2
+
+stderr:
+stderr 1
+stderr 2
+thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:7:1
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+
+failures:
+ $DIR/failed-doctest-output.rs - OtherStruct (line 25)
+ $DIR/failed-doctest-output.rs - SomeStruct (line 15)
+
+test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/failed-doctest-should-panic.rs b/src/test/rustdoc-ui/failed-doctest-should-panic.rs
new file mode 100644
index 000000000..2b8bb3168
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-should-panic.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```should_panic
+/// println!("Hello, world!");
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/failed-doctest-should-panic.stdout b/src/test/rustdoc-ui/failed-doctest-should-panic.stdout
new file mode 100644
index 000000000..57a20092a
--- /dev/null
+++ b/src/test/rustdoc-ui/failed-doctest-should-panic.stdout
@@ -0,0 +1,14 @@
+
+running 1 test
+test $DIR/failed-doctest-should-panic.rs - Foo (line 9) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-should-panic.rs - Foo (line 9) stdout ----
+Test executable succeeded, but it's marked `should_panic`.
+
+failures:
+ $DIR/failed-doctest-should-panic.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs
new file mode 100644
index 000000000..17812018b
--- /dev/null
+++ b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs
@@ -0,0 +1,7 @@
+#![doc(cfg_hide(test))]
+//~^ ERROR `#[doc(cfg_hide)]` is experimental
+
+#[cfg(not(test))]
+pub fn public_fn() {}
+#[cfg(test)]
+pub fn internal_use_only() {}
diff --git a/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
new file mode 100644
index 000000000..ba42c7bbb
--- /dev/null
+++ b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
@@ -0,0 +1,14 @@
+error[E0658]: `#[doc(cfg_hide)]` is experimental
+ --> $DIR/feature-gate-doc_cfg_hide.rs:1:1
+ |
+LL | #![doc(cfg_hide(test))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #43781 <https://github.com/rust-lang/rust/issues/43781> for more information
+ = help: add `#![feature(doc_cfg_hide)]` to the crate attributes to enable
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.rs b/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.rs
new file mode 100644
index 000000000..87620d74e
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.rs
@@ -0,0 +1,6 @@
+// This test purpose is to check that the "--generate-link-to-definition"
+// option can only be used on nightly.
+
+// compile-flags: --generate-link-to-definition
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.stderr b/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.stderr
new file mode 100644
index 000000000..a8ddf91bc
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt-unstable.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `generate-link-to-definition`
+
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt.rs b/src/test/rustdoc-ui/generate-link-to-definition-opt.rs
new file mode 100644
index 000000000..8f4f561b4
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt.rs
@@ -0,0 +1,6 @@
+// This test purpose is to check that the "--generate-link-to-definition"
+// option can only be used with HTML generation.
+
+// compile-flags: -Zunstable-options --generate-link-to-definition --output-format json
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt.stderr b/src/test/rustdoc-ui/generate-link-to-definition-opt.stderr
new file mode 100644
index 000000000..4c8c607e7
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt.stderr
@@ -0,0 +1,2 @@
+error: --generate-link-to-definition option can only be used with HTML output format
+
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt2.rs b/src/test/rustdoc-ui/generate-link-to-definition-opt2.rs
new file mode 100644
index 000000000..da5142087
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt2.rs
@@ -0,0 +1,6 @@
+// This test purpose is to check that the "--generate-link-to-definition"
+// option can only be used with HTML generation.
+
+// compile-flags: -Zunstable-options --generate-link-to-definition --show-coverage
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/generate-link-to-definition-opt2.stderr b/src/test/rustdoc-ui/generate-link-to-definition-opt2.stderr
new file mode 100644
index 000000000..4c8c607e7
--- /dev/null
+++ b/src/test/rustdoc-ui/generate-link-to-definition-opt2.stderr
@@ -0,0 +1,2 @@
+error: --generate-link-to-definition option can only be used with HTML output format
+
diff --git a/src/test/rustdoc-ui/ignore-block-help.rs b/src/test/rustdoc-ui/ignore-block-help.rs
new file mode 100644
index 000000000..86f6a2868
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+/// ```ignore (to-prevent-tidy-error)
+/// let heart = 'â¤ï¸';
+/// ```
+//~^^^ WARNING could not parse code block
+//~| NOTE on by default
+//~| NOTE character literal may only contain one codepoint
+//~| HELP `ignore` code blocks require valid Rust code
+pub struct X;
diff --git a/src/test/rustdoc-ui/ignore-block-help.stderr b/src/test/rustdoc-ui/ignore-block-help.stderr
new file mode 100644
index 000000000..9c02ff11d
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.stderr
@@ -0,0 +1,19 @@
+warning: could not parse code block as Rust code
+ --> $DIR/ignore-block-help.rs:3:5
+ |
+LL | /// ```ignore (to-prevent-tidy-error)
+ | _____^
+LL | | /// let heart = 'â¤ï¸';
+LL | | /// ```
+ | |_______^
+ |
+ = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
+help: `ignore` code blocks require valid Rust code for syntax highlighting; mark blocks that do not contain Rust code as text: ```text
+ --> $DIR/ignore-block-help.rs:3:5
+ |
+LL | /// ```ignore (to-prevent-tidy-error)
+ | ^^^
+ = note: error from rustc: character literal may only contain one codepoint
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/impl-fn-nesting.rs b/src/test/rustdoc-ui/impl-fn-nesting.rs
new file mode 100644
index 000000000..a927f6bd7
--- /dev/null
+++ b/src/test/rustdoc-ui/impl-fn-nesting.rs
@@ -0,0 +1,49 @@
+// Ensure that rustdoc gives errors for trait impls inside function bodies that don't resolve.
+// See https://github.com/rust-lang/rust/pull/73566
+pub struct ValidType;
+pub trait ValidTrait {}
+pub trait NeedsBody {
+ type Item;
+ fn f();
+}
+
+/// This function has docs
+pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+//~^ ERROR cannot find trait `UnknownBound` in this scope
+//~| ERROR cannot find type `UnknownType` in this scope
+ impl UnknownTrait for ValidType {} //~ ERROR cannot find trait `UnknownTrait`
+ impl<T: UnknownBound> UnknownTrait for T {}
+ //~^ ERROR cannot find trait `UnknownBound` in this scope
+ //~| ERROR cannot find trait `UnknownTrait` in this scope
+ impl ValidTrait for UnknownType {}
+ //~^ ERROR cannot find type `UnknownType` in this scope
+ impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
+ //~^ ERROR cannot find trait `UnknownBound` in this scope
+
+ /// This impl has documentation
+ impl NeedsBody for ValidType {
+ type Item = UnknownType;
+ //~^ ERROR cannot find type `UnknownType` in this scope
+
+ /// This function has documentation
+ fn f() {
+ <UnknownTypeShouldBeIgnored>::a();
+ content::shouldnt::matter();
+ unknown_macro!();
+ //~^ ERROR cannot find macro `unknown_macro` in this scope
+
+ /// This is documentation for a macro
+ macro_rules! can_define_macros_here_too {
+ () => {
+ this::content::should::also::be::ignored()
+ }
+ }
+ can_define_macros_here_too!();
+
+ /// This also is documented.
+ pub fn doubly_nested(c: UnknownType) {
+ //~^ ERROR cannot find type `UnknownType` in this scope
+ }
+ }
+ }
+}
diff --git a/src/test/rustdoc-ui/impl-fn-nesting.stderr b/src/test/rustdoc-ui/impl-fn-nesting.stderr
new file mode 100644
index 000000000..608749af8
--- /dev/null
+++ b/src/test/rustdoc-ui/impl-fn-nesting.stderr
@@ -0,0 +1,66 @@
+error: cannot find macro `unknown_macro` in this scope
+ --> $DIR/impl-fn-nesting.rs:32:13
+ |
+LL | unknown_macro!();
+ | ^^^^^^^^^^^^^
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+ --> $DIR/impl-fn-nesting.rs:11:13
+ |
+LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+ --> $DIR/impl-fn-nesting.rs:11:30
+ |
+LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+ | ^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownTrait` in this scope
+ --> $DIR/impl-fn-nesting.rs:14:10
+ |
+LL | impl UnknownTrait for ValidType {}
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownTrait` in this scope
+ --> $DIR/impl-fn-nesting.rs:15:27
+ |
+LL | impl<T: UnknownBound> UnknownTrait for T {}
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+ --> $DIR/impl-fn-nesting.rs:15:13
+ |
+LL | impl<T: UnknownBound> UnknownTrait for T {}
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+ --> $DIR/impl-fn-nesting.rs:18:25
+ |
+LL | impl ValidTrait for UnknownType {}
+ | ^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+ --> $DIR/impl-fn-nesting.rs:20:53
+ |
+LL | impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+ --> $DIR/impl-fn-nesting.rs:25:21
+ |
+LL | type Item = UnknownType;
+ | ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+ --> $DIR/impl-fn-nesting.rs:44:37
+ |
+LL | pub fn doubly_nested(c: UnknownType) {
+ | ^^^^^^^^^^^ not found in this scope
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0405, E0412.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
new file mode 100644
index 000000000..2319de556
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -0,0 +1,15 @@
+// normalize-stderr-test: "`.*`" -> "`DEF_ID`"
+// normalize-stdout-test: "`.*`" -> "`DEF_ID`"
+// edition:2018
+
+pub async fn f() -> impl std::fmt::Debug {
+ #[derive(Debug)]
+ enum E {
+ //~^ ERROR recursive type `f::{closure#0}::E` has infinite size
+ This(E),
+ Unit,
+ }
+ E::Unit
+}
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
new file mode 100644
index 000000000..aa39d26fe
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `DEF_ID` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
+ |
+LL | enum E {
+ | ^^^^^^ recursive type has infinite size
+LL |
+LL | This(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `DEF_ID` representable
+ |
+LL | This(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `DEF_ID`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
new file mode 100644
index 000000000..b3a7ee563
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -0,0 +1,7 @@
+fn f() -> impl Sized {
+ enum E {
+ //~^ ERROR recursive type `f::E` has infinite size
+ V(E),
+ }
+ unimplemented!()
+}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
new file mode 100644
index 000000000..009bedec5
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `f::E` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+ |
+LL | enum E {
+ | ^^^^^^ recursive type has infinite size
+LL |
+LL | V(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `f::E` representable
+ |
+LL | V(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type.rs b/src/test/rustdoc-ui/infinite-recursive-type.rs
new file mode 100644
index 000000000..32793fc4f
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type.rs
@@ -0,0 +1,4 @@
+enum E {
+//~^ ERROR recursive type `E` has infinite size
+ V(E),
+}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type.stderr b/src/test/rustdoc-ui/infinite-recursive-type.stderr
new file mode 100644
index 000000000..b33aba446
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `E` has infinite size
+ --> $DIR/infinite-recursive-type.rs:1:1
+ |
+LL | enum E {
+ | ^^^^^^ recursive type has infinite size
+LL |
+LL | V(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E` representable
+ |
+LL | V(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
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
+
diff --git a/src/test/rustdoc-ui/invalid-cfg.rs b/src/test/rustdoc-ui/invalid-cfg.rs
new file mode 100644
index 000000000..d237b8605
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-cfg.rs
@@ -0,0 +1,4 @@
+#![feature(doc_cfg)]
+#[doc(cfg = "x")] //~ ERROR not followed by parentheses
+#[doc(cfg(x, y))] //~ ERROR multiple `cfg` predicates
+struct S {}
diff --git a/src/test/rustdoc-ui/invalid-cfg.stderr b/src/test/rustdoc-ui/invalid-cfg.stderr
new file mode 100644
index 000000000..dae238b05
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-cfg.stderr
@@ -0,0 +1,14 @@
+error: `cfg` is not followed by parentheses
+ --> $DIR/invalid-cfg.rs:2:7
+ |
+LL | #[doc(cfg = "x")]
+ | ^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: multiple `cfg` predicates are specified
+ --> $DIR/invalid-cfg.rs:3:14
+ |
+LL | #[doc(cfg(x, y))]
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/rustdoc-ui/invalid-doc-attr.rs b/src/test/rustdoc-ui/invalid-doc-attr.rs
new file mode 100644
index 000000000..de004b41e
--- /dev/null
+++ b/src/test/rustdoc-ui/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(test(no_crate_inject))]
+#[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/src/test/rustdoc-ui/invalid-doc-attr.stderr b/src/test/rustdoc-ui/invalid-doc-attr.stderr
new file mode 100644
index 000000000..a4fa38179
--- /dev/null
+++ b/src/test/rustdoc-ui/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))]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+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)]`
+ = 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
+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/src/test/rustdoc-ui/invalid-html-tags.rs b/src/test/rustdoc-ui/invalid-html-tags.rs
new file mode 100644
index 000000000..0f9d2e4b3
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-html-tags.rs
@@ -0,0 +1,116 @@
+#![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() {}
diff --git a/src/test/rustdoc-ui/invalid-html-tags.stderr b/src/test/rustdoc-ui/invalid-html-tags.stderr
new file mode 100644
index 000000000..24a455576
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-html-tags.stderr
@@ -0,0 +1,98 @@
+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: aborting due to 15 previous errors
+
diff --git a/src/test/rustdoc-ui/invalid-keyword.rs b/src/test/rustdoc-ui/invalid-keyword.rs
new file mode 100644
index 000000000..2d70471c8
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-keyword.rs
@@ -0,0 +1,4 @@
+#![feature(rustdoc_internals)]
+
+#[doc(keyword = "foo df")] //~ ERROR
+mod foo {}
diff --git a/src/test/rustdoc-ui/invalid-keyword.stderr b/src/test/rustdoc-ui/invalid-keyword.stderr
new file mode 100644
index 000000000..8658e3825
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-keyword.stderr
@@ -0,0 +1,8 @@
+error: `foo df` is not a valid identifier
+ --> $DIR/invalid-keyword.rs:3:17
+ |
+LL | #[doc(keyword = "foo df")]
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
new file mode 100644
index 000000000..b503d1093
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -0,0 +1,101 @@
+// check-pass
+
+/// ```
+/// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/
+/// ```
+pub fn foo() {}
+//~^^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// |
+/// LL | use foobar::Baz;
+/// | ^^^^^^ did you mean `baz::foobar`?
+/// ```
+pub fn bar() {}
+//~^^^^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// valid
+/// ```
+///
+/// ```
+/// \_
+/// ```
+///
+/// ```text
+/// "invalid
+/// ```
+pub fn valid_and_invalid() {}
+//~^^^^^^^^ WARNING could not parse code block as Rust code
+
+/// This is a normal doc comment, but...
+///
+/// There's a code block with bad syntax in it:
+///
+/// ```rust
+/// \_
+/// ```
+///
+/// Good thing we tested it!
+pub fn baz() {}
+//~^^^^^^ WARNING could not parse code block as Rust code
+
+/// Indented block start
+///
+/// code with bad syntax
+/// \_
+///
+/// Indented block end
+pub fn quux() {}
+//~^^^^^ could not parse code block as Rust code
+
+/// Unclosed fence
+///
+/// ```
+/// slkdjf
+pub fn xyzzy() {}
+
+/// Indented code that contains a fence
+///
+/// ```
+pub fn blah() {}
+//~^^ WARNING could not parse code block as Rust code
+
+/// ```edition2018
+/// \_
+/// ```
+pub fn blargh() {}
+//~^^^^ WARNING could not parse code block as Rust code
+
+#[doc = "```"]
+/// \_
+#[doc = "```"]
+pub fn crazy_attrs() {}
+//~^^^^ WARNING could not parse code block
+
+/// ```rust
+/// ```
+pub fn empty_rust() {}
+//~^^^ WARNING Rust code block is empty
+
+/// ```
+///
+///
+/// ```
+pub fn empty_rust_with_whitespace() {}
+//~^^^^^ WARNING Rust code block is empty
+
+/// ```
+/// let x = 1;
+/// ```
+///
+/// \____/
+///
+pub fn indent_after_fenced() {}
+//~^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// "invalid
+/// ```
+pub fn invalid() {}
+//~^^^^ WARNING could not parse code block as Rust code
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
new file mode 100644
index 000000000..4c6249cc6
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -0,0 +1,154 @@
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:3:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/
+LL | | /// ```
+ | |_______^
+ |
+ = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
+ = note: error from rustc: unknown start of token: \
+ = note: error from rustc: unknown start of token: \
+ = note: error from rustc: unknown start of token: \
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:9:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// |
+LL | | /// LL | use foobar::Baz;
+LL | | /// | ^^^^^^ did you mean `baz::foobar`?
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: `
+ = note: error from rustc: unknown start of token: `
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:21:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// \_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: \
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:35:5
+ |
+LL | /// ```rust
+ | _____^
+LL | | /// \_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: \
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:45:9
+ |
+LL | /// code with bad syntax
+ | _________^
+LL | | /// \_
+ | |__________^
+ |
+ = note: error from rustc: unknown start of token: \
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:60:9
+ |
+LL | /// ```
+ | ^^^
+ |
+ = note: error from rustc: unknown start of token: `
+ = note: error from rustc: unknown start of token: `
+ = note: error from rustc: unknown start of token: `
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:64:5
+ |
+LL | /// ```edition2018
+ | _____^
+LL | | /// \_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: \
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:70:1
+ |
+LL | / #[doc = "```"]
+LL | | /// \_
+LL | | #[doc = "```"]
+ | |______________^
+ |
+ = help: mark blocks that do not contain Rust code as text: ```text
+ = note: error from rustc: unknown start of token: \
+
+warning: Rust code block is empty
+ --> $DIR/invalid-syntax.rs:76:5
+ |
+LL | /// ```rust
+ | _____^
+LL | | /// ```
+ | |_______^
+
+warning: Rust code block is empty
+ --> $DIR/invalid-syntax.rs:81:5
+ |
+LL | /// ```
+ | _____^
+LL | | ///
+LL | | ///
+LL | | /// ```
+ | |_______^
+ |
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:92:9
+ |
+LL | /// \____/
+ | _________^
+LL | | ///
+ | |_
+ |
+ = note: error from rustc: unknown start of token: \
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:97:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// "invalid
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unterminated double quote string
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: 12 warnings emitted
+
diff --git a/src/test/rustdoc-ui/invalid-theme-name.rs b/src/test/rustdoc-ui/invalid-theme-name.rs
new file mode 100644
index 000000000..c22ebf027
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-theme-name.rs
@@ -0,0 +1,3 @@
+// compile-flags:--theme {{src-base}}/invalid-theme-name.rs
+// error-pattern: invalid argument
+// error-pattern: must have a .css extension
diff --git a/src/test/rustdoc-ui/invalid-theme-name.stderr b/src/test/rustdoc-ui/invalid-theme-name.stderr
new file mode 100644
index 000000000..80204442d
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-theme-name.stderr
@@ -0,0 +1,4 @@
+error: invalid argument: "$DIR/invalid-theme-name.rs"
+ |
+ = help: arguments to --theme must have a .css extension
+
diff --git a/src/test/rustdoc-ui/issue-58473-2.rs b/src/test/rustdoc-ui/issue-58473-2.rs
new file mode 100644
index 000000000..000b6a329
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-58473-2.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+ /**
+ Does nothing, returns `()`
+
+ yadda-yadda-yadda
+ */
+ fn foo() {}
+}
diff --git a/src/test/rustdoc-ui/issue-58473.rs b/src/test/rustdoc-ui/issue-58473.rs
new file mode 100644
index 000000000..44e1f58d0
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-58473.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+pub trait Foo {
+ /**
+ Does nothing, returns `()`
+
+ yadda-yadda-yadda
+ */
+ fn foo() {}
+}
diff --git a/src/test/rustdoc-ui/issue-61592-2.rs b/src/test/rustdoc-ui/issue-61592-2.rs
new file mode 100644
index 000000000..5b4fc5ee7
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc = "bar"]
+#[doc(inline)] //~ ERROR
+#[doc = "baz"]
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592-2.stderr b/src/test/rustdoc-ui/issue-61592-2.stderr
new file mode 100644
index 000000000..1b7f8bb55
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592-2.stderr
@@ -0,0 +1,12 @@
+error[E0780]: anonymous imports cannot be inlined
+ --> $DIR/issue-61592-2.rs:6:7
+ |
+LL | #[doc(inline)]
+ | ^^^^^^
+LL | #[doc = "baz"]
+LL | pub use foo::Foo as _;
+ | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc-ui/issue-61592.rs b/src/test/rustdoc-ui/issue-61592.rs
new file mode 100644
index 000000000..66772557f
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+#[doc(inline)] //~ ERROR
+pub use foo::Foo as _;
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-61592.stderr b/src/test/rustdoc-ui/issue-61592.stderr
new file mode 100644
index 000000000..9c9c9106f
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61592.stderr
@@ -0,0 +1,11 @@
+error[E0780]: anonymous imports cannot be inlined
+ --> $DIR/issue-61592.rs:5:7
+ |
+LL | #[doc(inline)]
+ | ^^^^^^
+LL | pub use foo::Foo as _;
+ | ---------------------- anonymous import
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0780`.
diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs
new file mode 100644
index 000000000..4bd8efeaa
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.rs
@@ -0,0 +1,4 @@
+// This previously triggered an ICE.
+
+pub(in crate::r#mod) fn main() {}
+//~^ ERROR failed to resolve: maybe a missing crate `r#mod`
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
new file mode 100644
index 000000000..38fadaa44
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -0,0 +1,13 @@
+error[E0433]: failed to resolve: maybe a missing crate `r#mod`?
+ --> $DIR/issue-61732.rs:3:15
+ |
+LL | pub(in crate::r#mod) fn main() {}
+ | ^^^^^ maybe a missing crate `r#mod`?
+ |
+ = help: consider adding `extern crate r#mod` to use the `r#mod` 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/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr
new file mode 100644
index 000000000..31d2dbe96
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-74134.private.stderr
@@ -0,0 +1,11 @@
+warning: public documentation for `public_item` links to private item `PrivateType`
+ --> $DIR/issue-74134.rs:19:11
+ |
+LL | /// [`PrivateType`]
+ | ^^^^^^^^^^^ 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: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr
new file mode 100644
index 000000000..6a3173e3e
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-74134.public.stderr
@@ -0,0 +1,11 @@
+warning: public documentation for `public_item` links to private item `PrivateType`
+ --> $DIR/issue-74134.rs:19:11
+ |
+LL | /// [`PrivateType`]
+ | ^^^^^^^^^^^ 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/issue-74134.rs b/src/test/rustdoc-ui/issue-74134.rs
new file mode 100644
index 000000000..b1be9123a
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-74134.rs
@@ -0,0 +1,41 @@
+// revisions: public private
+// [private]compile-flags: --document-private-items
+// check-pass
+
+// There are 4 cases here:
+// 1. public item -> public type: no warning
+// 2. public item -> private type: warning
+// 3. private item -> public type: no warning
+// 4. private item -> private type: no warning
+// All 4 cases are tested with and without --document-private-items.
+//
+// Case 4 without --document-private-items is the one described in issue #74134.
+
+struct PrivateType;
+pub struct PublicType;
+
+pub struct Public {
+ /// [`PublicType`]
+ /// [`PrivateType`]
+ //~^ WARNING public documentation for `public_item` links to private item `PrivateType`
+ pub public_item: u32,
+
+ /// [`PublicType`]
+ /// [`PrivateType`]
+ private_item: u32,
+}
+
+// The following cases are identical to the ones above, except that they are in a private
+// module. Thus they all fall into cases 3 and 4 and should not produce a warning.
+
+mod private {
+ pub struct Public {
+ /// [`super::PublicType`]
+ /// [`super::PrivateType`]
+ pub public_item: u32,
+
+ /// [`super::PublicType`]
+ /// [`super::PrivateType`]
+ private_item: u32,
+ }
+}
diff --git a/src/test/rustdoc-ui/issue-79465.rs b/src/test/rustdoc-ui/issue-79465.rs
new file mode 100644
index 000000000..f1a77982f
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79465.rs
@@ -0,0 +1,3 @@
+pub fn f1<T>(x: T::A) {}
+//~^ ERROR
+//~^^ ERROR
diff --git a/src/test/rustdoc-ui/issue-79465.stderr b/src/test/rustdoc-ui/issue-79465.stderr
new file mode 100644
index 000000000..489cc1442
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79465.stderr
@@ -0,0 +1,15 @@
+error[E0220]: associated type `A` not found for `T`
+ --> $DIR/issue-79465.rs:1:20
+ |
+LL | pub fn f1<T>(x: T::A) {}
+ | ^ associated type `A` not found
+
+error[E0220]: associated type `A` not found for `T`
+ --> $DIR/issue-79465.rs:1:20
+ |
+LL | pub fn f1<T>(x: T::A) {}
+ | ^ associated type `A` not found
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/rustdoc-ui/issue-79467.rs b/src/test/rustdoc-ui/issue-79467.rs
new file mode 100644
index 000000000..eb0b9b380
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79467.rs
@@ -0,0 +1,8 @@
+fn g()
+where
+ 'static: 'static,
+ dyn 'static: 'static + Copy, //~ ERROR at least one trait is required for an object type
+{
+}
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/issue-79467.stderr b/src/test/rustdoc-ui/issue-79467.stderr
new file mode 100644
index 000000000..561513a43
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79467.stderr
@@ -0,0 +1,9 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/issue-79467.rs:4:5
+ |
+LL | dyn 'static: 'static + Copy,
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/rustdoc-ui/issue-79494.rs b/src/test/rustdoc-ui/issue-79494.rs
new file mode 100644
index 000000000..fc39424b7
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79494.rs
@@ -0,0 +1,5 @@
+// only-x86_64-unknown-linux-gnu
+
+#![feature(const_transmute)]
+
+const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; //~ ERROR cannot transmute between types of different sizes, or dependently-sized types
diff --git a/src/test/rustdoc-ui/issue-79494.stderr b/src/test/rustdoc-ui/issue-79494.stderr
new file mode 100644
index 000000000..7ed5ed382
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-79494.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> $DIR/issue-79494.rs:5:29
+ |
+LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `usize` (64 bits)
+ = note: target type: `&[u8]` (128 bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/rustdoc-ui/issue-80992.rs b/src/test/rustdoc-ui/issue-80992.rs
new file mode 100644
index 000000000..8983439bb
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+pub fn test() -> Result<(), ()> {
+ //! ```compile_fail
+ //! fn test() -> Result< {}
+ //! ```
+ Ok(())
+}
diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout
new file mode 100644
index 000000000..d2b1cd1d5
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/issue-80992.rs - test (line 7) - compile fail ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/issue-81662-shortness.rs b/src/test/rustdoc-ui/issue-81662-shortness.rs
new file mode 100644
index 000000000..27a21a313
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-81662-shortness.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test --error-format=short
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```rust
+/// foo();
+/// ```
+//~^^ ERROR cannot find function `foo` in this scope
+fn foo() {
+ println!("Hello, world!");
+}
diff --git a/src/test/rustdoc-ui/issue-81662-shortness.stdout b/src/test/rustdoc-ui/issue-81662-shortness.stdout
new file mode 100644
index 000000000..748113be3
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-81662-shortness.stdout
@@ -0,0 +1,16 @@
+
+running 1 test
+test $DIR/issue-81662-shortness.rs - foo (line 6) ... FAILED
+
+failures:
+
+---- $DIR/issue-81662-shortness.rs - foo (line 6) stdout ----
+$DIR/issue-81662-shortness.rs:7:1: error[E0425]: cannot find function `foo` in this scope
+error: aborting due to previous error
+Couldn't compile the test.
+
+failures:
+ $DIR/issue-81662-shortness.rs - foo (line 6)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.rs b/src/test/rustdoc-ui/issue-83883-describe-lints.rs
new file mode 100644
index 000000000..0474d6c14
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-83883-describe-lints.rs
@@ -0,0 +1,10 @@
+// compile-flags: -W help
+// check-pass
+// check-stdout
+// error-pattern:Lint checks provided
+// error-pattern:rustdoc::broken-intra-doc-links
+//
+// ignore-tidy-linelength
+//
+// normalize-stdout-test: "( +name default meaning\n +---- ------- -------\n)?( *[[:word:]:-]+ (allow |warn |deny |forbid ) [^\n]+\n)+" -> " $$NAMES $$LEVELS $$MEANINGS"
+// normalize-stdout-test: " +name sub-lints\n +---- ---------\n( *[[:word:]:-]+ [^\n]+\n)+" -> " $$NAMES $$SUB_LINTS"
diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout
new file mode 100644
index 000000000..bbf66a315
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout
@@ -0,0 +1,24 @@
+
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> (deny <foo> and all attempts to override)
+
+
+Lint checks provided by rustc:
+
+ $NAMES $LEVELS $MEANINGS
+
+Lint groups provided by rustc:
+
+ $NAMES $SUB_LINTS
+
+Lint checks provided by plugins loaded by this crate:
+
+ $NAMES $LEVELS $MEANINGS
+
+Lint groups provided by plugins loaded by this crate:
+
+ $NAMES $SUB_LINTS
+
diff --git a/src/test/rustdoc-ui/issue-91134.rs b/src/test/rustdoc-ui/issue-91134.rs
new file mode 100644
index 000000000..d2ff3a252
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-91134.rs
@@ -0,0 +1,14 @@
+// compile-flags: --test --crate-name=empty_fn --extern=empty_fn --test-args=--test-threads=1
+// aux-build:empty-fn.rs
+// check-pass
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// edition:2021
+
+/// <https://github.com/rust-lang/rust/issues/91134>
+///
+/// ```
+/// extern crate empty_fn;
+/// empty_fn::empty();
+/// ```
+pub struct Something;
diff --git a/src/test/rustdoc-ui/issue-91134.stdout b/src/test/rustdoc-ui/issue-91134.stdout
new file mode 100644
index 000000000..084062743
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-91134.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/issue-91134.rs - Something (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/issue-91713.rs b/src/test/rustdoc-ui/issue-91713.rs
new file mode 100644
index 000000000..610bbf11d
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-91713.rs
@@ -0,0 +1,3 @@
+// check-pass
+// compile-flags: --passes list
+// error-pattern: the `passes` flag no longer functions
diff --git a/src/test/rustdoc-ui/issue-91713.stderr b/src/test/rustdoc-ui/issue-91713.stderr
new file mode 100644
index 000000000..44ead7a1d
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-91713.stderr
@@ -0,0 +1,5 @@
+warning: the `passes` flag no longer functions
+ |
+ = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+ = help: you may want to use --document-private-items
+
diff --git a/src/test/rustdoc-ui/issue-91713.stdout b/src/test/rustdoc-ui/issue-91713.stdout
new file mode 100644
index 000000000..a19e452b4
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-91713.stdout
@@ -0,0 +1,29 @@
+Available passes for running rustdoc:
+check_doc_test_visibility - run various visibility-related lints on doctests
+ strip-hidden - strips all `#[doc(hidden)]` items from the output
+ strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
+ strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate
+ propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items
+collect-intra-doc-links - resolves intra-doc links
+check-code-block-syntax - validates syntax inside Rust code blocks
+ collect-trait-impls - retrieves trait impls for items in the crate
+calculate-doc-coverage - counts the number of items with and without documentation
+check-invalid-html-tags - detects invalid HTML tags in doc comments
+ check-bare-urls - detects URLs that are not hyperlinks
+
+Default passes for rustdoc:
+ collect-trait-impls
+check_doc_test_visibility
+ strip-hidden (when not --document-hidden-items)
+ strip-private (when not --document-private-items)
+ strip-priv-imports (when --document-private-items)
+collect-intra-doc-links
+check-code-block-syntax
+check-invalid-html-tags
+ propagate-doc-cfg
+ check-bare-urls
+
+Passes run with `--show-coverage`:
+ strip-hidden (when not --document-hidden-items)
+ strip-private (when not --document-private-items)
+calculate-doc-coverage
diff --git a/src/test/rustdoc-ui/issue-98690.rs b/src/test/rustdoc-ui/issue-98690.rs
new file mode 100644
index 000000000..fe9bd87ab
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-98690.rs
@@ -0,0 +1,10 @@
+// compile-flags: --test --persist-doctests /../../ -Z unstable-options
+// failure-status: 101
+// only-linux
+
+#![crate_name = "foo"]
+
+//! ```rust
+//! use foo::dummy;
+//! dummy();
+//! ```
diff --git a/src/test/rustdoc-ui/issue-98690.stderr b/src/test/rustdoc-ui/issue-98690.stderr
new file mode 100644
index 000000000..47d94f99a
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-98690.stderr
@@ -0,0 +1 @@
+Couldn't create directory for doctest executables: Permission denied (os error 13)
diff --git a/src/test/rustdoc-ui/lint-group.rs b/src/test/rustdoc-ui/lint-group.rs
new file mode 100644
index 000000000..61555a6e6
--- /dev/null
+++ b/src/test/rustdoc-ui/lint-group.rs
@@ -0,0 +1,29 @@
+//! Documenting the kinds of lints emitted by rustdoc.
+//!
+//! ```
+//! println!("sup");
+//! ```
+
+#![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/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr
new file mode 100644
index 000000000..e28600160
--- /dev/null
+++ b/src/test/rustdoc-ui/lint-group.stderr
@@ -0,0 +1,50 @@
+error: missing code example in this documentation
+ --> $DIR/lint-group.rs:16:1
+ |
+LL | /// wait, this doesn't have a doctest?
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/lint-group.rs:7:9
+ |
+LL | #![deny(rustdoc::all)]
+ | ^^^^^^^^^^^^
+ = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]`
+
+error: documentation test in private item
+ --> $DIR/lint-group.rs:19:1
+ |
+LL | / /// wait, this *does* have a doctest?
+LL | | ///
+LL | | /// ```
+LL | | /// println!("sup");
+LL | | /// ```
+ | |_______^
+ |
+ = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]`
+
+error: missing code example in this documentation
+ --> $DIR/lint-group.rs:26:1
+ |
+LL | /// <unknown>
+ | ^^^^^^^^^^^^^
+
+error: unresolved link to `error`
+ --> $DIR/lint-group.rs:9:29
+ |
+LL | /// what up, let's make an [error]
+ | ^^^^^ no item named `error` in scope
+ |
+ = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unclosed HTML tag `unknown`
+ --> $DIR/lint-group.rs:26:5
+ |
+LL | /// <unknown>
+ | ^^^^^^^^^
+ |
+ = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc::all)]`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
new file mode 100644
index 000000000..fac6342cd
--- /dev/null
+++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
@@ -0,0 +1,100 @@
+#![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/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
new file mode 100644
index 000000000..9e51ecd2b
--- /dev/null
+++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
@@ -0,0 +1,38 @@
+error: missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:19:1
+ |
+LL | pub mod module1 {
+ | ^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/lint-missing-doc-code-example.rs:2:9
+ |
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:37:3
+ |
+LL | /// doc
+ | ^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:49:1
+ |
+LL | /// Doc
+ | ^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:56:1
+ |
+LL | /// Doc
+ | ^^^^^^^
+
+error: missing code example in this documentation
+ --> $DIR/lint-missing-doc-code-example.rs:63:1
+ |
+LL | /// Doc
+ | ^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/rustdoc-ui/macro-docs.rs b/src/test/rustdoc-ui/macro-docs.rs
new file mode 100644
index 000000000..0e8472eb2
--- /dev/null
+++ b/src/test/rustdoc-ui/macro-docs.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+macro_rules! m {
+ () => {
+ /// A
+ //~^ WARNING
+ #[path = "auxiliary/module_macro_doc.rs"]
+ pub mod mymodule;
+ }
+}
+
+m!();
diff --git a/src/test/rustdoc-ui/macro-docs.stderr b/src/test/rustdoc-ui/macro-docs.stderr
new file mode 100644
index 000000000..e3cc17311
--- /dev/null
+++ b/src/test/rustdoc-ui/macro-docs.stderr
@@ -0,0 +1,20 @@
+warning: unresolved link to `long_cat`
+ --> $DIR/macro-docs.rs:5:9
+ |
+LL | /// A
+ | ^^^^^
+...
+LL | m!();
+ | ---- in this macro invocation
+ |
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+ = note: the link appears in this line:
+
+ [`long_cat`] is really long
+ ^^^^^^^^^^
+ = note: no item named `long_cat` in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+ = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/macro-docs.stdout b/src/test/rustdoc-ui/macro-docs.stdout
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/test/rustdoc-ui/macro-docs.stdout
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
new file mode 100644
index 000000000..a186410ac
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
new file mode 100644
index 000000000..1a1f8085a
--- /dev/null
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
@@ -0,0 +1,12 @@
+error: no documentation found for this crate's top-level module
+ |
+note: the lint level is defined here
+ --> $DIR/no-crate-level-doc-lint.rs:3:9
+ |
+LL | #![deny(rustdoc::missing_crate_level_docs)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: The following guide may be of use:
+ https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/no-run-flag-error.rs b/src/test/rustdoc-ui/no-run-flag-error.rs
new file mode 100644
index 000000000..4ead62148
--- /dev/null
+++ b/src/test/rustdoc-ui/no-run-flag-error.rs
@@ -0,0 +1,6 @@
+// test the behavior of the --no-run flag without the --test flag
+
+// compile-flags:-Z unstable-options --no-run --test-args=--test-threads=1
+// error-pattern: the `--test` flag must be passed
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/no-run-flag-error.stderr b/src/test/rustdoc-ui/no-run-flag-error.stderr
new file mode 100644
index 000000000..d032646c3
--- /dev/null
+++ b/src/test/rustdoc-ui/no-run-flag-error.stderr
@@ -0,0 +1,2 @@
+error: the `--test` flag must be passed to enable `--no-run`
+
diff --git a/src/test/rustdoc-ui/no-run-flag.rs b/src/test/rustdoc-ui/no-run-flag.rs
new file mode 100644
index 000000000..da1672c4a
--- /dev/null
+++ b/src/test/rustdoc-ui/no-run-flag.rs
@@ -0,0 +1,38 @@
+// test the behavior of the --no-run flag
+
+// check-pass
+// compile-flags:-Z unstable-options --test --no-run --test-args=--test-threads=1
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+/// println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+/// Ok the test does not run
+/// ```
+/// panic!()
+/// ```
+/// Ok the test does not run
+/// ```should_panic
+/// loop {
+/// println!("Hello, world");
+/// panic!()
+/// }
+/// ```
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/no-run-flag.stdout b/src/test/rustdoc-ui/no-run-flag.stdout
new file mode 100644
index 000000000..02f28aaf6
--- /dev/null
+++ b/src/test/rustdoc-ui/no-run-flag.stdout
@@ -0,0 +1,12 @@
+
+running 7 tests
+test $DIR/no-run-flag.rs - f (line 11) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 14) ... ignored
+test $DIR/no-run-flag.rs - f (line 17) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 23) - compile fail ... ok
+test $DIR/no-run-flag.rs - f (line 28) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 32) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 8) - compile ... ok
+
+test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/nocapture-fail.rs b/src/test/rustdoc-ui/nocapture-fail.rs
new file mode 100644
index 000000000..7706bd1f3
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```compile_fail
+/// fn foo() {
+/// Input: 123
+/// }
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture-fail.stderr b/src/test/rustdoc-ui/nocapture-fail.stderr
new file mode 100644
index 000000000..b65b622c1
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stderr
@@ -0,0 +1,18 @@
+error: struct literal body without path
+ --> $DIR/nocapture-fail.rs:8:10
+ |
+LL | fn foo() {
+ | __________^
+LL | | Input: 123
+LL | | }
+ | |_^
+ |
+help: you might have forgotten to add the struct literal inside the block
+ |
+LL ~ fn foo() { SomeStruct {
+LL | Input: 123
+LL ~ } }
+ |
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/nocapture-fail.stdout b/src/test/rustdoc-ui/nocapture-fail.stdout
new file mode 100644
index 000000000..754f77db5
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/nocapture.rs b/src/test/rustdoc-ui/nocapture.rs
new file mode 100644
index 000000000..321f5ca08
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.rs
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// println!("hello!");
+/// eprintln!("stderr");
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture.stderr b/src/test/rustdoc-ui/nocapture.stderr
new file mode 100644
index 000000000..af6415db3
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.stderr
@@ -0,0 +1 @@
+stderr
diff --git a/src/test/rustdoc-ui/nocapture.stdout b/src/test/rustdoc-ui/nocapture.stdout
new file mode 100644
index 000000000..4880e75da
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.stdout
@@ -0,0 +1,7 @@
+
+running 1 test
+hello!
+test $DIR/nocapture.rs - Foo (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/normalize-cycle.rs b/src/test/rustdoc-ui/normalize-cycle.rs
new file mode 100644
index 000000000..f48cad373
--- /dev/null
+++ b/src/test/rustdoc-ui/normalize-cycle.rs
@@ -0,0 +1,25 @@
+// check-pass
+// Regresion test for <https://github.com/rust-lang/rust/issues/79459>.
+pub trait Query {}
+
+pub trait AsQuery {
+ type Query;
+}
+
+impl<T: Query> AsQuery for T {
+ type Query = T;
+}
+
+pub trait SelectDsl<Selection> {
+ type Output;
+}
+
+impl<T, Selection> SelectDsl<Selection> for T
+where
+ T: AsQuery,
+ T::Query: SelectDsl<Selection>,
+{
+ type Output = <T::Query as SelectDsl<Selection>>::Output;
+}
+
+pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;
diff --git a/src/test/rustdoc-ui/normalize-overflow.rs b/src/test/rustdoc-ui/normalize-overflow.rs
new file mode 100644
index 000000000..0cdcc88e3
--- /dev/null
+++ b/src/test/rustdoc-ui/normalize-overflow.rs
@@ -0,0 +1,3 @@
+// aux-crate:overflow=overflow.rs
+// check-pass
+// Regression test for <https://github.com/rust-lang/rust/issues/79506>.
diff --git a/src/test/rustdoc-ui/output-format-html-stable.rs b/src/test/rustdoc-ui/output-format-html-stable.rs
new file mode 100644
index 000000000..fa0362640
--- /dev/null
+++ b/src/test/rustdoc-ui/output-format-html-stable.rs
@@ -0,0 +1,4 @@
+// compile-flags: --output-format html
+// check-pass
+// This tests that `--output-format html` is accepted without `-Z unstable-options`,
+// since it has been stable since 1.0.
diff --git a/src/test/rustdoc-ui/private-doc-test.rs b/src/test/rustdoc-ui/private-doc-test.rs
new file mode 100644
index 000000000..a1f9f8dca
--- /dev/null
+++ b/src/test/rustdoc-ui/private-doc-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+ /// private doc test
+ ///
+ /// ```ignore (used for testing ignored doc tests)
+ /// assert!(false);
+ /// ```
+ fn bar() {}
+}
diff --git a/src/test/rustdoc-ui/private-item-doc-test.rs b/src/test/rustdoc-ui/private-item-doc-test.rs
new file mode 100644
index 000000000..1a3d6cc63
--- /dev/null
+++ b/src/test/rustdoc-ui/private-item-doc-test.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+ /// private doc test
+ ///
+ /// ```
+ /// assert!(false);
+ /// ```
+ //~^^^^^ ERROR documentation test in private item
+ fn bar() {}
+}
diff --git a/src/test/rustdoc-ui/private-item-doc-test.stderr b/src/test/rustdoc-ui/private-item-doc-test.stderr
new file mode 100644
index 000000000..5df613298
--- /dev/null
+++ b/src/test/rustdoc-ui/private-item-doc-test.stderr
@@ -0,0 +1,18 @@
+error: documentation test in private item
+ --> $DIR/private-item-doc-test.rs:4:5
+ |
+LL | / /// private doc test
+LL | | ///
+LL | | /// ```
+LL | | /// assert!(false);
+LL | | /// ```
+ | |___________^
+ |
+note: the lint level is defined here
+ --> $DIR/private-item-doc-test.rs:1:9
+ |
+LL | #![deny(rustdoc::private_doc_tests)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/private-public-item-doc-test.rs b/src/test/rustdoc-ui/private-public-item-doc-test.rs
new file mode 100644
index 000000000..7cc62b38c
--- /dev/null
+++ b/src/test/rustdoc-ui/private-public-item-doc-test.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+ /// private doc test
+ ///
+ /// ```
+ /// assert!(false);
+ /// ```
+ //~^^^^^ ERROR documentation test in private item
+ pub fn bar() {}
+}
diff --git a/src/test/rustdoc-ui/private-public-item-doc-test.stderr b/src/test/rustdoc-ui/private-public-item-doc-test.stderr
new file mode 100644
index 000000000..f50dbd184
--- /dev/null
+++ b/src/test/rustdoc-ui/private-public-item-doc-test.stderr
@@ -0,0 +1,18 @@
+error: documentation test in private item
+ --> $DIR/private-public-item-doc-test.rs:4:5
+ |
+LL | / /// private doc test
+LL | | ///
+LL | | /// ```
+LL | | /// assert!(false);
+LL | | /// ```
+ | |___________^
+ |
+note: the lint level is defined here
+ --> $DIR/private-public-item-doc-test.rs:1:9
+ |
+LL | #![deny(rustdoc::private_doc_tests)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/pub-export-lint.rs b/src/test/rustdoc-ui/pub-export-lint.rs
new file mode 100644
index 000000000..f2e66b77b
--- /dev/null
+++ b/src/test/rustdoc-ui/pub-export-lint.rs
@@ -0,0 +1,5 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [aloha]
+//~^ ERROR unresolved link to `aloha`
+pub use std::task::RawWakerVTable;
diff --git a/src/test/rustdoc-ui/pub-export-lint.stderr b/src/test/rustdoc-ui/pub-export-lint.stderr
new file mode 100644
index 000000000..c6be9c6a9
--- /dev/null
+++ b/src/test/rustdoc-ui/pub-export-lint.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `aloha`
+ --> $DIR/pub-export-lint.rs:3:6
+ |
+LL | /// [aloha]
+ | ^^^^^ no item named `aloha` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/pub-export-lint.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/public-reexported-item-doc-test.rs b/src/test/rustdoc-ui/public-reexported-item-doc-test.rs
new file mode 100644
index 000000000..b86a53305
--- /dev/null
+++ b/src/test/rustdoc-ui/public-reexported-item-doc-test.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+pub fn foo() {}
+
+mod private {
+ /// re-exported doc test
+ ///
+ /// ```
+ /// assert!(true);
+ /// ```
+ pub fn bar() {}
+}
+
+pub use private::bar;
diff --git a/src/test/rustdoc-ui/range-pattern.rs b/src/test/rustdoc-ui/range-pattern.rs
new file mode 100644
index 000000000..fd255d02f
--- /dev/null
+++ b/src/test/rustdoc-ui/range-pattern.rs
@@ -0,0 +1,3 @@
+// check-pass
+
+fn func(0u8..=255: u8) {}
diff --git a/src/test/rustdoc-ui/recursive-deref-ice.rs b/src/test/rustdoc-ui/recursive-deref-ice.rs
new file mode 100644
index 000000000..c44fd27f4
--- /dev/null
+++ b/src/test/rustdoc-ui/recursive-deref-ice.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// ICE found in https://github.com/rust-lang/rust/issues/83123
+
+pub struct Attribute;
+
+pub struct Map<'hir> {}
+impl<'hir> Map<'hir> {
+ pub fn attrs(&self) -> &'hir [Attribute] { &[] }
+}
+
+pub struct List<T>(T);
+
+impl<T> std::ops::Deref for List<T> {
+ type Target = [T];
+ fn deref(&self) -> &[T] {
+ &[]
+ }
+}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.rs b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
new file mode 100644
index 000000000..71bd2c522
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
@@ -0,0 +1,20 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// Links to [a] [link][a]
+/// And also a [third link][a]
+/// And also a [reference link][b]
+///
+/// Other links to the same target should still emit error: [ref] //~ERROR unresolved link to `ref`
+/// Duplicate [ref] //~ERROR unresolved link to `ref`
+///
+/// Other links to other targets should still emit error: [ref2] //~ERROR unresolved link to `ref2`
+/// Duplicate [ref2] //~ERROR unresolved link to `ref2`
+///
+/// [a]: ref
+//~^ ERROR unresolved link to `ref`
+/// [b]: ref2
+//~^ ERROR unresolved link to
+
+/// [ref][]
+//~^ ERROR unresolved link
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.stderr b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
new file mode 100644
index 000000000..b46a51e93
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
@@ -0,0 +1,63 @@
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:13:10
+ |
+LL | /// [a]: ref
+ | ^^^ no item named `ref` in scope
+ |
+note: the lint level is defined here
+ --> $DIR/reference-link-reports-error-once.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:15:10
+ |
+LL | /// [b]: ref2
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:7:62
+ |
+LL | /// Other links to the same target should still emit error: [ref]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:8:16
+ |
+LL | /// Duplicate [ref]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:10:60
+ |
+LL | /// Other links to other targets should still emit error: [ref2]
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+ --> $DIR/reference-link-reports-error-once.rs:11:16
+ |
+LL | /// Duplicate [ref2]
+ | ^^^^ no item named `ref2` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+ --> $DIR/reference-link-reports-error-once.rs:18:6
+ |
+LL | /// [ref][]
+ | ^^^ no item named `ref` in scope
+ |
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/rustdoc-ui/reference-links.rs b/src/test/rustdoc-ui/reference-links.rs
new file mode 100644
index 000000000..e81e03446
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-links.rs
@@ -0,0 +1,6 @@
+// Test that errors point to the reference, not to the title text.
+#![deny(rustdoc::broken_intra_doc_links)]
+//! Links to [a] [link][a]
+//!
+//! [a]: std::process::Comman
+//~^ ERROR unresolved
diff --git a/src/test/rustdoc-ui/reference-links.stderr b/src/test/rustdoc-ui/reference-links.stderr
new file mode 100644
index 000000000..c98a2fd7c
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-links.stderr
@@ -0,0 +1,14 @@
+error: unresolved link to `std::process::Comman`
+ --> $DIR/reference-links.rs:5:10
+ |
+LL | //! [a]: std::process::Comman
+ | ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process`
+ |
+note: the lint level is defined here
+ --> $DIR/reference-links.rs:2:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.rs b/src/test/rustdoc-ui/renamed-lint-still-applies.rs
new file mode 100644
index 000000000..a4d3a4b49
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/renamed-lint-still-applies.stderr b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr
new file mode 100644
index 000000000..8e2a2cdd7
--- /dev/null
+++ b/src/test/rustdoc-ui/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
+ |
+note: the lint level is defined here
+ --> $DIR/renamed-lint-still-applies.rs:2:9
+ |
+LL | #![deny(broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+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: the lint level is defined here
+ --> $DIR/renamed-lint-still-applies.rs:7:9
+ |
+LL | #![deny(rustdoc::non_autolinks)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: bare URLs are not automatically turned into clickable links
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
diff --git a/src/test/rustdoc-ui/run-directory.correct.stdout b/src/test/rustdoc-ui/run-directory.correct.stdout
new file mode 100644
index 000000000..e9b275479
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.correct.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/run-directory.incorrect.stdout b/src/test/rustdoc-ui/run-directory.incorrect.stdout
new file mode 100644
index 000000000..97a5dbc5c
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.incorrect.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 19) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/run-directory.rs b/src/test/rustdoc-ui/run-directory.rs
new file mode 100644
index 000000000..0d432c1e6
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.rs
@@ -0,0 +1,23 @@
+// this test asserts that the cwd of doctest invocations is set correctly.
+
+// revisions: correct incorrect
+// check-pass
+// [correct]compile-flags:--test --test-run-directory={{src-base}} -Zunstable-options
+// [incorrect]compile-flags:--test --test-run-directory={{src-base}}/coverage -Zunstable-options
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// assert_eq!(
+/// std::fs::read_to_string("run-directory.rs").unwrap(),
+/// include_str!("run-directory.rs"),
+/// );
+/// ```
+#[cfg(correct)]
+pub fn foo() {}
+
+/// ```
+/// assert!(std::fs::read_to_string("run-directory.rs").is_err());
+/// ```
+#[cfg(incorrect)]
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/rustc-check-passes.rs b/src/test/rustdoc-ui/rustc-check-passes.rs
new file mode 100644
index 000000000..731cc8ba6
--- /dev/null
+++ b/src/test/rustdoc-ui/rustc-check-passes.rs
@@ -0,0 +1,4 @@
+#![feature(box_syntax)]
+#![feature(box_syntax)] //~ ERROR
+
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/rustc-check-passes.stderr b/src/test/rustdoc-ui/rustc-check-passes.stderr
new file mode 100644
index 000000000..9707895ff
--- /dev/null
+++ b/src/test/rustdoc-ui/rustc-check-passes.stderr
@@ -0,0 +1,9 @@
+error[E0636]: the feature `box_syntax` has already been declared
+ --> $DIR/rustc-check-passes.rs:2:12
+ |
+LL | #![feature(box_syntax)]
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0636`.
diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs
new file mode 100644
index 000000000..8f4fde96d
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs
@@ -0,0 +1,7 @@
+// check-fail
+// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
+
+pub fn foo() {
+ INVALID_FUNC();
+ //~^ ERROR could not resolve path
+}
diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr
new file mode 100644
index 000000000..750aa3207
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: could not resolve path `INVALID_FUNC`
+ --> $DIR/scrape-examples-fail-if-type-error.rs:5:3
+ |
+LL | INVALID_FUNC();
+ | ^^^^^^^^^^^^ could not resolve path `INVALID_FUNC`
+ |
+ = note: this error was originally ignored because you are running `rustdoc`
+ = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+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/scrape-examples-ice.rs b/src/test/rustdoc-ui/scrape-examples-ice.rs
new file mode 100644
index 000000000..d629b62a7
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-ice.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
+// check-pass
+#![no_std]
+use core as _;
diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs
new file mode 100644
index 000000000..a1f005c32
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs
@@ -0,0 +1 @@
+// compile-flags: -Z unstable-options --scrape-examples-target-crate foobar
diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr
new file mode 100644
index 000000000..eb8e9f799
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr
@@ -0,0 +1,2 @@
+error: must use --scrape-examples-output-path and --scrape-examples-target-crate together
+
diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs
new file mode 100644
index 000000000..4aacec7f0
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs
@@ -0,0 +1 @@
+// compile-flags: -Z unstable-options --scrape-examples-output-path ex.calls
diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr
new file mode 100644
index 000000000..eb8e9f799
--- /dev/null
+++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr
@@ -0,0 +1,2 @@
+error: must use --scrape-examples-output-path and --scrape-examples-target-crate together
+
diff --git a/src/test/rustdoc-ui/search-index-generics-recursion-bug-issue-59502.rs b/src/test/rustdoc-ui/search-index-generics-recursion-bug-issue-59502.rs
new file mode 100644
index 000000000..ce51556dd
--- /dev/null
+++ b/src/test/rustdoc-ui/search-index-generics-recursion-bug-issue-59502.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+// Minimization of issue #59502
+
+trait MyTrait<T> {
+ type Output;
+}
+
+pub fn pow<T: MyTrait<T, Output = T>>(arg: T) -> T {
+ arg
+}
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs
new file mode 100644
index 000000000..744b3071f
--- /dev/null
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs
@@ -0,0 +1,38 @@
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This Vec<32> thing!
+// Numbers aren't valid HTML tags, so no error.
+pub struct ConstGeneric;
+
+/// This Vec<i32, i32> thing!
+// HTML tags cannot contain commas, so no error.
+pub struct MultipleGenerics;
+
+/// This Vec<i32 class="test"> thing!
+//~^ERROR unclosed HTML tag `i32`
+// HTML attributes shouldn't be treated as Rust syntax, so no suggestions.
+pub struct TagWithAttributes;
+
+/// This Vec<i32></i32> thing!
+// There should be no error, and no suggestion, since the tags are balanced.
+pub struct DoNotWarnOnMatchingTags;
+
+/// This Vec</i32> thing!
+//~^ERROR unopened HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct EndTagsAreNotValidRustSyntax;
+
+/// This 123<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct NumbersAreNotPaths;
+
+/// This Vec:<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct InvalidTurbofish;
+
+/// This [link](https://rust-lang.org)<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct BareTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr
new file mode 100644
index 000000000..832b8b2ca
--- /dev/null
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr
@@ -0,0 +1,38 @@
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-no-suggestions.rs:11:13
+ |
+LL | /// This Vec<i32 class="test"> thing!
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/html-as-generics-no-suggestions.rs:1:9
+ |
+LL | #![deny(rustdoc::invalid_html_tags)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unopened HTML tag `i32`
+ --> $DIR/html-as-generics-no-suggestions.rs:20:13
+ |
+LL | /// This Vec</i32> thing!
+ | ^^^^^^
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-no-suggestions.rs:25:13
+ |
+LL | /// This 123<i32> thing!
+ | ^^^^^
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-no-suggestions.rs:30:14
+ |
+LL | /// This Vec:<i32> thing!
+ | ^^^^^
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics-no-suggestions.rs:35:39
+ |
+LL | /// This [link](https://rust-lang.org)<i32> thing!
+ | ^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
new file mode 100644
index 000000000..c0a0de24c
--- /dev/null
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
@@ -0,0 +1,32 @@
+// run-rustfix
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This `Vec<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Generic;
+
+/// This `vec::Vec<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct GenericPath;
+
+/// This `i32<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct PathsCanContainTrailingNumbers;
+
+/// This `Vec::<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Turbofish;
+
+/// This [link](https://rust-lang.org)`::<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct BareTurbofish;
+
+/// This <span>`Vec::<i32>`</span> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Nested;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.rs b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
new file mode 100644
index 000000000..0b6009b0e
--- /dev/null
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
@@ -0,0 +1,32 @@
+// run-rustfix
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This Vec<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Generic;
+
+/// This vec::Vec<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct GenericPath;
+
+/// This i32<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct PathsCanContainTrailingNumbers;
+
+/// This Vec::<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Turbofish;
+
+/// This [link](https://rust-lang.org)::<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct BareTurbofish;
+
+/// This <span>Vec::<i32></span> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Nested;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
new file mode 100644
index 000000000..df54b7126
--- /dev/null
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
@@ -0,0 +1,73 @@
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:4:13
+ |
+LL | /// This Vec<i32> thing!
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/html-as-generics.rs:2:9
+ |
+LL | #![deny(rustdoc::invalid_html_tags)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try marking as source code
+ |
+LL | /// This `Vec<i32>` thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:9:18
+ |
+LL | /// This vec::Vec<i32> thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This `vec::Vec<i32>` thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:14:13
+ |
+LL | /// This i32<i32> thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This `i32<i32>` thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:19:15
+ |
+LL | /// This Vec::<i32> thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This `Vec::<i32>` thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:24:41
+ |
+LL | /// This [link](https://rust-lang.org)::<i32> thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This [link](https://rust-lang.org)`::<i32>` thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:29:21
+ |
+LL | /// This <span>Vec::<i32></span> thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This <span>`Vec::<i32>`</span> thing!
+ | + +
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/rustdoc-ui/test-compile-fail1.rs b/src/test/rustdoc-ui/test-compile-fail1.rs
new file mode 100644
index 000000000..a05390238
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail1.rs
@@ -0,0 +1,8 @@
+// compile-flags:--test
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-compile-fail1.stderr b/src/test/rustdoc-ui/test-compile-fail1.stderr
new file mode 100644
index 000000000..72915e46b
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail1.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `f` is defined multiple times
+ --> $DIR/test-compile-fail1.rs:8:1
+ |
+6 | pub fn f() {}
+ | ---------- previous definition of the value `f` here
+7 |
+8 | pub fn f() {}
+ | ^^^^^^^^^^ `f` redefined here
+ |
+ = note: `f` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/rustdoc-ui/test-compile-fail2.rs b/src/test/rustdoc-ui/test-compile-fail2.rs
new file mode 100644
index 000000000..651ded0a0
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail2.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+fail
diff --git a/src/test/rustdoc-ui/test-compile-fail2.stderr b/src/test/rustdoc-ui/test-compile-fail2.stderr
new file mode 100644
index 000000000..cee5b63cf
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `<eof>`
+ --> $DIR/test-compile-fail2.rs:3:1
+ |
+3 | fail
+ | ^^^^ expected one of `!` or `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/test-compile-fail3.rs b/src/test/rustdoc-ui/test-compile-fail3.rs
new file mode 100644
index 000000000..faa30ad83
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail3.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+"fail
diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr
new file mode 100644
index 000000000..fab801b3b
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail3.stderr
@@ -0,0 +1,9 @@
+error[E0765]: unterminated double quote string
+ --> $DIR/test-compile-fail3.rs:3:1
+ |
+3 | "fail
+ | ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0765`.
diff --git a/src/test/rustdoc-ui/test-no_std.rs b/src/test/rustdoc-ui/test-no_std.rs
new file mode 100644
index 000000000..ee919985e
--- /dev/null
+++ b/src/test/rustdoc-ui/test-no_std.rs
@@ -0,0 +1,13 @@
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+#![no_std]
+
+extern crate alloc;
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-no_std.stdout b/src/test/rustdoc-ui/test-no_std.stdout
new file mode 100644
index 000000000..8d5a30804
--- /dev/null
+++ b/src/test/rustdoc-ui/test-no_std.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/test-no_std.rs - f (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/test-type.rs b/src/test/rustdoc-ui/test-type.rs
new file mode 100644
index 000000000..882da5c25
--- /dev/null
+++ b/src/test/rustdoc-ui/test-type.rs
@@ -0,0 +1,26 @@
+// compile-flags: --test --test-args=--test-threads=1
+// check-pass
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+/// println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-type.stdout b/src/test/rustdoc-ui/test-type.stdout
new file mode 100644
index 000000000..a66fd240d
--- /dev/null
+++ b/src/test/rustdoc-ui/test-type.stdout
@@ -0,0 +1,10 @@
+
+running 5 tests
+test $DIR/test-type.rs - f (line 12) ... ignored
+test $DIR/test-type.rs - f (line 15) - compile ... ok
+test $DIR/test-type.rs - f (line 21) - compile fail ... ok
+test $DIR/test-type.rs - f (line 6) ... ok
+test $DIR/test-type.rs - f (line 9) ... ok
+
+test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/tuple-variadic-check.rs b/src/test/rustdoc-ui/tuple-variadic-check.rs
new file mode 100644
index 000000000..505de5348
--- /dev/null
+++ b/src/test/rustdoc-ui/tuple-variadic-check.rs
@@ -0,0 +1,15 @@
+#![feature(rustdoc_internals)]
+
+trait Mine {}
+
+// This one is fine
+#[doc(fake_variadic)]
+impl<T> Mine for (T,) {}
+
+trait Mine2 {}
+
+// This one is not
+#[doc(fake_variadic)] //~ ERROR
+impl<T, U> Mine for (T,U) {}
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/tuple-variadic-check.stderr b/src/test/rustdoc-ui/tuple-variadic-check.stderr
new file mode 100644
index 000000000..d127fb858
--- /dev/null
+++ b/src/test/rustdoc-ui/tuple-variadic-check.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
+ --> $DIR/tuple-variadic-check.rs:12:7
+ |
+LL | #[doc(fake_variadic)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs
new file mode 100644
index 000000000..ddf03dd07
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr
new file mode 100644
index 000000000..b105f47d7
--- /dev/null
+++ b/src/test/rustdoc-ui/unknown-renamed-lints.stderr
@@ -0,0 +1,64 @@
+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: Compilation failed, aborting rustdoc
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/rustdoc-ui/unparseable-doc-test.rs b/src/test/rustdoc-ui/unparseable-doc-test.rs
new file mode 100644
index 000000000..0cff8cd9a
--- /dev/null
+++ b/src/test/rustdoc-ui/unparseable-doc-test.rs
@@ -0,0 +1,11 @@
+// compile-flags: --test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+// rustc-env: RUST_BACKTRACE=0
+
+/// ```rust
+/// let x = 7;
+/// "unterminated
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout
new file mode 100644
index 000000000..2641c66f2
--- /dev/null
+++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout
@@ -0,0 +1,23 @@
+
+running 1 test
+test $DIR/unparseable-doc-test.rs - foo (line 7) ... FAILED
+
+failures:
+
+---- $DIR/unparseable-doc-test.rs - foo (line 7) stdout ----
+error[E0765]: unterminated double quote string
+ --> $DIR/unparseable-doc-test.rs:9:1
+ |
+LL | "unterminated
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0765`.
+Couldn't compile the test.
+
+failures:
+ $DIR/unparseable-doc-test.rs - foo (line 7)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/unused-braces-lint.rs b/src/test/rustdoc-ui/unused-braces-lint.rs
new file mode 100644
index 000000000..be0e31e4b
--- /dev/null
+++ b/src/test/rustdoc-ui/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/src/test/rustdoc-ui/unused-extern-crate.rs b/src/test/rustdoc-ui/unused-extern-crate.rs
new file mode 100644
index 000000000..f703a1837
--- /dev/null
+++ b/src/test/rustdoc-ui/unused-extern-crate.rs
@@ -0,0 +1,3 @@
+// check-pass
+// aux-crate:panic_item=panic-item.rs
+// @has unused_extern_crate/index.html
diff --git a/src/test/rustdoc-ui/unused.rs b/src/test/rustdoc-ui/unused.rs
new file mode 100644
index 000000000..702b24c36
--- /dev/null
+++ b/src/test/rustdoc-ui/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;
+}
diff --git a/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs
new file mode 100644
index 000000000..5037043f1
--- /dev/null
+++ b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs
@@ -0,0 +1 @@
+// compile-flags: --output ./foo
diff --git a/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr
new file mode 100644
index 000000000..96d2295ac
--- /dev/null
+++ b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr
@@ -0,0 +1,2 @@
+error: cannot use both 'out-dir' and 'output' at once
+
diff --git a/src/test/rustdoc-ui/wasm-safe.rs b/src/test/rustdoc-ui/wasm-safe.rs
new file mode 100644
index 000000000..ba971342b
--- /dev/null
+++ b/src/test/rustdoc-ui/wasm-safe.rs
@@ -0,0 +1,5 @@
+// check-pass
+
+#[cfg(any(target_arch = "wasm32", doc))]
+#[target_feature(enable = "simd128")]
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/z-help.rs b/src/test/rustdoc-ui/z-help.rs
new file mode 100644
index 000000000..c7cf841b9
--- /dev/null
+++ b/src/test/rustdoc-ui/z-help.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Zhelp
+// check-stdout
+// regex-error-pattern: -Z\s+self-profile
+
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
new file mode 100644
index 000000000..6dc412315
--- /dev/null
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -0,0 +1,200 @@
+ -Z allow-features=val -- only allow the listed language features to be enabled in code (space separated)
+ -Z always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
+ -Z assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
+ -Z asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
+ -Z assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
+ -Z binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+ -Z box-noalias=val -- emit noalias metadata for box (default: yes)
+ -Z branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
+ -Z cf-protection=val -- instrument control-flow architecture protection
+ -Z cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
+ -Z chalk=val -- enable the experimental Chalk-based trait solving engine
+ -Z codegen-backend=val -- the backend to use
+ -Z combine-cgu=val -- combine CGUs into a single one
+ -Z crate-attr=val -- inject the given attribute in the crate
+ -Z debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
+ -Z debug-macros=val -- emit line numbers debug info inside macros (default: no)
+ -Z deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
+ -Z dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
+ -Z dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
+ -Z dlltool=val -- import library generation tool (windows-gnu only)
+ -Z dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
+ -Z drop-tracking=val -- enables drop tracking in generators (default: no)
+ -Z dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
+ -Z dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
+ -Z dump-drop-tracking-cfg=val -- dump drop-tracking control-flow graph as a `.dot` file (default: no)
+ -Z dump-mir=val -- dump MIR state to file.
+ `val` is used to select which passes and functions to dump. For example:
+ `all` matches all passes and functions,
+ `foo` matches all passes for functions whose name contains 'foo',
+ `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
+ `foo | bar` all passes for function names containing 'foo' or 'bar'.
+ -Z dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
+ -Z dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
+ -Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
+ -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
+ -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+ -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
+ -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+ -Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
+ -Z export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
+ -Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
+ -Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
+ -Z fuel=val -- set the optimization fuel quota for a crate
+ -Z function-sections=val -- whether each function should go in its own section
+ -Z future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
+ -Z gcc-ld=val -- implementation of ld used by cc
+ -Z graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
+ -Z graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
+ -Z hir-stats=val -- print some statistics about AST and HIR (default: no)
+ -Z human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
+ -Z identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
+ -Z incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
+ -Z incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
+ -Z incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
+ -Z incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
+ -Z inline-mir=val -- enable MIR inlining (default: no)
+ -Z inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
+ -Z inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
+ -Z inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+ -Z input-stats=val -- gather statistics about the input (default: no)
+ -Z instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+ `=all` (implicit value)
+ `=except-unused-generics`
+ `=except-unused-functions`
+ `=off` (default)
+ -Z instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
+ -Z keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
+ -Z link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
+ -Z link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
+ -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated)
+ -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
+ -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
+ -Z ls=val -- list the symbols defined by a library crate (default: no)
+ -Z macro-backtrace=val -- show macro backtraces (default: no)
+ -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
+ -Z meta-stats=val -- gather metadata statistics (default: no)
+ -Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
+ -Z mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
+ -Z mir-pretty-relative-line-numbers=val -- use line numbers relative to the function in mir pretty printing
+ -Z mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
+ -Z move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
+ -Z mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
+ -Z new-llvm-pass-manager=val -- use new LLVM pass manager (default: no)
+ -Z nll-facts=val -- dump facts from NLL analysis into side files (default: no)
+ -Z nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
+ -Z no-analysis=val -- parse and expand the source, but run no analysis
+ -Z no-codegen=val -- run all passes except codegen; no output
+ -Z no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+ -Z no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints
+ -Z no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
+ -Z no-link=val -- compile without linking
+ -Z no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
+ -Z no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
+ -Z no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
+ -Z normalize-docs=val -- normalize associated items in rustdoc when generating documentation
+ -Z oom=val -- panic strategy for out-of-memory handling
+ -Z osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
+ -Z diagnostic-width=val -- set the current output width for diagnostic truncation
+ -Z panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
+ -Z panic-in-drop=val -- panic strategy for panics in drops
+ -Z parse-only=val -- parse only; do not compile, assemble, or link (default: no)
+ -Z perf-stats=val -- print some performance-related statistics (default: no)
+ -Z pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
+ -Z plt=val -- whether to use the PLT when calling into shared libraries;
+ only has effect for PIC code on systems with ELF binaries
+ (default: PLT is disabled if full relro is enabled)
+ -Z polonius=val -- enable polonius-based borrow-checker (default: no)
+ -Z polymorphize=val -- perform polymorphization analysis
+ -Z pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
+ -Z pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
+ -Z precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
+ -Z print-fuel=val -- make rustc print the total optimization fuel used by a crate
+ -Z print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
+ -Z print-mono-items=val -- print the result of the monomorphization collection pass
+ -Z print-type-sizes=val -- print layout information for each type encountered (default: no)
+ -Z proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
+ -Z proc-macro-execution-strategy=val -- how to run proc-macro code (default: same-thread)
+ -Z profile=val -- insert profiling code (default: no)
+ -Z profile-closures=val -- profile size of closures
+ -Z profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
+ -Z profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
+ -Z profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
+ -Z query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
+ -Z randomize-layout=val -- randomize the layout of types (default: no)
+ -Z layout-seed=val -- seed layout randomization
+ -Z relax-elf-relocations=val -- whether ELF relocations can be relaxed
+ -Z relro-level=val -- choose which RELRO level to use
+ -Z remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
+ -Z simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
+ -Z report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
+ -Z sanitizer=val -- use a sanitizer
+ -Z sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
+ -Z sanitizer-recover=val -- enable recovery for selected sanitizers
+ -Z saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
+ -Z save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
+ -Z self-profile=val -- run the self profiler and output the raw event data
+ -Z self-profile-events=val -- specify the events recorded by the self profiler;
+ for example: `-Z self-profile-events=default,query-keys`
+ all options: none, all, default, generic-activity, query-provider, query-cache-hit
+ query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes
+ -Z self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
+ `wall-time` (monotonic clock, i.e. `std::time::Instant`)
+ `instructions:u` (retired instructions, userspace-only)
+ `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)
+ -Z share-generics=val -- make the current crate share its generic instantiations
+ -Z show-span=val -- show spans for compiler debugging (expr|pat|ty)
+ -Z span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
+ -Z span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
+ -Z src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
+ -Z stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
+ -Z strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
+ -Z strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+ -Z split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
+ (default: `split`)
+
+ `split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
+ file which is ignored by the linker
+ `single`: sections which do not require relocation are written into object file but ignored
+ by the linker
+ -Z split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
+ -Z symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+ -Z teach=val -- show extended diagnostic help (default: no)
+ -Z temps-dir=val -- the directory the intermediate files are written to
+ -Z translate-lang=val -- language identifier for diagnostic output
+ -Z translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
+ -Z translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
+ -Z tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
+ -Z thinlto=val -- enable ThinLTO when possible
+ -Z thir-unsafeck=val -- use the THIR unsafety checker (default: no)
+ -Z threads=val -- use a thread pool with N threads
+ -Z time=val -- measure time of rustc processes (default: no)
+ -Z time-llvm-passes=val -- measure time of each LLVM pass (default: no)
+ -Z time-passes=val -- measure time of each rustc pass (default: no)
+ -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
+ -Z trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
+ -Z translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
+ -Z trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
+ -Z treat-err-as-bug=val -- treat error number `val` that occurs as bug
+ -Z trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
+ -Z ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
+ -Z uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
+ -Z unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
+ -Z unpretty=val -- present the input source, unstable (and less-pretty) variants;
+ `normal`, `identified`,
+ `expanded`, `expanded,identified`,
+ `expanded,hygiene` (with internal representations),
+ `ast-tree` (raw AST before expansion),
+ `ast-tree,expanded` (raw AST after expansion),
+ `hir` (the HIR), `hir,identified`,
+ `hir,typed` (HIR with types for each node),
+ `hir-tree` (dump the raw HIR),
+ `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
+ -Z unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
+ -Z unstable-options=val -- adds unstable command line options to rustc interface (default: no)
+ -Z use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
+ -Z validate-mir=val -- validate MIR after each transformation
+ -Z verbose=val -- in general, enable more debug printouts (default: no)
+ -Z verify-llvm-ir=val -- verify LLVM IR (default: no)
+ -Z virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
+ -Z wasi-exec-model=val -- whether to build a wasi command or reactor