summaryrefslogtreecommitdiffstats
path: root/tests/rustdoc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/rustdoc
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/rustdoc')
-rw-r--r--tests/rustdoc/all.rs28
-rw-r--r--tests/rustdoc/anchors.no_const_anchor.html1
-rw-r--r--tests/rustdoc/anchors.no_const_anchor2.html1
-rw-r--r--tests/rustdoc/anchors.no_method_anchor.html1
-rw-r--r--tests/rustdoc/anchors.no_trait_method_anchor.html1
-rw-r--r--tests/rustdoc/anchors.no_tymethod_anchor.html1
-rw-r--r--tests/rustdoc/anchors.no_type_anchor.html1
-rw-r--r--tests/rustdoc/anchors.no_type_anchor2.html1
-rw-r--r--tests/rustdoc/anchors.rs49
-rw-r--r--tests/rustdoc/anonymous-lifetime.rs28
-rw-r--r--tests/rustdoc/anonymous-reexport.rs22
-rw-r--r--tests/rustdoc/array-links.link_box_generic.html1
-rw-r--r--tests/rustdoc/array-links.link_box_u32.html1
-rw-r--r--tests/rustdoc/array-links.link_slice_generic.html1
-rw-r--r--tests/rustdoc/array-links.link_slice_u32.html1
-rw-r--r--tests/rustdoc/array-links.rs28
-rw-r--r--tests/rustdoc/asm-foreign.rs20
-rw-r--r--tests/rustdoc/asm-foreign2.rs11
-rw-r--r--tests/rustdoc/assoc-consts-version.rs15
-rw-r--r--tests/rustdoc/assoc-consts.rs104
-rw-r--r--tests/rustdoc/assoc-item-cast.rs14
-rw-r--r--tests/rustdoc/assoc-types.rs37
-rw-r--r--tests/rustdoc/associated-consts.rs51
-rw-r--r--tests/rustdoc/async-fn.rs95
-rw-r--r--tests/rustdoc/async-move-doctest.rs12
-rw-r--r--tests/rustdoc/async-trait-sig.rs14
-rw-r--r--tests/rustdoc/async-trait.rs16
-rw-r--r--tests/rustdoc/attribute-rendering.rs7
-rw-r--r--tests/rustdoc/attributes.rs13
-rw-r--r--tests/rustdoc/auto-impl-for-trait.rs16
-rw-r--r--tests/rustdoc/auto-impl-primitive.rs10
-rw-r--r--tests/rustdoc/auto-trait-not-send.rs8
-rw-r--r--tests/rustdoc/auto-traits.rs13
-rw-r--r--tests/rustdoc/auto_aliases.rs6
-rw-r--r--tests/rustdoc/auxiliary/all-item-types.rs22
-rw-r--r--tests/rustdoc/auxiliary/async-trait-dep.rs9
-rw-r--r--tests/rustdoc/auxiliary/auto-traits.rs3
-rw-r--r--tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs19
-rw-r--r--tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs5
-rw-r--r--tests/rustdoc/auxiliary/elided-lifetime.rs11
-rw-r--r--tests/rustdoc/auxiliary/empty.rs1
-rw-r--r--tests/rustdoc/auxiliary/enum-primitive.rs207
-rw-r--r--tests/rustdoc/auxiliary/extern-impl-trait.rs27
-rw-r--r--tests/rustdoc/auxiliary/extern-links.rs1
-rw-r--r--tests/rustdoc/auxiliary/external-cross-doc.md4
-rw-r--r--tests/rustdoc/auxiliary/external-cross.rs3
-rw-r--r--tests/rustdoc/auxiliary/external-doc.md3
-rw-r--r--tests/rustdoc/auxiliary/external-macro-src.rs15
-rw-r--r--tests/rustdoc/auxiliary/html_root.rs2
-rw-r--r--tests/rustdoc/auxiliary/incoherent-impl-types.rs7
-rw-r--r--tests/rustdoc/auxiliary/inline-default-methods.rs6
-rw-r--r--tests/rustdoc/auxiliary/issue-100204-aux.rs13
-rw-r--r--tests/rustdoc/auxiliary/issue-13698.rs8
-rw-r--r--tests/rustdoc/auxiliary/issue-15318.rs16
-rw-r--r--tests/rustdoc/auxiliary/issue-17476.rs7
-rw-r--r--tests/rustdoc/auxiliary/issue-19190-3.rs23
-rw-r--r--tests/rustdoc/auxiliary/issue-20646.rs7
-rw-r--r--tests/rustdoc/auxiliary/issue-20727.rs30
-rw-r--r--tests/rustdoc/auxiliary/issue-21092.rs12
-rw-r--r--tests/rustdoc/auxiliary/issue-21801.rs9
-rw-r--r--tests/rustdoc/auxiliary/issue-22025.rs10
-rw-r--r--tests/rustdoc/auxiliary/issue-23207-1.rs3
-rw-r--r--tests/rustdoc/auxiliary/issue-23207-2.rs5
-rw-r--r--tests/rustdoc/auxiliary/issue-26606-macro.rs4
-rw-r--r--tests/rustdoc/auxiliary/issue-27362-aux.rs10
-rw-r--r--tests/rustdoc/auxiliary/issue-28927-1.rs4
-rw-r--r--tests/rustdoc/auxiliary/issue-28927-2.rs1
-rw-r--r--tests/rustdoc/auxiliary/issue-29584.rs10
-rw-r--r--tests/rustdoc/auxiliary/issue-30109-1.rs1
-rw-r--r--tests/rustdoc/auxiliary/issue-34274.rs3
-rw-r--r--tests/rustdoc/auxiliary/issue-36031.rs9
-rw-r--r--tests/rustdoc/auxiliary/issue-40936.rs5
-rw-r--r--tests/rustdoc/auxiliary/issue-46727.rs7
-rw-r--r--tests/rustdoc/auxiliary/issue-48414.rs5
-rw-r--r--tests/rustdoc/auxiliary/issue-53689.rs1
-rw-r--r--tests/rustdoc/auxiliary/issue-57180.rs16
-rw-r--r--tests/rustdoc/auxiliary/issue-61592.rs4
-rw-r--r--tests/rustdoc/auxiliary/issue-73061.rs17
-rw-r--r--tests/rustdoc/auxiliary/issue-85454.rs17
-rw-r--r--tests/rustdoc/auxiliary/issue-86620-1.rs11
-rw-r--r--tests/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs17
-rw-r--r--tests/rustdoc/auxiliary/issue-99221-aux.rs20
-rw-r--r--tests/rustdoc/auxiliary/issue-99734-aux.rs11
-rw-r--r--tests/rustdoc/auxiliary/macro_pub_in_module.rs13
-rw-r--r--tests/rustdoc/auxiliary/masked.rs14
-rw-r--r--tests/rustdoc/auxiliary/mod-stackoverflow.rs11
-rw-r--r--tests/rustdoc/auxiliary/no_html_root.rs1
-rw-r--r--tests/rustdoc/auxiliary/normalize-assoc-item.rs12
-rw-r--r--tests/rustdoc/auxiliary/primitive-doc.rs9
-rw-r--r--tests/rustdoc/auxiliary/primitive-reexport.rs8
-rw-r--r--tests/rustdoc/auxiliary/pub-extern-crate.rs2
-rw-r--r--tests/rustdoc/auxiliary/pub-use-extern-macros.rs21
-rw-r--r--tests/rustdoc/auxiliary/real_gimli.rs13
-rw-r--r--tests/rustdoc/auxiliary/realcore.rs15
-rw-r--r--tests/rustdoc/auxiliary/reexp-stripped.rs11
-rw-r--r--tests/rustdoc/auxiliary/reexport-check.rs2
-rw-r--r--tests/rustdoc/auxiliary/reexport-doc-aux.rs5
-rw-r--r--tests/rustdoc/auxiliary/reexports.rs66
-rw-r--r--tests/rustdoc/auxiliary/rustdoc-default-impl.rs23
-rw-r--r--tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs11
-rw-r--r--tests/rustdoc/auxiliary/rustdoc-extern-method.rs7
-rw-r--r--tests/rustdoc/auxiliary/rustdoc-ffi.rs6
-rw-r--r--tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs3
-rw-r--r--tests/rustdoc/auxiliary/source-code-bar.rs17
-rw-r--r--tests/rustdoc/auxiliary/source_code.rs1
-rw-r--r--tests/rustdoc/auxiliary/src-links-external.rs1
-rw-r--r--tests/rustdoc/auxiliary/trait-alias-mention.rs3
-rw-r--r--tests/rustdoc/auxiliary/trait-visibility.rs3
-rw-r--r--tests/rustdoc/auxiliary/unit-return.rs3
-rw-r--r--tests/rustdoc/auxiliary/unstable-trait.rs26
-rw-r--r--tests/rustdoc/auxiliary/variant-struct.rs5
-rw-r--r--tests/rustdoc/bad-codeblock-syntax.rs44
-rw-r--r--tests/rustdoc/blanket-reexport-item.rs8
-rw-r--r--tests/rustdoc/bounds-in-multiple-parts.rs20
-rw-r--r--tests/rustdoc/cap-lints.rs9
-rw-r--r--tests/rustdoc/cfg-doctest.rs6
-rw-r--r--tests/rustdoc/cfg_doc_reexport.rs33
-rw-r--r--tests/rustdoc/check-source-code-urls-to-def-std.rs42
-rw-r--r--tests/rustdoc/check-source-code-urls-to-def.rs69
-rw-r--r--tests/rustdoc/check-styled-link.rs8
-rw-r--r--tests/rustdoc/check.rs5
-rw-r--r--tests/rustdoc/codeblock-title.rs25
-rw-r--r--tests/rustdoc/comment-in-doctest.rs20
-rw-r--r--tests/rustdoc/const-display.rs86
-rw-r--r--tests/rustdoc/const-doc.rs19
-rw-r--r--tests/rustdoc/const-fn.rs16
-rw-r--r--tests/rustdoc/const-generics/add-impl.rs17
-rw-r--r--tests/rustdoc/const-generics/auxiliary/extern_crate.rs16
-rw-r--r--tests/rustdoc/const-generics/const-generic-defaults.rs5
-rw-r--r--tests/rustdoc/const-generics/const-generic-slice.rs11
-rw-r--r--tests/rustdoc/const-generics/const-generics-docs.rs128
-rw-r--r--tests/rustdoc/const-generics/const-impl.rs37
-rw-r--r--tests/rustdoc/const-generics/generic_const_exprs.rs7
-rw-r--r--tests/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs18
-rw-r--r--tests/rustdoc/const-generics/type-alias.rs4
-rw-r--r--tests/rustdoc/const-intrinsic.rs25
-rw-r--r--tests/rustdoc/const-underscore.rs7
-rw-r--r--tests/rustdoc/const-value-display.rs9
-rw-r--r--tests/rustdoc/const.rs10
-rw-r--r--tests/rustdoc/constructor-imports.rs15
-rw-r--r--tests/rustdoc/crate-version-escape.rs5
-rw-r--r--tests/rustdoc/crate-version.rs3
-rw-r--r--tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs23
-rw-r--r--tests/rustdoc/cross-crate-hidden-impl-parameter.rs35
-rw-r--r--tests/rustdoc/cross-crate-links.rs59
-rw-r--r--tests/rustdoc/cross-crate-primitive-doc.rs13
-rw-r--r--tests/rustdoc/decl-trailing-whitespace.declaration.html7
-rw-r--r--tests/rustdoc/decl-trailing-whitespace.rs30
-rw-r--r--tests/rustdoc/decl_macro.rs56
-rw-r--r--tests/rustdoc/decl_macro_priv.rs14
-rw-r--r--tests/rustdoc/deep-structures.rs104
-rw-r--r--tests/rustdoc/default-impl.rs9
-rw-r--r--tests/rustdoc/default-theme.rs7
-rw-r--r--tests/rustdoc/default-trait-method-link.rs15
-rw-r--r--tests/rustdoc/default-trait-method.rs26
-rw-r--r--tests/rustdoc/deprecated-future-staged-api.rs18
-rw-r--r--tests/rustdoc/deprecated-future.rs6
-rw-r--r--tests/rustdoc/deprecated-impls.rs118
-rw-r--r--tests/rustdoc/deprecated.rs33
-rw-r--r--tests/rustdoc/deref-const-fn.rs38
-rw-r--r--tests/rustdoc/deref-mut-methods.rs29
-rw-r--r--tests/rustdoc/deref-recursive-pathbuf.rs25
-rw-r--r--tests/rustdoc/deref-recursive.rs41
-rw-r--r--tests/rustdoc/deref-slice-core.rs22
-rw-r--r--tests/rustdoc/deref-to-primitive.rs15
-rw-r--r--tests/rustdoc/deref-typedef.rs46
-rw-r--r--tests/rustdoc/description.rs24
-rw-r--r--tests/rustdoc/description_default.rs14
-rw-r--r--tests/rustdoc/doc-assoc-item.rs18
-rw-r--r--tests/rustdoc/doc-auto-cfg.rs35
-rw-r--r--tests/rustdoc/doc-cfg-hide.rs32
-rw-r--r--tests/rustdoc/doc-cfg-implicit-gate.rs7
-rw-r--r--tests/rustdoc/doc-cfg-implicit.rs31
-rw-r--r--tests/rustdoc/doc-cfg-simplification.rs182
-rw-r--r--tests/rustdoc/doc-cfg-target-feature.rs21
-rw-r--r--tests/rustdoc/doc-cfg-traits.rs124
-rw-r--r--tests/rustdoc/doc-cfg.rs101
-rw-r--r--tests/rustdoc/doc-notable_trait-mut_t_is_not_an_iterator.rs23
-rw-r--r--tests/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs21
-rw-r--r--tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html1
-rw-r--r--tests/rustdoc/doc-notable_trait-slice.rs20
-rw-r--r--tests/rustdoc/doc-notable_trait.bare-fn.html1
-rw-r--r--tests/rustdoc/doc-notable_trait.rs38
-rw-r--r--tests/rustdoc/doc-notable_trait.some-struct-new.html1
-rw-r--r--tests/rustdoc/doc-notable_trait.wrap-me.html1
-rw-r--r--tests/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs38
-rw-r--r--tests/rustdoc/doc-proc-macro.rs8
-rw-r--r--tests/rustdoc/doc_auto_cfg_nested_impl.rs24
-rw-r--r--tests/rustdoc/doctest-manual-crate-name.rs7
-rw-r--r--tests/rustdoc/double-quote-escape.rs11
-rw-r--r--tests/rustdoc/duplicate-cfg.rs53
-rw-r--r--tests/rustdoc/duplicate-flags.rs4
-rw-r--r--tests/rustdoc/duplicate_impls/impls.rs12
-rw-r--r--tests/rustdoc/duplicate_impls/issue-33054.rs14
-rw-r--r--tests/rustdoc/duplicated_impl.rs14
-rw-r--r--tests/rustdoc/early-unindent.rs26
-rw-r--r--tests/rustdoc/edition-doctest.rs44
-rw-r--r--tests/rustdoc/edition-flag.rs11
-rw-r--r--tests/rustdoc/elided-lifetime.rs43
-rw-r--r--tests/rustdoc/empty-doc-comment.rs22
-rw-r--r--tests/rustdoc/empty-impl-block-private-with-doc.rs44
-rw-r--r--tests/rustdoc/empty-impl-block-private.rs40
-rw-r--r--tests/rustdoc/empty-impl-block.rs20
-rw-r--r--tests/rustdoc/empty-impls.rs19
-rw-r--r--tests/rustdoc/empty-mod-private.rs16
-rw-r--r--tests/rustdoc/empty-mod-public.rs14
-rw-r--r--tests/rustdoc/empty-section.rs13
-rw-r--r--tests/rustdoc/ensure-src-link.rs6
-rw-r--r--tests/rustdoc/enum-headings.rs40
-rw-r--r--tests/rustdoc/escape-deref-methods.rs35
-rw-r--r--tests/rustdoc/extern-default-method.no_href_on_anchor.html1
-rw-r--r--tests/rustdoc/extern-default-method.rs23
-rw-r--r--tests/rustdoc/extern-html-root-url-precedence.rs7
-rw-r--r--tests/rustdoc/extern-html-root-url.rs18
-rw-r--r--tests/rustdoc/extern-impl-trait.rs11
-rw-r--r--tests/rustdoc/extern-impl.rs27
-rw-r--r--tests/rustdoc/extern-links.rs21
-rw-r--r--tests/rustdoc/extern-method.rs19
-rw-r--r--tests/rustdoc/external-cross.rs10
-rw-r--r--tests/rustdoc/external-doc.rs14
-rw-r--r--tests/rustdoc/external-macro-src.rs12
-rw-r--r--tests/rustdoc/feature-gate-doc_auto_cfg.rs8
-rw-r--r--tests/rustdoc/ffi.rs12
-rw-r--r--tests/rustdoc/fn-bound.rs21
-rw-r--r--tests/rustdoc/fn-pointer-arg-name.rs5
-rw-r--r--tests/rustdoc/fn-sidebar.rs9
-rw-r--r--tests/rustdoc/fn-type.rs13
-rw-r--r--tests/rustdoc/force-target-feature.rs11
-rw-r--r--tests/rustdoc/foreigntype-reexport.rs56
-rw-r--r--tests/rustdoc/foreigntype.rs18
-rw-r--r--tests/rustdoc/generic-associated-types/gats.rs33
-rw-r--r--tests/rustdoc/generic-associated-types/issue-94683.rs12
-rw-r--r--tests/rustdoc/generic-impl.rs16
-rw-r--r--tests/rustdoc/generic_const_exprs.rs24
-rw-r--r--tests/rustdoc/glob-shadowing-const.rs20
-rw-r--r--tests/rustdoc/glob-shadowing.rs86
-rw-r--r--tests/rustdoc/hidden-impls.rs17
-rw-r--r--tests/rustdoc/hidden-line.rs19
-rw-r--r--tests/rustdoc/hidden-methods.rs29
-rw-r--r--tests/rustdoc/hidden-trait-methods-with-document-hidden-items.rs31
-rw-r--r--tests/rustdoc/hidden-trait-methods.rs29
-rw-r--r--tests/rustdoc/hidden-trait-struct-impls.rs22
-rw-r--r--tests/rustdoc/hide-complex-unevaluated-const-arguments.rs82
-rw-r--r--tests/rustdoc/hide-complex-unevaluated-consts.rs71
-rw-r--r--tests/rustdoc/hide-unstable-trait.rs11
-rw-r--r--tests/rustdoc/higher-ranked-trait-bounds.rs61
-rw-r--r--tests/rustdoc/impl-box.rs16
-rw-r--r--tests/rustdoc/impl-disambiguation.rs30
-rw-r--r--tests/rustdoc/impl-everywhere.rs30
-rw-r--r--tests/rustdoc/impl-parts-crosscrate.rs20
-rw-r--r--tests/rustdoc/impl-parts.rs12
-rw-r--r--tests/rustdoc/impl-trait-alias.rs14
-rw-r--r--tests/rustdoc/implementor-stable-version.rs21
-rw-r--r--tests/rustdoc/impossible-default.rs20
-rw-r--r--tests/rustdoc/include_str_cut.rs7
-rw-r--r--tests/rustdoc/index-page.rs11
-rw-r--r--tests/rustdoc/infinite-redirection.rs29
-rw-r--r--tests/rustdoc/inline-default-methods.rs9
-rw-r--r--tests/rustdoc/inline_cross/add-docs.rs9
-rw-r--r--tests/rustdoc/inline_cross/assoc-items.rs42
-rw-r--r--tests/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html1
-rw-r--r--tests/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html1
-rw-r--r--tests/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html1
-rw-r--r--tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs44
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/add-docs.rs4
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/assoc-items.rs38
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs46
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/cross-glob.rs7
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/default-trait-method.rs16
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs17
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs8
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs41
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/implementors_inline.rs18
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-24183.rs14
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-33113.rs7
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/macro-vis.rs25
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/macros.rs10
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/proc_macro.rs47
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/renamed-via-module.rs9
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden-sig.rs12
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden.rs4
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs34
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/rustdoc-trait-object-impl.rs13
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/trait-vis.rs13
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/use_crate.rs5
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/use_crate_2.rs1
-rw-r--r--tests/rustdoc/inline_cross/cross-glob.rs16
-rw-r--r--tests/rustdoc/inline_cross/default-trait-method.rs20
-rw-r--r--tests/rustdoc/inline_cross/dyn_trait.rs31
-rw-r--r--tests/rustdoc/inline_cross/hidden-use.rs12
-rw-r--r--tests/rustdoc/inline_cross/impl-inline-without-trait.rs12
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs47
-rw-r--r--tests/rustdoc/inline_cross/implementors-js.rs25
-rw-r--r--tests/rustdoc/inline_cross/inline_hidden.rs12
-rw-r--r--tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html1
-rw-r--r--tests/rustdoc/inline_cross/issue-24183.rs18
-rw-r--r--tests/rustdoc/inline_cross/issue-28480.rs13
-rw-r--r--tests/rustdoc/inline_cross/issue-31948-1.rs27
-rw-r--r--tests/rustdoc/inline_cross/issue-31948-2.rs21
-rw-r--r--tests/rustdoc/inline_cross/issue-31948.rs29
-rw-r--r--tests/rustdoc/inline_cross/issue-32881.rs11
-rw-r--r--tests/rustdoc/inline_cross/issue-33113.rs10
-rw-r--r--tests/rustdoc/inline_cross/macro-vis.rs36
-rw-r--r--tests/rustdoc/inline_cross/macros.rs19
-rw-r--r--tests/rustdoc/inline_cross/proc_macro.rs36
-rw-r--r--tests/rustdoc/inline_cross/renamed-via-module.rs24
-rw-r--r--tests/rustdoc/inline_cross/trait-vis.rs7
-rw-r--r--tests/rustdoc/inline_cross/use_crate.rs27
-rw-r--r--tests/rustdoc/inline_local/glob-extern-document-private-items.rs25
-rw-r--r--tests/rustdoc/inline_local/glob-extern.rs21
-rw-r--r--tests/rustdoc/inline_local/glob-private-document-private-items.rs48
-rw-r--r--tests/rustdoc/inline_local/glob-private.rs42
-rw-r--r--tests/rustdoc/inline_local/hidden-use.rs10
-rw-r--r--tests/rustdoc/inline_local/issue-28537.rs17
-rw-r--r--tests/rustdoc/inline_local/issue-32343.rs23
-rw-r--r--tests/rustdoc/inline_local/macro_by_example.rs17
-rw-r--r--tests/rustdoc/inline_local/please_inline.rs19
-rw-r--r--tests/rustdoc/inline_local/trait-vis.rs18
-rw-r--r--tests/rustdoc/internal.rs18
-rw-r--r--tests/rustdoc/intra-doc-crate/auxiliary/self.rs10
-rw-r--r--tests/rustdoc/intra-doc-crate/self.rs9
-rw-r--r--tests/rustdoc/intra-doc/anchors.rs24
-rw-r--r--tests/rustdoc/intra-doc/assoc-reexport-super.rs20
-rw-r--r--tests/rustdoc/intra-doc/associated-defaults.rs26
-rw-r--r--tests/rustdoc/intra-doc/associated-items.rs68
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/empty.rs1
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/empty2.rs1
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs28
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs11
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs3
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs4
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs6
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs6
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs4
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/issue-66159-1.rs2
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/my-core.rs23
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs34
-rw-r--r--tests/rustdoc/intra-doc/auxiliary/pub-struct.rs1
-rw-r--r--tests/rustdoc/intra-doc/basic.rs84
-rw-r--r--tests/rustdoc/intra-doc/builtin-macros.rs3
-rw-r--r--tests/rustdoc/intra-doc/crate-relative-assoc.rs17
-rw-r--r--tests/rustdoc/intra-doc/crate-relative.rs13
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/additional_doc.rs10
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs6
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs19
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs7
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs5
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs10
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/module.rs7
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs20
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs12
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs13
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs16
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/basic.rs9
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/crate.rs6
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/hidden.rs10
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/macro.rs11
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/module.rs8
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/submodule-inner.rs8
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/submodule-outer.rs16
-rw-r--r--tests/rustdoc/intra-doc/cross-crate/traits.rs14
-rw-r--r--tests/rustdoc/intra-doc/disambiguators-removed.rs50
-rw-r--r--tests/rustdoc/intra-doc/email-address.rs10
-rw-r--r--tests/rustdoc/intra-doc/enum-struct-field.rs14
-rw-r--r--tests/rustdoc/intra-doc/extern-builtin-type-impl.rs11
-rw-r--r--tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs19
-rw-r--r--tests/rustdoc/intra-doc/extern-crate.rs9
-rw-r--r--tests/rustdoc/intra-doc/extern-inherent-impl.rs8
-rw-r--r--tests/rustdoc/intra-doc/extern-reference-link.rs7
-rw-r--r--tests/rustdoc/intra-doc/extern-type.rs37
-rw-r--r--tests/rustdoc/intra-doc/external-traits.rs12
-rw-r--r--tests/rustdoc/intra-doc/field.rs4
-rw-r--r--tests/rustdoc/intra-doc/generic-params.rs62
-rw-r--r--tests/rustdoc/intra-doc/generic-trait-impl.rs20
-rw-r--r--tests/rustdoc/intra-doc/in-bodies.rs30
-rw-r--r--tests/rustdoc/intra-doc/issue-103463.rs8
-rw-r--r--tests/rustdoc/intra-doc/issue-104145.rs14
-rw-r--r--tests/rustdoc/intra-doc/issue-66159.rs10
-rw-r--r--tests/rustdoc/intra-doc/issue-82209.rs11
-rw-r--r--tests/rustdoc/intra-doc/libstd-re-export.rs4
-rw-r--r--tests/rustdoc/intra-doc/macros-disambiguators.rs25
-rw-r--r--tests/rustdoc/intra-doc/mod-ambiguity.rs16
-rw-r--r--tests/rustdoc/intra-doc/mod-relative.rs17
-rw-r--r--tests/rustdoc/intra-doc/no-doc-primitive.rs15
-rw-r--r--tests/rustdoc/intra-doc/non-path-primitives.rs46
-rw-r--r--tests/rustdoc/intra-doc/prim-assoc.rs4
-rw-r--r--tests/rustdoc/intra-doc/prim-associated-traits.rs46
-rw-r--r--tests/rustdoc/intra-doc/prim-methods-external-core.rs17
-rw-r--r--tests/rustdoc/intra-doc/prim-methods-local.rs29
-rw-r--r--tests/rustdoc/intra-doc/prim-methods.rs7
-rw-r--r--tests/rustdoc/intra-doc/prim-precedence.rs16
-rw-r--r--tests/rustdoc/intra-doc/prim-self.rs41
-rw-r--r--tests/rustdoc/intra-doc/primitive-disambiguators.rs4
-rw-r--r--tests/rustdoc/intra-doc/primitive-non-default-impl.rs31
-rw-r--r--tests/rustdoc/intra-doc/private-failures-ignored.rs8
-rw-r--r--tests/rustdoc/intra-doc/private.rs20
-rw-r--r--tests/rustdoc/intra-doc/proc-macro.rs27
-rw-r--r--tests/rustdoc/intra-doc/pub-use.rs17
-rw-r--r--tests/rustdoc/intra-doc/raw-ident-self.rs13
-rw-r--r--tests/rustdoc/intra-doc/reexport-additional-docs.rs23
-rw-r--r--tests/rustdoc/intra-doc/self-cache.rs14
-rw-r--r--tests/rustdoc/intra-doc/self.rs116
-rw-r--r--tests/rustdoc/intra-doc/trait-impl.rs34
-rw-r--r--tests/rustdoc/intra-doc/trait-item.rs11
-rw-r--r--tests/rustdoc/intra-doc/true-false.rs8
-rw-r--r--tests/rustdoc/intra-doc/type-alias.rs19
-rw-r--r--tests/rustdoc/invalid.crate.name.rs3
-rw-r--r--tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs14
-rw-r--r--tests/rustdoc/issue-100241.rs12
-rw-r--r--tests/rustdoc/issue-100620.rs19
-rw-r--r--tests/rustdoc/issue-100679-sidebar-links-deref.rs30
-rw-r--r--tests/rustdoc/issue-101743-bold-tag.rs19
-rw-r--r--tests/rustdoc/issue-102154.rs13
-rw-r--r--tests/rustdoc/issue-105952.rs14
-rw-r--r--tests/rustdoc/issue-107350.rs18
-rw-r--r--tests/rustdoc/issue-12834.rs12
-rw-r--r--tests/rustdoc/issue-13698.rs16
-rw-r--r--tests/rustdoc/issue-15169.rs3
-rw-r--r--tests/rustdoc/issue-15318-2.rs12
-rw-r--r--tests/rustdoc/issue-15318-3.rs7
-rw-r--r--tests/rustdoc/issue-15318.rs11
-rw-r--r--tests/rustdoc/issue-15347.rs5
-rw-r--r--tests/rustdoc/issue-16019.rs9
-rw-r--r--tests/rustdoc/issue-16265-1.rs10
-rw-r--r--tests/rustdoc/issue-16265-2.rs4
-rw-r--r--tests/rustdoc/issue-17476.rs11
-rw-r--r--tests/rustdoc/issue-18199.rs9
-rw-r--r--tests/rustdoc/issue-19181.rs5
-rw-r--r--tests/rustdoc/issue-19190-2.rs12
-rw-r--r--tests/rustdoc/issue-19190-3.rs27
-rw-r--r--tests/rustdoc/issue-19190.rs20
-rw-r--r--tests/rustdoc/issue-20175.rs10
-rw-r--r--tests/rustdoc/issue-20646.rs26
-rw-r--r--tests/rustdoc/issue-20727-2.rs22
-rw-r--r--tests/rustdoc/issue-20727-3.rs24
-rw-r--r--tests/rustdoc/issue-20727-4.rs40
-rw-r--r--tests/rustdoc/issue-20727.rs24
-rw-r--r--tests/rustdoc/issue-21092.rs8
-rw-r--r--tests/rustdoc/issue-21474.rs11
-rw-r--r--tests/rustdoc/issue-21801.rs9
-rw-r--r--tests/rustdoc/issue-22025.rs6
-rw-r--r--tests/rustdoc/issue-22038.rs19
-rw-r--r--tests/rustdoc/issue-23106.rs7
-rw-r--r--tests/rustdoc/issue-23207.rs9
-rw-r--r--tests/rustdoc/issue-23511.rs13
-rw-r--r--tests/rustdoc/issue-23744.rs12
-rw-r--r--tests/rustdoc/issue-23812.rs36
-rw-r--r--tests/rustdoc/issue-25001.rs43
-rw-r--r--tests/rustdoc/issue-25944.rs11
-rw-r--r--tests/rustdoc/issue-26606.rs11
-rw-r--r--tests/rustdoc/issue-26995.rs7
-rw-r--r--tests/rustdoc/issue-27104.rs10
-rw-r--r--tests/rustdoc/issue-27362.rs10
-rw-r--r--tests/rustdoc/issue-27759.rs14
-rw-r--r--tests/rustdoc/issue-27862.rs4
-rw-r--r--tests/rustdoc/issue-28478.rs31
-rw-r--r--tests/rustdoc/issue-28927.rs6
-rw-r--r--tests/rustdoc/issue-29449.rs20
-rw-r--r--tests/rustdoc/issue-29503.rs18
-rw-r--r--tests/rustdoc/issue-29584.rs8
-rw-r--r--tests/rustdoc/issue-30109.rs14
-rw-r--r--tests/rustdoc/issue-30252.rs6
-rw-r--r--tests/rustdoc/issue-30366.rs6
-rw-r--r--tests/rustdoc/issue-31808.rs11
-rw-r--r--tests/rustdoc/issue-31899.rs59
-rw-r--r--tests/rustdoc/issue-32374.rs31
-rw-r--r--tests/rustdoc/issue-32395.rs15
-rw-r--r--tests/rustdoc/issue-32556.rs5
-rw-r--r--tests/rustdoc/issue-32890.rs17
-rw-r--r--tests/rustdoc/issue-33069.rs10
-rw-r--r--tests/rustdoc/issue-33178-1.rs10
-rw-r--r--tests/rustdoc/issue-33178.rs13
-rw-r--r--tests/rustdoc/issue-33302.rs51
-rw-r--r--tests/rustdoc/issue-33592.rs13
-rw-r--r--tests/rustdoc/issue-34025.rs12
-rw-r--r--tests/rustdoc/issue-34274.rs10
-rw-r--r--tests/rustdoc/issue-34423.rs10
-rw-r--r--tests/rustdoc/issue-34473.rs11
-rw-r--r--tests/rustdoc/issue-34928.rs6
-rw-r--r--tests/rustdoc/issue-35169-2.rs40
-rw-r--r--tests/rustdoc/issue-35169.rs35
-rw-r--r--tests/rustdoc/issue-35488.rs13
-rw-r--r--tests/rustdoc/issue-36031.rs9
-rw-r--r--tests/rustdoc/issue-38129.rs99
-rw-r--r--tests/rustdoc/issue-38219.rs8
-rw-r--r--tests/rustdoc/issue-40936.rs6
-rw-r--r--tests/rustdoc/issue-41783.codeblock.html5
-rw-r--r--tests/rustdoc/issue-41783.rs19
-rw-r--r--tests/rustdoc/issue-42760.rs15
-rw-r--r--tests/rustdoc/issue-43153.rs10
-rw-r--r--tests/rustdoc/issue-43701.rs5
-rw-r--r--tests/rustdoc/issue-43869.rs72
-rw-r--r--tests/rustdoc/issue-43893.rs19
-rw-r--r--tests/rustdoc/issue-45584.rs15
-rw-r--r--tests/rustdoc/issue-46271.rs5
-rw-r--r--tests/rustdoc/issue-46377.rs3
-rw-r--r--tests/rustdoc/issue-46380-2.rs9
-rw-r--r--tests/rustdoc/issue-46727.rs7
-rw-r--r--tests/rustdoc/issue-46766.rs6
-rw-r--r--tests/rustdoc/issue-46767.rs9
-rw-r--r--tests/rustdoc/issue-46976.rs1
-rw-r--r--tests/rustdoc/issue-47038.rs10
-rw-r--r--tests/rustdoc/issue-47197-blank-line-in-doc-block.rs8
-rw-r--r--tests/rustdoc/issue-47639.rs6
-rw-r--r--tests/rustdoc/issue-48377.rs13
-rw-r--r--tests/rustdoc/issue-48414.rs11
-rw-r--r--tests/rustdoc/issue-50159.rs20
-rw-r--r--tests/rustdoc/issue-51236.rs14
-rw-r--r--tests/rustdoc/issue-52873.rs171
-rw-r--r--tests/rustdoc/issue-53689.rs16
-rw-r--r--tests/rustdoc/issue-53812.rs20
-rw-r--r--tests/rustdoc/issue-54478-demo-allocator.rs42
-rw-r--r--tests/rustdoc/issue-54705.rs27
-rw-r--r--tests/rustdoc/issue-55001.rs31
-rw-r--r--tests/rustdoc/issue-55321.rs18
-rw-r--r--tests/rustdoc/issue-55364.rs86
-rw-r--r--tests/rustdoc/issue-56701.rs33
-rw-r--r--tests/rustdoc/issue-56822.rs24
-rw-r--r--tests/rustdoc/issue-57180.rs7
-rw-r--r--tests/rustdoc/issue-60482.rs9
-rw-r--r--tests/rustdoc/issue-60726.rs35
-rw-r--r--tests/rustdoc/issue-61592.rs15
-rw-r--r--tests/rustdoc/issue-67851-both.rs8
-rw-r--r--tests/rustdoc/issue-67851-hidden.rs8
-rw-r--r--tests/rustdoc/issue-67851-neither.rs6
-rw-r--r--tests/rustdoc/issue-67851-private.rs8
-rw-r--r--tests/rustdoc/issue-72340.rs19
-rw-r--r--tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs14
-rw-r--r--tests/rustdoc/issue-74083.rs21
-rw-r--r--tests/rustdoc/issue-75588.rs17
-rw-r--r--tests/rustdoc/issue-76501.rs17
-rw-r--r--tests/rustdoc/issue-78673.rs24
-rw-r--r--tests/rustdoc/issue-78701.rs20
-rw-r--r--tests/rustdoc/issue-79201.rs41
-rw-r--r--tests/rustdoc/issue-80233-normalize-auto-trait.rs37
-rw-r--r--tests/rustdoc/issue-82465-asref-for-and-of-local.rs16
-rw-r--r--tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs16
-rw-r--r--tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs16
-rw-r--r--tests/rustdoc/issue-85454.rs29
-rw-r--r--tests/rustdoc/issue-86620.rs9
-rw-r--r--tests/rustdoc/issue-88600.rs35
-rw-r--r--tests/rustdoc/issue-89309-heading-levels.rs29
-rw-r--r--tests/rustdoc/issue-89852.rs14
-rw-r--r--tests/rustdoc/issue-95633.rs7
-rw-r--r--tests/rustdoc/issue-95873.rs2
-rw-r--r--tests/rustdoc/issue-96381.rs16
-rw-r--r--tests/rustdoc/issue-98697.rs17
-rw-r--r--tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs19
-rw-r--r--tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs17
-rw-r--r--tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs14
-rw-r--r--tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs16
-rw-r--r--tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs14
-rw-r--r--tests/rustdoc/keyword.rs23
-rw-r--r--tests/rustdoc/legacy-const-generic.rs16
-rw-r--r--tests/rustdoc/lifetime-name.rs5
-rw-r--r--tests/rustdoc/line-breaks.rs30
-rw-r--r--tests/rustdoc/link-assoc-const.rs16
-rw-r--r--tests/rustdoc/link-title-escape.rs9
-rw-r--r--tests/rustdoc/local-reexport-doc.rs16
-rw-r--r--tests/rustdoc/logo-class-default.rs4
-rw-r--r--tests/rustdoc/logo-class.rs10
-rw-r--r--tests/rustdoc/macro-document-private-duplicate.rs25
-rw-r--r--tests/rustdoc/macro-document-private.rs19
-rw-r--r--tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html6
-rw-r--r--tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html15
-rw-r--r--tests/rustdoc/macro-generated-macro.rs39
-rw-r--r--tests/rustdoc/macro-higher-kinded-function.rs21
-rw-r--r--tests/rustdoc/macro-in-async-block.rs9
-rw-r--r--tests/rustdoc/macro-in-closure.rs16
-rw-r--r--tests/rustdoc/macro-indirect-use.rs16
-rw-r--r--tests/rustdoc/macro-private-not-documented.rs19
-rw-r--r--tests/rustdoc/macro_pub_in_module.rs82
-rw-r--r--tests/rustdoc/macro_rules-matchers.rs34
-rw-r--r--tests/rustdoc/macros.rs24
-rw-r--r--tests/rustdoc/manual_impl.rs77
-rw-r--r--tests/rustdoc/markdown-summaries.rs27
-rw-r--r--tests/rustdoc/masked.rs31
-rw-r--r--tests/rustdoc/method-list.rs18
-rw-r--r--tests/rustdoc/mixing-doc-comments-and-attrs.S1_top-doc.html4
-rw-r--r--tests/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html4
-rw-r--r--tests/rustdoc/mixing-doc-comments-and-attrs.S3_top-doc.html3
-rw-r--r--tests/rustdoc/mixing-doc-comments-and-attrs.rs25
-rw-r--r--tests/rustdoc/mod-stackoverflow.rs6
-rw-r--r--tests/rustdoc/module-impls.rs5
-rw-r--r--tests/rustdoc/multiple-import-levels.rs34
-rw-r--r--tests/rustdoc/must_implement_one_of.rs10
-rw-r--r--tests/rustdoc/mut-params.rs18
-rw-r--r--tests/rustdoc/namespaces.rs16
-rw-r--r--tests/rustdoc/negative-impl-sidebar.rs9
-rw-r--r--tests/rustdoc/negative-impl.rs14
-rw-r--r--tests/rustdoc/nested-modules.rs42
-rw-r--r--tests/rustdoc/no-compiler-reexport.rs7
-rw-r--r--tests/rustdoc/no-crate-filter.rs6
-rw-r--r--tests/rustdoc/no-run-still-checks-lints.rs9
-rw-r--r--tests/rustdoc/no-stack-overflow-25295.rs35
-rw-r--r--tests/rustdoc/no-unit-struct-field.rs18
-rw-r--r--tests/rustdoc/no_std-primitive.rs6
-rw-r--r--tests/rustdoc/normalize-assoc-item.rs82
-rw-r--r--tests/rustdoc/not-wf-ambiguous-normalization.rs24
-rw-r--r--tests/rustdoc/nul-error.rs8
-rw-r--r--tests/rustdoc/playground-arg.rs13
-rw-r--r--tests/rustdoc/playground-empty.rs13
-rw-r--r--tests/rustdoc/playground-none.rs9
-rw-r--r--tests/rustdoc/playground-syntax-error.rs21
-rw-r--r--tests/rustdoc/playground.rs27
-rw-r--r--tests/rustdoc/primitive-link.rs14
-rw-r--r--tests/rustdoc/primitive-reexport.rs28
-rw-r--r--tests/rustdoc/primitive-reference.rs37
-rw-r--r--tests/rustdoc/primitive-slice-auto-trait.rs14
-rw-r--r--tests/rustdoc/primitive-tuple-auto-trait.rs22
-rw-r--r--tests/rustdoc/primitive-tuple-variadic.rs18
-rw-r--r--tests/rustdoc/primitive-unit-auto-trait.rs14
-rw-r--r--tests/rustdoc/primitive.rs21
-rw-r--r--tests/rustdoc/primitive/no_std.rs16
-rw-r--r--tests/rustdoc/primitive/primitive-generic-impl.rs8
-rw-r--r--tests/rustdoc/private-type-alias.rs31
-rw-r--r--tests/rustdoc/proc-macro.rs72
-rw-r--r--tests/rustdoc/process-termination.rs24
-rw-r--r--tests/rustdoc/pub-extern-crate.rs9
-rw-r--r--tests/rustdoc/pub-method.rs20
-rw-r--r--tests/rustdoc/pub-use-extern-macros.rs17
-rw-r--r--tests/rustdoc/range-arg-pattern.rs5
-rw-r--r--tests/rustdoc/raw-ident-eliminate-r-hashtag.rs21
-rw-r--r--tests/rustdoc/read-more-unneeded.rs34
-rw-r--r--tests/rustdoc/recursion1.rs13
-rw-r--r--tests/rustdoc/recursion2.rs13
-rw-r--r--tests/rustdoc/recursion3.rs13
-rw-r--r--tests/rustdoc/recursive-deref-sidebar.rs22
-rw-r--r--tests/rustdoc/recursive-deref.rs120
-rw-r--r--tests/rustdoc/redirect-const.rs13
-rw-r--r--tests/rustdoc/redirect-map-empty.rs6
-rw-r--r--tests/rustdoc/redirect-map.rs23
-rw-r--r--tests/rustdoc/redirect-rename.rs34
-rw-r--r--tests/rustdoc/redirect.rs39
-rw-r--r--tests/rustdoc/reexport-check.rs18
-rw-r--r--tests/rustdoc/reexport-dep-foreign-fn.rs12
-rw-r--r--tests/rustdoc/reexport-doc-hidden.rs26
-rw-r--r--tests/rustdoc/reexport-doc.rs8
-rw-r--r--tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs48
-rw-r--r--tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs61
-rw-r--r--tests/rustdoc/reexports-priv.rs135
-rw-r--r--tests/rustdoc/reexports.rs129
-rw-r--r--tests/rustdoc/remove-duplicates.rs14
-rw-r--r--tests/rustdoc/remove-url-from-headings.rs17
-rw-r--r--tests/rustdoc/return-impl-trait.rs15
-rw-r--r--tests/rustdoc/rfc-2632-const-trait-impl.rs70
-rw-r--r--tests/rustdoc/rustc-incoherent-impls.rs28
-rw-r--r--tests/rustdoc/rustc-macro-crate.rs14
-rw-r--r--tests/rustdoc/safe-intrinsic.rs22
-rw-r--r--tests/rustdoc/same-crate-hidden-impl-parameter.rs36
-rw-r--r--tests/rustdoc/sanitizer-option.rs18
-rw-r--r--tests/rustdoc/search-index-summaries.rs10
-rw-r--r--tests/rustdoc/search-index.rs26
-rw-r--r--tests/rustdoc/short-docblock-codeblock.rs10
-rw-r--r--tests/rustdoc/short-docblock.rs25
-rw-r--r--tests/rustdoc/short-line.md2
-rw-r--r--tests/rustdoc/show-const-contents.rs68
-rw-r--r--tests/rustdoc/sidebar-all-page.rs35
-rw-r--r--tests/rustdoc/sidebar-items.rs56
-rw-r--r--tests/rustdoc/sidebar-link-generation.rs13
-rw-r--r--tests/rustdoc/sidebar-links-to-foreign-impl.rs16
-rw-r--r--tests/rustdoc/sized_trait.rs17
-rw-r--r--tests/rustdoc/slice-links.link_box_generic.html1
-rw-r--r--tests/rustdoc/slice-links.link_box_u32.html1
-rw-r--r--tests/rustdoc/slice-links.link_slice_generic.html1
-rw-r--r--tests/rustdoc/slice-links.link_slice_u32.html1
-rw-r--r--tests/rustdoc/slice-links.rs28
-rw-r--r--tests/rustdoc/smart-punct.rs28
-rw-r--r--tests/rustdoc/smoke.rs25
-rw-r--r--tests/rustdoc/sort-modules-by-appearance.rs13
-rw-r--r--tests/rustdoc/source-file.rs5
-rw-r--r--tests/rustdoc/source-version-separator.rs30
-rw-r--r--tests/rustdoc/spotlight-from-dependency.odd.html1
-rw-r--r--tests/rustdoc/spotlight-from-dependency.rs25
-rw-r--r--tests/rustdoc/src-links-auto-impls.rs12
-rw-r--r--tests/rustdoc/src-links-external.rs13
-rw-r--r--tests/rustdoc/src-links.rs51
-rw-r--r--tests/rustdoc/src-links/compiletest-ignore-dir0
-rw-r--r--tests/rustdoc/src-links/fizz.rs1
-rw-r--r--tests/rustdoc/src-links/mod.rs19
-rw-r--r--tests/rustdoc/stability.rs12
-rw-r--r--tests/rustdoc/static-root-path.rs18
-rw-r--r--tests/rustdoc/static.rs12
-rw-r--r--tests/rustdoc/strip-block-doc-comments-stars.docblock.html2
-rw-r--r--tests/rustdoc/strip-block-doc-comments-stars.rs11
-rw-r--r--tests/rustdoc/strip-enum-variant.no-not-shown.html1
-rw-r--r--tests/rustdoc/strip-enum-variant.rs11
-rw-r--r--tests/rustdoc/struct-arg-pattern.rs10
-rw-r--r--tests/rustdoc/struct-field.rs22
-rw-r--r--tests/rustdoc/struct-implementations-title.rs9
-rw-r--r--tests/rustdoc/structfields.rs44
-rw-r--r--tests/rustdoc/synthetic_auto/basic.rs8
-rw-r--r--tests/rustdoc/synthetic_auto/complex.rs42
-rw-r--r--tests/rustdoc/synthetic_auto/crate-local.rs9
-rw-r--r--tests/rustdoc/synthetic_auto/issue-72213-projection-lifetime.rs25
-rw-r--r--tests/rustdoc/synthetic_auto/lifetimes.rs19
-rw-r--r--tests/rustdoc/synthetic_auto/manual.rs14
-rw-r--r--tests/rustdoc/synthetic_auto/negative.rs13
-rw-r--r--tests/rustdoc/synthetic_auto/nested.rs19
-rw-r--r--tests/rustdoc/synthetic_auto/no-redundancy.rs16
-rw-r--r--tests/rustdoc/synthetic_auto/overflow.rs35
-rw-r--r--tests/rustdoc/synthetic_auto/project.rs34
-rw-r--r--tests/rustdoc/synthetic_auto/self-referential.rs29
-rw-r--r--tests/rustdoc/synthetic_auto/static-region.rs10
-rw-r--r--tests/rustdoc/tab_title.rs44
-rw-r--r--tests/rustdoc/table-in-docblock.rs16
-rw-r--r--tests/rustdoc/task-lists.rs13
-rw-r--r--tests/rustdoc/test-lists.rs26
-rw-r--r--tests/rustdoc/test-parens.rs5
-rw-r--r--tests/rustdoc/test-strikethrough.rs6
-rw-r--r--tests/rustdoc/test_option_check/bar.rs9
-rw-r--r--tests/rustdoc/test_option_check/test.rs18
-rw-r--r--tests/rustdoc/thread-local-src.rs6
-rw-r--r--tests/rustdoc/titles.rs56
-rw-r--r--tests/rustdoc/toggle-item-contents.rs185
-rw-r--r--tests/rustdoc/toggle-method.rs18
-rw-r--r--tests/rustdoc/toggle-trait-fn.rs30
-rw-r--r--tests/rustdoc/trait-alias-mention.rs10
-rw-r--r--tests/rustdoc/trait-impl-items-links-and-anchors.rs65
-rw-r--r--tests/rustdoc/trait-impl.rs45
-rw-r--r--tests/rustdoc/trait-self-link.rs6
-rw-r--r--tests/rustdoc/trait-src-link.rs26
-rw-r--r--tests/rustdoc/trait-visibility.rs8
-rw-r--r--tests/rustdoc/trait_alias.rs26
-rw-r--r--tests/rustdoc/traits-in-bodies-private.rs13
-rw-r--r--tests/rustdoc/traits-in-bodies.rs52
-rw-r--r--tests/rustdoc/tuple-struct-fields-doc.rs50
-rw-r--r--tests/rustdoc/tuples.link1_i32.html1
-rw-r--r--tests/rustdoc/tuples.link1_t.html1
-rw-r--r--tests/rustdoc/tuples.link2_i32.html1
-rw-r--r--tests/rustdoc/tuples.link2_t.html1
-rw-r--r--tests/rustdoc/tuples.link2_tu.html1
-rw-r--r--tests/rustdoc/tuples.link_unit.html1
-rw-r--r--tests/rustdoc/tuples.rs20
-rw-r--r--tests/rustdoc/type-layout-flag-required.rs4
-rw-r--r--tests/rustdoc/type-layout.rs85
-rw-r--r--tests/rustdoc/typedef.rs25
-rw-r--r--tests/rustdoc/unindent.md1
-rw-r--r--tests/rustdoc/unindent.rs62
-rw-r--r--tests/rustdoc/union.rs8
-rw-r--r--tests/rustdoc/unit-return.rs17
-rw-r--r--tests/rustdoc/universal-impl-trait.rs55
-rw-r--r--tests/rustdoc/unneeded-trait-implementations-title.rs5
-rw-r--r--tests/rustdoc/use-attr.rs8
-rw-r--r--tests/rustdoc/useless_lifetime_bound.rs13
-rw-r--r--tests/rustdoc/variadic.rs4
-rw-r--r--tests/rustdoc/version-separator-without-source.rs23
-rw-r--r--tests/rustdoc/viewpath-rename.rs21
-rw-r--r--tests/rustdoc/viewpath-self.rs21
-rw-r--r--tests/rustdoc/visibility.rs105
-rw-r--r--tests/rustdoc/where-clause-order.rs19
-rw-r--r--tests/rustdoc/where-sized.rs6
-rw-r--r--tests/rustdoc/where.SWhere_Simd_item-decl.html1
-rw-r--r--tests/rustdoc/where.SWhere_TraitWhere_item-decl.html8
-rw-r--r--tests/rustdoc/where.rs62
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.enum.html4
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.enum2.html4
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.rs77
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.struct.html4
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.struct2.html4
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.trait.html6
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.trait2.html6
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.union.html3
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.union2.html3
-rw-r--r--tests/rustdoc/without-redirect.rs13
-rw-r--r--tests/rustdoc/wrapping.rs5
766 files changed, 15768 insertions, 0 deletions
diff --git a/tests/rustdoc/all.rs b/tests/rustdoc/all.rs
new file mode 100644
index 000000000..4c8d02310
--- /dev/null
+++ b/tests/rustdoc/all.rs
@@ -0,0 +1,28 @@
+#![crate_name = "foo"]
+
+// @has foo/all.html '//a[@href="struct.Struct.html"]' 'Struct'
+// @has foo/all.html '//a[@href="enum.Enum.html"]' 'Enum'
+// @has foo/all.html '//a[@href="union.Union.html"]' 'Union'
+// @has foo/all.html '//a[@href="constant.CONST.html"]' 'CONST'
+// @has foo/all.html '//a[@href="static.STATIC.html"]' 'STATIC'
+// @has foo/all.html '//a[@href="fn.function.html"]' 'function'
+
+pub struct Struct;
+pub enum Enum {
+ X,
+ Y,
+}
+pub union Union {
+ x: u32,
+}
+pub const CONST: u32 = 0;
+pub static STATIC: &str = "baguette";
+pub fn function() {}
+
+mod private_module {
+ pub struct ReexportedStruct;
+}
+
+// @has foo/all.html '//a[@href="struct.ReexportedStruct.html"]' 'ReexportedStruct'
+// @!hasraw foo/all.html 'private_module'
+pub use private_module::ReexportedStruct;
diff --git a/tests/rustdoc/anchors.no_const_anchor.html b/tests/rustdoc/anchors.no_const_anchor.html
new file mode 100644
index 000000000..75e67330a
--- /dev/null
+++ b/tests/rustdoc/anchors.no_const_anchor.html
@@ -0,0 +1 @@
+<section id="associatedconstant.YOLO" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_const_anchor2.html b/tests/rustdoc/anchors.no_const_anchor2.html
new file mode 100644
index 000000000..c00251976
--- /dev/null
+++ b/tests/rustdoc/anchors.no_const_anchor2.html
@@ -0,0 +1 @@
+<section id="associatedconstant.X" class="associatedconstant has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#42">source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_method_anchor.html b/tests/rustdoc/anchors.no_method_anchor.html
new file mode 100644
index 000000000..b9ec8bf4c
--- /dev/null
+++ b/tests/rustdoc/anchors.no_method_anchor.html
@@ -0,0 +1 @@
+<section id="method.new" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#48">source</a><h4 class="code-header">pub fn <a href="#method.new" class="fn">new</a>() -&gt; Self</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_trait_method_anchor.html b/tests/rustdoc/anchors.no_trait_method_anchor.html
new file mode 100644
index 000000000..4308ddad4
--- /dev/null
+++ b/tests/rustdoc/anchors.no_trait_method_anchor.html
@@ -0,0 +1 @@
+<section id="method.bar" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fn">bar</a>()</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_tymethod_anchor.html b/tests/rustdoc/anchors.no_tymethod_anchor.html
new file mode 100644
index 000000000..91eed8a37
--- /dev/null
+++ b/tests/rustdoc/anchors.no_tymethod_anchor.html
@@ -0,0 +1 @@
+<section id="tymethod.foo" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fn">foo</a>()</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_type_anchor.html b/tests/rustdoc/anchors.no_type_anchor.html
new file mode 100644
index 000000000..2c66d5aa3
--- /dev/null
+++ b/tests/rustdoc/anchors.no_type_anchor.html
@@ -0,0 +1 @@
+<section id="associatedtype.T" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_type_anchor2.html b/tests/rustdoc/anchors.no_type_anchor2.html
new file mode 100644
index 000000000..72a1186bf
--- /dev/null
+++ b/tests/rustdoc/anchors.no_type_anchor2.html
@@ -0,0 +1 @@
+<section id="associatedtype.Y" class="associatedtype has-srclink"><h4 class="code-header">type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section>
diff --git a/tests/rustdoc/anchors.rs b/tests/rustdoc/anchors.rs
new file mode 100644
index 000000000..034cf8eaf
--- /dev/null
+++ b/tests/rustdoc/anchors.rs
@@ -0,0 +1,49 @@
+// This test ensures that anchors are generated in the right places.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @has 'foo/trait.Bar.html'
+pub trait Bar {
+ // There should be no anchors here.
+ // @snapshot no_type_anchor - '//*[@id="associatedtype.T"]'
+ type T;
+ // There should be no anchors here.
+ // @snapshot no_const_anchor - '//*[@id="associatedconstant.YOLO"]'
+ const YOLO: u32;
+
+ // There should be no anchors here.
+ // @snapshot no_tymethod_anchor - '//*[@id="tymethod.foo"]'
+ fn foo();
+ // There should be no anchors here.
+ // @snapshot no_trait_method_anchor - '//*[@id="method.bar"]'
+ fn bar() {}
+}
+
+// @has 'foo/struct.Foo.html'
+impl Bar for Foo {
+ // @has - '//*[@id="associatedtype.T"]/a[@class="anchor"]' ''
+ type T = u32;
+ // @has - '//*[@id="associatedconstant.YOLO"]/a[@class="anchor"]' ''
+ const YOLO: u32 = 0;
+
+ // @has - '//*[@id="method.foo"]/a[@class="anchor"]' ''
+ fn foo() {}
+ // Same check for provided "bar" method.
+ // @has - '//*[@id="method.bar"]/a[@class="anchor"]' ''
+}
+
+impl Foo {
+ // @snapshot no_const_anchor2 - '//*[@id="associatedconstant.X"]'
+ // There should be no anchors here.
+ pub const X: i32 = 0;
+ // @snapshot no_type_anchor2 - '//*[@id="associatedtype.Y"]'
+ // There should be no anchors here.
+ pub type Y = u32;
+ // @snapshot no_method_anchor - '//*[@id="method.new"]'
+ // There should be no anchors here.
+ pub fn new() -> Self { Self }
+}
diff --git a/tests/rustdoc/anonymous-lifetime.rs b/tests/rustdoc/anonymous-lifetime.rs
new file mode 100644
index 000000000..390ed5a1f
--- /dev/null
+++ b/tests/rustdoc/anonymous-lifetime.rs
@@ -0,0 +1,28 @@
+// Regression test for https://github.com/rust-lang/rust/issues/84634
+#![crate_name = "foo"]
+
+use std::pin::Pin;
+use std::task::Poll;
+
+pub trait Stream {
+ type Item;
+
+ fn poll_next(mut self: Pin<&mut Self>) -> Poll<Option<Self::Item>>;
+ fn size_hint(&self) -> (usize, Option<usize>);
+}
+
+// @has 'foo/trait.Stream.html'
+// @has - '//*[@class="code-header"]' 'impl<S: ?Sized + Stream + Unpin> Stream for &mut S'
+impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
+ type Item = S::Item;
+
+ fn poll_next(
+ mut self: Pin<&mut Self>,
+ ) -> Poll<Option<Self::Item>> {
+ S::poll_next(Pin::new(&mut **self), cx)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (**self).size_hint()
+ }
+}
diff --git a/tests/rustdoc/anonymous-reexport.rs b/tests/rustdoc/anonymous-reexport.rs
new file mode 100644
index 000000000..6b884ff14
--- /dev/null
+++ b/tests/rustdoc/anonymous-reexport.rs
@@ -0,0 +1,22 @@
+#![crate_name = "foo"]
+
+// This test ensures we don't display anonymous (non-inline) re-exports of public items.
+
+// @has 'foo/index.html'
+// @has - '//*[@id="main-content"]' ''
+// We check that the only "h2" present is for "Bla".
+// @count - '//*[@id="main-content"]/h2' 1
+// @has - '//*[@id="main-content"]/h2' 'Structs'
+// @count - '//*[@id="main-content"]//a[@class="struct"]' 1
+
+mod ext {
+ pub trait Foo {}
+ pub trait Bar {}
+ pub struct S;
+}
+
+pub use crate::ext::Foo as _;
+pub use crate::ext::Bar as _;
+pub use crate::ext::S as _;
+
+pub struct Bla;
diff --git a/tests/rustdoc/array-links.link_box_generic.html b/tests/rustdoc/array-links.link_box_generic.html
new file mode 100644
index 000000000..3481bb6a0
--- /dev/null
+++ b/tests/rustdoc/array-links.link_box_generic.html
@@ -0,0 +1 @@
+<code>pub fn delta&lt;T&gt;() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;<a class="primitive" href="{{channel}}/core/primitive.array.html">[T; 1]</a>&gt;</code> \ No newline at end of file
diff --git a/tests/rustdoc/array-links.link_box_u32.html b/tests/rustdoc/array-links.link_box_u32.html
new file mode 100644
index 000000000..e864ae55c
--- /dev/null
+++ b/tests/rustdoc/array-links.link_box_u32.html
@@ -0,0 +1 @@
+<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]&gt;</code> \ No newline at end of file
diff --git a/tests/rustdoc/array-links.link_slice_generic.html b/tests/rustdoc/array-links.link_slice_generic.html
new file mode 100644
index 000000000..f1ca2f59b
--- /dev/null
+++ b/tests/rustdoc/array-links.link_slice_generic.html
@@ -0,0 +1 @@
+<code>pub fn beta&lt;T&gt;() -&gt; &amp;'static <a class="primitive" href="{{channel}}/core/primitive.array.html">[T; 1]</a></code> \ No newline at end of file
diff --git a/tests/rustdoc/array-links.link_slice_u32.html b/tests/rustdoc/array-links.link_slice_u32.html
new file mode 100644
index 000000000..c3943e8d3
--- /dev/null
+++ b/tests/rustdoc/array-links.link_slice_u32.html
@@ -0,0 +1 @@
+<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]</code> \ No newline at end of file
diff --git a/tests/rustdoc/array-links.rs b/tests/rustdoc/array-links.rs
new file mode 100644
index 000000000..e7c0ee2de
--- /dev/null
+++ b/tests/rustdoc/array-links.rs
@@ -0,0 +1,28 @@
+#![crate_name = "foo"]
+#![no_std]
+
+pub struct MyBox<T: ?Sized>(*const T);
+
+// @has 'foo/fn.alpha.html'
+// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn alpha() -> &'static [u32; 1] {
+ loop {}
+}
+
+// @has 'foo/fn.beta.html'
+// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn beta<T>() -> &'static [T; 1] {
+ loop {}
+}
+
+// @has 'foo/fn.gamma.html'
+// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn gamma() -> MyBox<[u32; 1]> {
+ loop {}
+}
+
+// @has 'foo/fn.delta.html'
+// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn delta<T>() -> MyBox<[T; 1]> {
+ loop {}
+}
diff --git a/tests/rustdoc/asm-foreign.rs b/tests/rustdoc/asm-foreign.rs
new file mode 100644
index 000000000..d7550ca5a
--- /dev/null
+++ b/tests/rustdoc/asm-foreign.rs
@@ -0,0 +1,20 @@
+// Make sure rustdoc accepts asm! for a foreign architecture.
+
+use std::arch::asm;
+
+// @has asm_foreign/fn.aarch64.html
+pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ || {};
+ b
+ });
+ c
+}
+
+// @has asm_foreign/fn.x86.html
+pub unsafe fn x86(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
+ c
+}
diff --git a/tests/rustdoc/asm-foreign2.rs b/tests/rustdoc/asm-foreign2.rs
new file mode 100644
index 000000000..87306901e
--- /dev/null
+++ b/tests/rustdoc/asm-foreign2.rs
@@ -0,0 +1,11 @@
+// only-aarch64
+// Make sure rustdoc accepts options(att_syntax) asm! on non-x86 targets.
+
+use std::arch::asm;
+
+// @has asm_foreign2/fn.x86.html
+pub unsafe fn x86(x: i64) -> i64 {
+ let y;
+ asm!("movq {}, {}", in(reg) x, out(reg) y, options(att_syntax));
+ y
+}
diff --git a/tests/rustdoc/assoc-consts-version.rs b/tests/rustdoc/assoc-consts-version.rs
new file mode 100644
index 000000000..6060bc0a6
--- /dev/null
+++ b/tests/rustdoc/assoc-consts-version.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+
+#![feature(staged_api)]
+
+#![stable(since="1.1.1", feature="rust1")]
+
+#[stable(since="1.1.1", feature="rust1")]
+pub struct SomeStruct;
+
+impl SomeStruct {
+ // @has 'foo/struct.SomeStruct.html' \
+ // '//*[@id="associatedconstant.SOME_CONST"]//span[@class="since"]' '1.1.2'
+ #[stable(since="1.1.2", feature="rust2")]
+ pub const SOME_CONST: usize = 0;
+}
diff --git a/tests/rustdoc/assoc-consts.rs b/tests/rustdoc/assoc-consts.rs
new file mode 100644
index 000000000..77b139b64
--- /dev/null
+++ b/tests/rustdoc/assoc-consts.rs
@@ -0,0 +1,104 @@
+pub trait Foo {
+ // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'const FOO: usize = 13usize;'
+ // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
+ const FOO: usize = 12 + 1;
+ // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
+ const FOO_NO_DEFAULT: bool;
+ // @!hasraw - FOO_HIDDEN
+ #[doc(hidden)]
+ const FOO_HIDDEN: u8 = 0;
+}
+
+pub struct Bar;
+
+impl Foo for Bar {
+ // @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Foo for Bar'
+ // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
+ const FOO: usize = 12;
+ // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
+ const FOO_NO_DEFAULT: bool = false;
+ // @!hasraw - FOO_HIDDEN
+ #[doc(hidden)]
+ const FOO_HIDDEN: u8 = 0;
+}
+
+impl Bar {
+ // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \
+ // 'const BAR: usize'
+ pub const BAR: usize = 3;
+
+ // @has - '//*[@id="associatedconstant.BAR_ESCAPED"]' \
+ // "const BAR_ESCAPED: &'static str = \"<em>markup</em>\""
+ pub const BAR_ESCAPED: &'static str = "<em>markup</em>";
+}
+
+pub struct Baz<'a, U: 'a, T>(T, &'a [U]);
+
+impl Bar {
+ // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAZ"]' \
+ // "const BAZ: Baz<'static, u8, u32>"
+ pub const BAZ: Baz<'static, u8, u32> = Baz(321, &[1, 2, 3]);
+}
+
+pub fn f(_: &(ToString + 'static)) {}
+
+impl Bar {
+ // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \
+ // "const F: fn(_: &(dyn ToString + 'static))"
+ // FIXME(fmease): Hide default lifetime, render "const F: fn(_: &dyn ToString)"
+ pub const F: fn(_: &(ToString + 'static)) = f;
+}
+
+impl Bar {
+ // @!hasraw assoc_consts/struct.Bar.html 'BAR_PRIVATE'
+ const BAR_PRIVATE: char = 'a';
+ // @!hasraw assoc_consts/struct.Bar.html 'BAR_HIDDEN'
+ #[doc(hidden)]
+ pub const BAR_HIDDEN: &'static str = "a";
+}
+
+// @has assoc_consts/trait.Qux.html
+pub trait Qux {
+ // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
+ /// Docs for QUX0 in trait.
+ const QUX0: u8;
+ // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX1 in trait."
+ /// Docs for QUX1 in trait.
+ const QUX1: i8;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT12 in trait."
+ /// Docs for QUX_DEFAULT12 in trait.
+ const QUX_DEFAULT0: u16 = 1;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in trait."
+ /// Docs for QUX_DEFAULT1 in trait.
+ const QUX_DEFAULT1: i16 = 2;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32'
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait."
+ /// Docs for QUX_DEFAULT2 in trait.
+ const QUX_DEFAULT2: u32 = 3;
+}
+
+// @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Qux for Bar'
+impl Qux for Bar {
+ // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
+ /// Docs for QUX0 in trait.
+ const QUX0: u8 = 4;
+ // @has - '//*[@id="associatedconstant.QUX1"]' 'const QUX1: i8'
+ // @has - '//*[@class="docblock"]' "Docs for QUX1 in impl."
+ /// Docs for QUX1 in impl.
+ const QUX1: i8 = 5;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
+ // @has - '//div[@class="impl-items"]//*[@class="docblock"]' "Docs for QUX_DEFAULT12 in trait."
+ const QUX_DEFAULT0: u16 = 6;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
+ // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in impl."
+ /// Docs for QUX_DEFAULT1 in impl.
+ const QUX_DEFAULT1: i16 = 7;
+ // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32'
+ // @has - '//div[@class="impl-items"]//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait."
+}
diff --git a/tests/rustdoc/assoc-item-cast.rs b/tests/rustdoc/assoc-item-cast.rs
new file mode 100644
index 000000000..ab9702a24
--- /dev/null
+++ b/tests/rustdoc/assoc-item-cast.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+pub trait Expression {
+ type SqlType;
+}
+
+pub trait AsExpression<T> {
+ type Expression: Expression<SqlType = T>;
+ fn as_expression(self) -> Self::Expression;
+}
+
+// @has foo/type.AsExprOf.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
+pub type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;
diff --git a/tests/rustdoc/assoc-types.rs b/tests/rustdoc/assoc-types.rs
new file mode 100644
index 000000000..de36c8ffe
--- /dev/null
+++ b/tests/rustdoc/assoc-types.rs
@@ -0,0 +1,37 @@
+#![crate_type="lib"]
+
+// @has assoc_types/trait.Index.html
+pub trait Index<I: ?Sized> {
+ // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized'
+ type Output: ?Sized;
+ // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]' \
+ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output"
+ // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]//a[@href="trait.Index.html#associatedtype.Output"]' \
+ // "Output"
+ fn index<'a>(&'a self, index: I) -> &'a Self::Output;
+}
+
+// @has assoc_types/fn.use_output.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '-> &T::Output'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
+ obj.index(index)
+}
+
+pub trait Feed {
+ type Input;
+}
+
+// @has assoc_types/fn.use_input.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'T::Input'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
+
+// @has assoc_types/fn.cmp_input.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where T::Input: PartialEq<U::Input>'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
+ where T::Input: PartialEq<U::Input>
+{
+ a == b
+}
diff --git a/tests/rustdoc/associated-consts.rs b/tests/rustdoc/associated-consts.rs
new file mode 100644
index 000000000..adb155bb5
--- /dev/null
+++ b/tests/rustdoc/associated-consts.rs
@@ -0,0 +1,51 @@
+#![crate_name = "foo"]
+
+pub trait Trait {
+ const FOO: u32 = 12;
+
+ fn foo();
+}
+
+pub struct Bar;
+
+// @has 'foo/struct.Bar.html'
+// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
+// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
+impl Trait for Bar {
+ const FOO: u32 = 1;
+
+ fn foo() {}
+}
+
+pub enum Foo {
+ A,
+}
+
+// @has 'foo/enum.Foo.html'
+// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
+// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
+impl Trait for Foo {
+ const FOO: u32 = 1;
+
+ fn foo() {}
+}
+
+pub struct Baz;
+
+// @has 'foo/struct.Baz.html'
+// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
+impl Baz {
+ pub const FOO: u32 = 42;
+}
+
+pub enum Quux {
+ B,
+}
+
+// @has 'foo/enum.Quux.html'
+// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
+impl Quux {
+ pub const FOO: u32 = 42;
+}
diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs
new file mode 100644
index 000000000..fb7ebb5f8
--- /dev/null
+++ b/tests/rustdoc/async-fn.rs
@@ -0,0 +1,95 @@
+// edition:2018
+// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option<Foo>'
+pub async fn foo() -> Option<Foo> {
+ None
+}
+
+// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+pub async fn bar(a: i32, b: i32) -> i32 {
+ 0
+}
+
+// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz<T>(a: T) -> T'
+pub async fn baz<T>(a: T) -> T {
+ a
+}
+
+// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
+pub async unsafe fn qux() -> char {
+ '⚠'
+}
+
+// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
+pub async fn mut_args(mut a: usize) {}
+
+// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_ref(x: i32)'
+pub async fn mut_ref(ref mut x: i32) {}
+
+trait Bar {}
+
+impl Bar for () {}
+
+// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn quux() -> impl Bar'
+pub async fn quux() -> impl Bar {
+ ()
+}
+
+// @has async_fn/struct.Foo.html
+// @matches - '//h4[@class="code-header"]' 'pub async fn f\(\)$'
+// @matches - '//h4[@class="code-header"]' 'pub async unsafe fn g\(\)$'
+// @matches - '//h4[@class="code-header"]' 'pub async fn mut_self\(self, first: usize\)$'
+pub struct Foo;
+
+impl Foo {
+ pub async fn f() {}
+ pub async unsafe fn g() {}
+ pub async fn mut_self(mut self, mut first: usize) {}
+}
+
+pub trait Pattern<'a> {}
+
+pub trait Trait<const N: usize> {}
+// @has async_fn/fn.const_generics.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
+pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
+
+// test that elided lifetimes are properly elided and not displayed as `'_`
+// regression test for #63037
+// @has async_fn/fn.elided.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn elided(foo: &str) -> &str'
+pub async fn elided(foo: &str) -> &str {}
+// This should really be shown as written, but for implementation reasons it's difficult.
+// See `impl Clean for TyKind::Ref`.
+// @has async_fn/fn.user_elided.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
+pub async fn user_elided(foo: &'_ str) -> &str {}
+// @has async_fn/fn.static_trait.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
+pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
+// @has async_fn/fn.lifetime_for_trait.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
+pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
+// @has async_fn/fn.elided_in_input_trait.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
+
+struct AsyncFdReadyGuard<'a, T> { x: &'a T }
+
+impl Foo {
+ // @has async_fn/struct.Foo.html
+ // @has - '//*[@class="method has-srclink"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>'
+ pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {}
+ // taken from `tokio` as an example of a method that was particularly bad before
+ // @has - '//*[@class="method has-srclink"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
+ pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {}
+ // @has - '//*[@class="method has-srclink"]' "pub async fn mut_self(&mut self)"
+ pub async fn mut_self(&mut self) {}
+}
+
+// test named lifetimes, just in case
+// @has async_fn/fn.named.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
+// @has async_fn/fn.named_trait.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
diff --git a/tests/rustdoc/async-move-doctest.rs b/tests/rustdoc/async-move-doctest.rs
new file mode 100644
index 000000000..2ba61388c
--- /dev/null
+++ b/tests/rustdoc/async-move-doctest.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test
+// edition:2018
+
+// Prior to setting the default edition for the doctest pre-parser,
+// this doctest would fail due to a fatal parsing error.
+// see https://github.com/rust-lang/rust/issues/59313
+
+//! ```
+//! fn foo() {
+//! drop(async move {});
+//! }
+//! ```
diff --git a/tests/rustdoc/async-trait-sig.rs b/tests/rustdoc/async-trait-sig.rs
new file mode 100644
index 000000000..2578bc8f7
--- /dev/null
+++ b/tests/rustdoc/async-trait-sig.rs
@@ -0,0 +1,14 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+ // @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn bar() -> i32"
+ async fn bar() -> i32;
+
+ // @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn baz() -> i32"
+ async fn baz() -> i32 {
+ 1
+ }
+}
diff --git a/tests/rustdoc/async-trait.rs b/tests/rustdoc/async-trait.rs
new file mode 100644
index 000000000..a473e4674
--- /dev/null
+++ b/tests/rustdoc/async-trait.rs
@@ -0,0 +1,16 @@
+// aux-build:async-trait-dep.rs
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+extern crate async_trait_dep;
+
+pub struct Oink {}
+
+// @has 'async_trait/struct.Oink.html' '//h4[@class="code-header"]' "async fn woof()"
+impl async_trait_dep::Meow for Oink {
+ async fn woof() {
+ todo!()
+ }
+}
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
new file mode 100644
index 000000000..36e10923c
--- /dev/null
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+
+// @has 'foo/fn.f.html'
+// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
+#[export_name = "\
+f"]
+pub fn f() {}
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
new file mode 100644
index 000000000..70e2e5c29
--- /dev/null
+++ b/tests/rustdoc/attributes.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
+#[no_mangle]
+pub extern "C" fn f() {}
+
+// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
+#[export_name = "bar"]
+pub extern "C" fn g() {}
+
+// @has foo/struct.Repr.html '//div[@class="item-decl"]' '#[repr(C, align(8))]'
+#[repr(C, align(8))]
+pub struct Repr;
diff --git a/tests/rustdoc/auto-impl-for-trait.rs b/tests/rustdoc/auto-impl-for-trait.rs
new file mode 100644
index 000000000..bc658fbfc
--- /dev/null
+++ b/tests/rustdoc/auto-impl-for-trait.rs
@@ -0,0 +1,16 @@
+// Test for https://github.com/rust-lang/rust/issues/48463 issue.
+
+use std::any::Any;
+use std::ops::Deref;
+
+pub struct AnyValue {
+ val: Box<Any>,
+}
+
+impl Deref for AnyValue {
+ type Target = Any;
+
+ fn deref(&self) -> &Any {
+ &*self.val
+ }
+}
diff --git a/tests/rustdoc/auto-impl-primitive.rs b/tests/rustdoc/auto-impl-primitive.rs
new file mode 100644
index 000000000..172333d44
--- /dev/null
+++ b/tests/rustdoc/auto-impl-primitive.rs
@@ -0,0 +1,10 @@
+#![feature(rustdoc_internals)]
+
+#![crate_name = "foo"]
+
+pub use std::fs::File;
+
+// @has 'foo/primitive.i16.html' '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementation'
+#[doc(primitive = "i16")]
+/// I love poneys!
+mod prim {}
diff --git a/tests/rustdoc/auto-trait-not-send.rs b/tests/rustdoc/auto-trait-not-send.rs
new file mode 100644
index 000000000..661d905ab
--- /dev/null
+++ b/tests/rustdoc/auto-trait-not-send.rs
@@ -0,0 +1,8 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Foo.html'
+// @has - '//*[@id="impl-Send-for-Foo"]' 'impl !Send for Foo'
+// @has - '//*[@id="impl-Sync-for-Foo"]' 'impl !Sync for Foo'
+pub struct Foo(*const i8);
+pub trait Whatever: Send {}
+impl<T: Send + ?Sized> Whatever for T {}
diff --git a/tests/rustdoc/auto-traits.rs b/tests/rustdoc/auto-traits.rs
new file mode 100644
index 000000000..93d4bf2f6
--- /dev/null
+++ b/tests/rustdoc/auto-traits.rs
@@ -0,0 +1,13 @@
+// aux-build:auto-traits.rs
+
+#![feature(auto_traits)]
+
+#![crate_name = "foo"]
+
+extern crate auto_traits;
+
+// @has 'foo/trait.Foo.html' '//pre' 'pub unsafe auto trait Foo'
+pub unsafe auto trait Foo {}
+
+// @has 'foo/trait.Bar.html' '//pre' 'pub unsafe auto trait Bar'
+pub use auto_traits::Bar;
diff --git a/tests/rustdoc/auto_aliases.rs b/tests/rustdoc/auto_aliases.rs
new file mode 100644
index 000000000..a047c76b6
--- /dev/null
+++ b/tests/rustdoc/auto_aliases.rs
@@ -0,0 +1,6 @@
+#![feature(auto_traits)]
+
+// @has auto_aliases/trait.Bar.html '//*[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo'
+pub struct Foo;
+
+pub auto trait Bar {}
diff --git a/tests/rustdoc/auxiliary/all-item-types.rs b/tests/rustdoc/auxiliary/all-item-types.rs
new file mode 100644
index 000000000..f94bd9987
--- /dev/null
+++ b/tests/rustdoc/auxiliary/all-item-types.rs
@@ -0,0 +1,22 @@
+#![feature(extern_types)]
+
+pub mod foo_mod {}
+extern "C" {
+ pub fn foo_ffn();
+ pub static FOO_FSTATIC: FooStruct;
+ pub type FooFType;
+}
+pub fn foo_fn() {}
+pub trait FooTrait {}
+pub struct FooStruct;
+pub enum FooEnum {}
+pub union FooUnion {
+ x: (),
+}
+pub type FooType = FooStruct;
+pub static FOO_STATIC: FooStruct = FooStruct;
+pub const FOO_CONSTANT: FooStruct = FooStruct;
+#[macro_export]
+macro_rules! foo_macro {
+ () => ();
+}
diff --git a/tests/rustdoc/auxiliary/async-trait-dep.rs b/tests/rustdoc/auxiliary/async-trait-dep.rs
new file mode 100644
index 000000000..10a55dd02
--- /dev/null
+++ b/tests/rustdoc/auxiliary/async-trait-dep.rs
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Meow {
+ /// Who's a good dog?
+ async fn woof();
+}
diff --git a/tests/rustdoc/auxiliary/auto-traits.rs b/tests/rustdoc/auxiliary/auto-traits.rs
new file mode 100644
index 000000000..84976c73b
--- /dev/null
+++ b/tests/rustdoc/auxiliary/auto-traits.rs
@@ -0,0 +1,3 @@
+#![feature(auto_traits)]
+
+pub unsafe auto trait Bar {}
diff --git a/tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs b/tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs
new file mode 100644
index 000000000..3baf8a6c0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs
@@ -0,0 +1,19 @@
+pub trait Tr {
+ type VisibleAssoc;
+ #[doc(hidden)]
+ type HiddenAssoc;
+
+ const VISIBLE_ASSOC: ();
+ #[doc(hidden)]
+ const HIDDEN_ASSOC: ();
+}
+
+pub struct Ty;
+
+impl Tr for Ty {
+ type VisibleAssoc = ();
+ type HiddenAssoc = ();
+
+ const VISIBLE_ASSOC: () = ();
+ const HIDDEN_ASSOC: () = ();
+}
diff --git a/tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs b/tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs
new file mode 100644
index 000000000..159531222
--- /dev/null
+++ b/tests/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs
@@ -0,0 +1,5 @@
+#[doc(hidden)]
+pub enum HiddenType {}
+
+#[doc(hidden)]
+pub trait HiddenTrait {}
diff --git a/tests/rustdoc/auxiliary/elided-lifetime.rs b/tests/rustdoc/auxiliary/elided-lifetime.rs
new file mode 100644
index 000000000..4f2c93379
--- /dev/null
+++ b/tests/rustdoc/auxiliary/elided-lifetime.rs
@@ -0,0 +1,11 @@
+#![crate_name = "bar"]
+
+pub struct Ref<'a>(&'a u32);
+
+pub fn test5(a: &u32) -> Ref {
+ Ref(a)
+}
+
+pub fn test6(a: &u32) -> Ref<'_> {
+ Ref(a)
+}
diff --git a/tests/rustdoc/auxiliary/empty.rs b/tests/rustdoc/auxiliary/empty.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/tests/rustdoc/auxiliary/empty.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/rustdoc/auxiliary/enum-primitive.rs b/tests/rustdoc/auxiliary/enum-primitive.rs
new file mode 100644
index 000000000..ed1da253a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/enum-primitive.rs
@@ -0,0 +1,207 @@
+// Copyright (c) 2015 Anders Kaseorg <andersk@mit.edu>
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// “Software”), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+//! This crate exports a macro `enum_from_primitive!` that wraps an
+//! `enum` declaration and automatically adds an implementation of
+//! `num::FromPrimitive` (reexported here), to allow conversion from
+//! primitive integers to the enum. It therefore provides an
+//! alternative to the built-in `#[derive(FromPrimitive)]`, which
+//! requires the unstable `std::num::FromPrimitive` and is disabled in
+//! Rust 1.0.
+//!
+//! # Example
+//!
+//! ```
+//! #[macro_use] extern crate enum_primitive;
+//! extern crate num_traits;
+//! use num_traits::FromPrimitive;
+//!
+//! enum_from_primitive! {
+//! #[derive(Debug, PartialEq)]
+//! enum FooBar {
+//! Foo = 17,
+//! Bar = 42,
+//! Baz,
+//! }
+//! }
+//!
+//! fn main() {
+//! assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
+//! assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
+//! assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
+//! assert_eq!(FooBar::from_i32(91), None);
+//! }
+//! ```
+
+pub mod num_traits {
+ pub trait FromPrimitive: Sized {
+ fn from_i64(n: i64) -> Option<Self>;
+ fn from_u64(n: u64) -> Option<Self>;
+ }
+}
+
+pub use std::option::Option;
+pub use num_traits::FromPrimitive;
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+macro_rules! enum_from_primitive_impl_ty {
+ ($meth:ident, $ty:ty, $name:ident, $( $variant:ident )*) => {
+ #[allow(non_upper_case_globals, unused)]
+ fn $meth(n: $ty) -> $crate::Option<Self> {
+ $( if n == $name::$variant as $ty {
+ $crate::Option::Some($name::$variant)
+ } else )* {
+ $crate::Option::None
+ }
+ }
+ };
+}
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl_ty)]
+macro_rules! enum_from_primitive_impl {
+ ($name:ident, $( $variant:ident )*) => {
+ impl $crate::FromPrimitive for $name {
+ enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant )* }
+ enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant )* }
+ }
+ };
+}
+
+/// Wrap this macro around an `enum` declaration to get an
+/// automatically generated implementation of `num::FromPrimitive`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl)]
+macro_rules! enum_from_primitive {
+ (
+ $( #[$enum_attr:meta] )*
+ enum $name:ident {
+ $( $( #[$variant_attr:meta] )* $variant:ident ),+
+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ enum $name {
+ $( $( #[$variant_attr] )* $variant ),+
+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+ }
+ enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ enum $name:ident {
+ $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ enum $name {
+ $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+ }
+ enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ enum $name:ident {
+ $( $( #[$variant_attr:meta] )* $variant:ident ),+
+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ enum $name {
+ $( $( #[$variant_attr] )* $variant ),+
+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+ }
+ enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ enum $name:ident {
+ $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ enum $name {
+ $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+ }
+ enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ pub enum $name:ident {
+ $( $( #[$variant_attr:meta] )* $variant:ident ),+
+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ pub enum $name {
+ $( $( #[$variant_attr] )* $variant ),+
+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+ }
+ enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ pub enum $name:ident {
+ $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ pub enum $name {
+ $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+ }
+ enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ pub enum $name:ident {
+ $( $( #[$variant_attr:meta] )* $variant:ident ),+
+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ pub enum $name {
+ $( $( #[$variant_attr] )* $variant ),+
+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+ }
+ enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+ };
+
+ (
+ $( #[$enum_attr:meta] )*
+ pub enum $name:ident {
+ $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+ }
+ ) => {
+ $( #[$enum_attr] )*
+ pub enum $name {
+ $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+ }
+ enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+ };
+}
diff --git a/tests/rustdoc/auxiliary/extern-impl-trait.rs b/tests/rustdoc/auxiliary/extern-impl-trait.rs
new file mode 100644
index 000000000..dbd543930
--- /dev/null
+++ b/tests/rustdoc/auxiliary/extern-impl-trait.rs
@@ -0,0 +1,27 @@
+pub trait Foo {
+ type Associated;
+}
+
+pub struct X;
+pub struct Y;
+
+
+impl Foo for X {
+ type Associated = ();
+}
+
+impl Foo for Y {
+ type Associated = ();
+}
+
+impl X {
+ pub fn returns_sized<'a>(&'a self) -> impl Foo<Associated=()> + 'a {
+ X
+ }
+}
+
+impl Y {
+ pub fn returns_unsized<'a>(&'a self) -> Box<impl ?Sized + Foo<Associated=()> + 'a> {
+ Box::new(X)
+ }
+}
diff --git a/tests/rustdoc/auxiliary/extern-links.rs b/tests/rustdoc/auxiliary/extern-links.rs
new file mode 100644
index 000000000..4a835673a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/extern-links.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/tests/rustdoc/auxiliary/external-cross-doc.md b/tests/rustdoc/auxiliary/external-cross-doc.md
new file mode 100644
index 000000000..d3c853265
--- /dev/null
+++ b/tests/rustdoc/auxiliary/external-cross-doc.md
@@ -0,0 +1,4 @@
+# Cross-crate imported docs
+
+This file is to make sure `#[doc = include_str!("file.md")]` works when you re-export an item with included
+docs.
diff --git a/tests/rustdoc/auxiliary/external-cross.rs b/tests/rustdoc/auxiliary/external-cross.rs
new file mode 100644
index 000000000..5de63cdab
--- /dev/null
+++ b/tests/rustdoc/auxiliary/external-cross.rs
@@ -0,0 +1,3 @@
+#[deny(missing_docs)]
+#[doc = include_str!("external-cross-doc.md")]
+pub struct NeedMoreDocs;
diff --git a/tests/rustdoc/auxiliary/external-doc.md b/tests/rustdoc/auxiliary/external-doc.md
new file mode 100644
index 000000000..babde0a05
--- /dev/null
+++ b/tests/rustdoc/auxiliary/external-doc.md
@@ -0,0 +1,3 @@
+# External Docs
+
+This file is here to test the `#[doc = include_str!("file")]` attribute.
diff --git a/tests/rustdoc/auxiliary/external-macro-src.rs b/tests/rustdoc/auxiliary/external-macro-src.rs
new file mode 100644
index 000000000..ce20ca5c9
--- /dev/null
+++ b/tests/rustdoc/auxiliary/external-macro-src.rs
@@ -0,0 +1,15 @@
+// compile-flags:--remap-path-prefix={{src-base}}=/does-not-exist
+
+#![doc(html_root_url = "https://example.com/")]
+
+#[macro_export]
+macro_rules! make_foo {
+ () => {
+ pub struct Foo;
+ impl Foo {
+ pub fn new() -> Foo {
+ Foo
+ }
+ }
+ }
+}
diff --git a/tests/rustdoc/auxiliary/html_root.rs b/tests/rustdoc/auxiliary/html_root.rs
new file mode 100644
index 000000000..4eb0b700f
--- /dev/null
+++ b/tests/rustdoc/auxiliary/html_root.rs
@@ -0,0 +1,2 @@
+#![doc(html_root_url="https://example.com/html_root")]
+pub fn foo() {}
diff --git a/tests/rustdoc/auxiliary/incoherent-impl-types.rs b/tests/rustdoc/auxiliary/incoherent-impl-types.rs
new file mode 100644
index 000000000..fc51e42e5
--- /dev/null
+++ b/tests/rustdoc/auxiliary/incoherent-impl-types.rs
@@ -0,0 +1,7 @@
+#![feature(rustc_attrs)]
+
+#[rustc_has_incoherent_inherent_impls]
+pub trait FooTrait {}
+
+#[rustc_has_incoherent_inherent_impls]
+pub struct FooStruct;
diff --git a/tests/rustdoc/auxiliary/inline-default-methods.rs b/tests/rustdoc/auxiliary/inline-default-methods.rs
new file mode 100644
index 000000000..8a636f449
--- /dev/null
+++ b/tests/rustdoc/auxiliary/inline-default-methods.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Foo {
+ fn bar(&self);
+ fn foo(&mut self) {}
+}
diff --git a/tests/rustdoc/auxiliary/issue-100204-aux.rs b/tests/rustdoc/auxiliary/issue-100204-aux.rs
new file mode 100644
index 000000000..df1b59069
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-100204-aux.rs
@@ -0,0 +1,13 @@
+#![crate_name="first"]
+
+pub mod prelude {
+ pub use crate::Bot;
+}
+
+pub struct Bot;
+
+impl Bot {
+ pub fn new() -> Bot {
+ Bot
+ }
+}
diff --git a/tests/rustdoc/auxiliary/issue-13698.rs b/tests/rustdoc/auxiliary/issue-13698.rs
new file mode 100644
index 000000000..a65ebfe36
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-13698.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Foo {
+ #[doc(hidden)]
+ fn foo(&self) {}
+}
+
+impl Foo for i32 {}
diff --git a/tests/rustdoc/auxiliary/issue-15318.rs b/tests/rustdoc/auxiliary/issue-15318.rs
new file mode 100644
index 000000000..695fa58ef
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-15318.rs
@@ -0,0 +1,16 @@
+// no-prefer-dynamic
+// compile-flags: -Cmetadata=aux
+#![crate_type = "rlib"]
+#![doc(html_root_url = "http://example.com/")]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
+
+/// dox
+#[doc(primitive = "pointer")]
+pub mod ptr {}
diff --git a/tests/rustdoc/auxiliary/issue-17476.rs b/tests/rustdoc/auxiliary/issue-17476.rs
new file mode 100644
index 000000000..80c915eb7
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-17476.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Cmetadata=aux
+
+#![doc(html_root_url = "http://example.com")]
+
+pub trait Foo {
+ fn foo(&self) {}
+}
diff --git a/tests/rustdoc/auxiliary/issue-19190-3.rs b/tests/rustdoc/auxiliary/issue-19190-3.rs
new file mode 100644
index 000000000..8c526a89a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-19190-3.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Cmetadata=aux
+
+use std::ops::Deref;
+
+pub struct Foo;
+
+impl Deref for Foo {
+ type Target = String;
+ fn deref(&self) -> &String { loop {} }
+}
+
+pub struct Bar;
+pub struct Baz;
+
+impl Baz {
+ pub fn baz(&self) {}
+ pub fn static_baz() {}
+}
+
+impl Deref for Bar {
+ type Target = Baz;
+ fn deref(&self) -> &Baz { loop {} }
+}
diff --git a/tests/rustdoc/auxiliary/issue-20646.rs b/tests/rustdoc/auxiliary/issue-20646.rs
new file mode 100644
index 000000000..8e16f2de0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-20646.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Trait {
+ type Output;
+}
+
+pub fn fun<T>(_: T) where T: Trait<Output=i32> {}
diff --git a/tests/rustdoc/auxiliary/issue-20727.rs b/tests/rustdoc/auxiliary/issue-20727.rs
new file mode 100644
index 000000000..7ffc1985b
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-20727.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Deref {
+ type Target: ?Sized;
+
+ fn deref<'a>(&'a self) -> &'a Self::Target;
+}
+
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+
+pub trait Bar {}
+pub trait Deref2 {
+ type Target: Bar;
+
+ fn deref(&self) -> Self::Target;
+}
+
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
+ fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
+}
diff --git a/tests/rustdoc/auxiliary/issue-21092.rs b/tests/rustdoc/auxiliary/issue-21092.rs
new file mode 100644
index 000000000..51ab7de1c
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-21092.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Foo {
+ type Bar;
+ fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {
+ type Bar = i32;
+}
diff --git a/tests/rustdoc/auxiliary/issue-21801.rs b/tests/rustdoc/auxiliary/issue-21801.rs
new file mode 100644
index 000000000..732612ff0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-21801.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Cmetadata=aux
+
+pub struct Foo;
+
+impl Foo {
+ pub fn new<F>(f: F) -> Foo where F: FnMut() -> i32 {
+ loop {}
+ }
+}
diff --git a/tests/rustdoc/auxiliary/issue-22025.rs b/tests/rustdoc/auxiliary/issue-22025.rs
new file mode 100644
index 000000000..5346c0e92
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-22025.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Cmetadata=aux
+
+pub mod foo {
+
+ pub trait Foo {}
+ pub struct Bar;
+
+ impl Foo for Bar {}
+
+}
diff --git a/tests/rustdoc/auxiliary/issue-23207-1.rs b/tests/rustdoc/auxiliary/issue-23207-1.rs
new file mode 100644
index 000000000..8531d5f1a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-23207-1.rs
@@ -0,0 +1,3 @@
+pub mod fmt {
+ pub struct Error;
+}
diff --git a/tests/rustdoc/auxiliary/issue-23207-2.rs b/tests/rustdoc/auxiliary/issue-23207-2.rs
new file mode 100644
index 000000000..b92b16653
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-23207-2.rs
@@ -0,0 +1,5 @@
+extern crate issue_23207_1;
+
+pub mod fmt {
+ pub use issue_23207_1::fmt::Error;
+}
diff --git a/tests/rustdoc/auxiliary/issue-26606-macro.rs b/tests/rustdoc/auxiliary/issue-26606-macro.rs
new file mode 100644
index 000000000..d60d32526
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-26606-macro.rs
@@ -0,0 +1,4 @@
+#[macro_export]
+macro_rules! make_item (
+ ($name: ident) => (pub const $name: usize = 42;)
+);
diff --git a/tests/rustdoc/auxiliary/issue-27362-aux.rs b/tests/rustdoc/auxiliary/issue-27362-aux.rs
new file mode 100644
index 000000000..077bdc33e
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-27362-aux.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Cmetadata=aux
+
+pub const fn foo() {}
+pub const unsafe fn bar() {}
+
+pub struct Foo;
+
+impl Foo {
+ pub const unsafe fn baz() {}
+}
diff --git a/tests/rustdoc/auxiliary/issue-28927-1.rs b/tests/rustdoc/auxiliary/issue-28927-1.rs
new file mode 100644
index 000000000..688c73428
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-28927-1.rs
@@ -0,0 +1,4 @@
+mod detail {
+ pub extern crate issue_28927_2 as inner2;
+}
+pub use detail::inner2 as bar;
diff --git a/tests/rustdoc/auxiliary/issue-28927-2.rs b/tests/rustdoc/auxiliary/issue-28927-2.rs
new file mode 100644
index 000000000..7c0937fce
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-28927-2.rs
@@ -0,0 +1 @@
+pub struct Baz;
diff --git a/tests/rustdoc/auxiliary/issue-29584.rs b/tests/rustdoc/auxiliary/issue-29584.rs
new file mode 100644
index 000000000..a9b8796c0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-29584.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Cmetadata=aux
+
+pub struct Foo;
+
+#[doc(hidden)]
+mod bar {
+ trait Bar {}
+
+ impl Bar for ::Foo {}
+}
diff --git a/tests/rustdoc/auxiliary/issue-30109-1.rs b/tests/rustdoc/auxiliary/issue-30109-1.rs
new file mode 100644
index 000000000..ca05a6a90
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-30109-1.rs
@@ -0,0 +1 @@
+pub struct Bar;
diff --git a/tests/rustdoc/auxiliary/issue-34274.rs b/tests/rustdoc/auxiliary/issue-34274.rs
new file mode 100644
index 000000000..c46660579
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-34274.rs
@@ -0,0 +1,3 @@
+extern "C" {
+ pub fn extern_c_fn();
+}
diff --git a/tests/rustdoc/auxiliary/issue-36031.rs b/tests/rustdoc/auxiliary/issue-36031.rs
new file mode 100644
index 000000000..da688139e
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-36031.rs
@@ -0,0 +1,9 @@
+pub trait Foo {
+ const FOO: usize;
+}
+
+pub struct Bar;
+
+impl Bar {
+ pub const BAR: usize = 3;
+}
diff --git a/tests/rustdoc/auxiliary/issue-40936.rs b/tests/rustdoc/auxiliary/issue-40936.rs
new file mode 100644
index 000000000..b921e5201
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-40936.rs
@@ -0,0 +1,5 @@
+pub mod outermod {
+ pub mod innermod {
+ pub use super::*;
+ }
+}
diff --git a/tests/rustdoc/auxiliary/issue-46727.rs b/tests/rustdoc/auxiliary/issue-46727.rs
new file mode 100644
index 000000000..30dccfa77
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-46727.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Foo {}
+
+pub struct Bar<T> { x: T }
+
+impl<T> Foo for Bar<[T; 1 + 1 + 1]> {}
diff --git a/tests/rustdoc/auxiliary/issue-48414.rs b/tests/rustdoc/auxiliary/issue-48414.rs
new file mode 100644
index 000000000..f442ac722
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-48414.rs
@@ -0,0 +1,5 @@
+/// Woah, this trait links to [OtherTrait](OtherTrait)!
+pub trait SomeTrait {}
+
+/// Woah, this trait links to [SomeTrait](SomeTrait)!
+pub trait OtherTrait {}
diff --git a/tests/rustdoc/auxiliary/issue-53689.rs b/tests/rustdoc/auxiliary/issue-53689.rs
new file mode 100644
index 000000000..5003c2c00
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-53689.rs
@@ -0,0 +1 @@
+pub struct MyStruct;
diff --git a/tests/rustdoc/auxiliary/issue-57180.rs b/tests/rustdoc/auxiliary/issue-57180.rs
new file mode 100644
index 000000000..4e2f4b87c
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-57180.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Trait {
+}
+
+pub struct Struct<F>
+{
+ _p: ::std::marker::PhantomData<F>,
+}
+
+impl<F: Fn() -> u32>
+Trait for Struct<F>
+ where
+ F: Fn() -> u32,
+{
+}
diff --git a/tests/rustdoc/auxiliary/issue-61592.rs b/tests/rustdoc/auxiliary/issue-61592.rs
new file mode 100644
index 000000000..6e16a4caf
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-61592.rs
@@ -0,0 +1,4 @@
+#![crate_name = "foo"]
+
+pub trait FooTrait {}
+pub struct FooStruct;
diff --git a/tests/rustdoc/auxiliary/issue-73061.rs b/tests/rustdoc/auxiliary/issue-73061.rs
new file mode 100644
index 000000000..e05a3bc6d
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-73061.rs
@@ -0,0 +1,17 @@
+//edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Foo {
+ type X: std::future::Future<Output = ()>;
+ fn x(&self) -> Self::X;
+}
+
+pub struct F;
+
+impl Foo for F {
+ type X = impl std::future::Future<Output = ()>;
+ fn x(&self) -> Self::X {
+ async {}
+ }
+}
diff --git a/tests/rustdoc/auxiliary/issue-85454.rs b/tests/rustdoc/auxiliary/issue-85454.rs
new file mode 100644
index 000000000..5143968bb
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-85454.rs
@@ -0,0 +1,17 @@
+// @has issue_85454/trait.FromResidual.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+pub trait FromResidual<R = <Self as Try>::Residual> {
+ fn from_residual(residual: R) -> Self;
+}
+
+pub trait Try: FromResidual {
+ type Output;
+ type Residual;
+ fn from_output(output: Self::Output) -> Self;
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+}
+
+pub enum ControlFlow<B, C = ()> {
+ Continue(C),
+ Break(B),
+}
diff --git a/tests/rustdoc/auxiliary/issue-86620-1.rs b/tests/rustdoc/auxiliary/issue-86620-1.rs
new file mode 100644
index 000000000..f6debf6fb
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-86620-1.rs
@@ -0,0 +1,11 @@
+#![crate_name = "issue_86620_1"]
+
+pub trait VZip {
+ fn vzip() -> usize;
+}
+
+impl<T> VZip for T {
+ fn vzip() -> usize {
+ 0
+ }
+}
diff --git a/tests/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs b/tests/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs
new file mode 100644
index 000000000..4e55e7ed5
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs
@@ -0,0 +1,17 @@
+/// When reexporting this function, make sure the anonymous lifetimes are not rendered.
+///
+/// https://github.com/rust-lang/rust/issues/98697
+pub fn repro<F>()
+where
+ F: Fn(&str),
+{
+ unimplemented!()
+}
+
+pub struct Extra;
+
+pub trait MyTrait<T> {
+ fn run() {}
+}
+
+impl MyTrait<&Extra> for Extra {}
diff --git a/tests/rustdoc/auxiliary/issue-99221-aux.rs b/tests/rustdoc/auxiliary/issue-99221-aux.rs
new file mode 100644
index 000000000..e061e42b2
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-99221-aux.rs
@@ -0,0 +1,20 @@
+pub struct Option;
+impl Option {
+ pub fn unwrap(self) {}
+}
+
+mod macros {
+ use crate::Option;
+ /// [`Option::unwrap`]
+ #[macro_export]
+ macro_rules! print {
+ () => ()
+ }
+}
+
+mod structs {
+ use crate::Option;
+ /// [`Option::unwrap`]
+ pub struct Print;
+}
+pub use structs::Print;
diff --git a/tests/rustdoc/auxiliary/issue-99734-aux.rs b/tests/rustdoc/auxiliary/issue-99734-aux.rs
new file mode 100644
index 000000000..234d55efb
--- /dev/null
+++ b/tests/rustdoc/auxiliary/issue-99734-aux.rs
@@ -0,0 +1,11 @@
+pub struct Option;
+impl Option {
+ pub fn unwrap(self) {}
+}
+
+/// [`Option::unwrap`]
+pub mod task {}
+
+extern "C" {
+ pub fn main() -> std::ffi::c_int;
+}
diff --git a/tests/rustdoc/auxiliary/macro_pub_in_module.rs b/tests/rustdoc/auxiliary/macro_pub_in_module.rs
new file mode 100644
index 000000000..137b12386
--- /dev/null
+++ b/tests/rustdoc/auxiliary/macro_pub_in_module.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![feature(decl_macro)]
+#![crate_name = "external_crate"]
+
+pub mod some_module {
+ /* == Make sure the logic is not affected by a re-export == */
+ mod private {
+ pub macro external_macro() {}
+ }
+
+ pub use private::external_macro;
+}
diff --git a/tests/rustdoc/auxiliary/masked.rs b/tests/rustdoc/auxiliary/masked.rs
new file mode 100644
index 000000000..3d722d5e0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/masked.rs
@@ -0,0 +1,14 @@
+#[derive(Clone)]
+pub struct MaskedStruct;
+
+pub trait MaskedTrait {
+ fn masked_method();
+}
+
+impl MaskedTrait for String {
+ fn masked_method() {}
+}
+
+pub trait MaskedBlanketTrait {}
+
+impl<T> MaskedBlanketTrait for T {}
diff --git a/tests/rustdoc/auxiliary/mod-stackoverflow.rs b/tests/rustdoc/auxiliary/mod-stackoverflow.rs
new file mode 100644
index 000000000..e0b90f180
--- /dev/null
+++ b/tests/rustdoc/auxiliary/mod-stackoverflow.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Cmetadata=aux
+
+pub mod tree {
+ pub use tree;
+}
+
+pub mod tree2 {
+ pub mod prelude {
+ pub use tree2;
+ }
+}
diff --git a/tests/rustdoc/auxiliary/no_html_root.rs b/tests/rustdoc/auxiliary/no_html_root.rs
new file mode 100644
index 000000000..c5c0bc606
--- /dev/null
+++ b/tests/rustdoc/auxiliary/no_html_root.rs
@@ -0,0 +1 @@
+pub fn bar() {}
diff --git a/tests/rustdoc/auxiliary/normalize-assoc-item.rs b/tests/rustdoc/auxiliary/normalize-assoc-item.rs
new file mode 100644
index 000000000..fbd111c30
--- /dev/null
+++ b/tests/rustdoc/auxiliary/normalize-assoc-item.rs
@@ -0,0 +1,12 @@
+#![crate_name = "inner"]
+pub trait MyTrait {
+ type Y;
+}
+
+impl MyTrait for u32 {
+ type Y = i32;
+}
+
+pub fn foo() -> <u32 as MyTrait>::Y {
+ 0
+}
diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/auxiliary/primitive-doc.rs
new file mode 100644
index 000000000..e8da852a5
--- /dev/null
+++ b/tests/rustdoc/auxiliary/primitive-doc.rs
@@ -0,0 +1,9 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![feature(no_core)]
+#![no_core]
+
+#[doc(primitive = "usize")]
+/// This is the built-in type `usize`.
+mod usize {
+}
diff --git a/tests/rustdoc/auxiliary/primitive-reexport.rs b/tests/rustdoc/auxiliary/primitive-reexport.rs
new file mode 100644
index 000000000..b2e9fa43b
--- /dev/null
+++ b/tests/rustdoc/auxiliary/primitive-reexport.rs
@@ -0,0 +1,8 @@
+// compile-flags: --emit metadata --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+
+pub mod bar {
+ pub use bool;
+ pub use char as my_char;
+}
diff --git a/tests/rustdoc/auxiliary/pub-extern-crate.rs b/tests/rustdoc/auxiliary/pub-extern-crate.rs
new file mode 100644
index 000000000..8c89c8d6c
--- /dev/null
+++ b/tests/rustdoc/auxiliary/pub-extern-crate.rs
@@ -0,0 +1,2 @@
+#![crate_name = "inner"]
+pub struct SomeStruct;
diff --git a/tests/rustdoc/auxiliary/pub-use-extern-macros.rs b/tests/rustdoc/auxiliary/pub-use-extern-macros.rs
new file mode 100644
index 000000000..7934e0733
--- /dev/null
+++ b/tests/rustdoc/auxiliary/pub-use-extern-macros.rs
@@ -0,0 +1,21 @@
+#![crate_name="macros"]
+
+#[macro_export]
+macro_rules! foo {
+ () => {};
+}
+
+#[macro_export]
+macro_rules! bar {
+ () => {};
+}
+
+#[macro_export]
+macro_rules! baz {
+ () => {};
+}
+
+#[macro_export]
+macro_rules! quux {
+ () => {};
+}
diff --git a/tests/rustdoc/auxiliary/real_gimli.rs b/tests/rustdoc/auxiliary/real_gimli.rs
new file mode 100644
index 000000000..80d5c4ba8
--- /dev/null
+++ b/tests/rustdoc/auxiliary/real_gimli.rs
@@ -0,0 +1,13 @@
+// aux-build:realcore.rs
+
+#![crate_name = "real_gimli"]
+#![feature(staged_api, extremely_unstable)]
+#![unstable(feature = "rustc_private", issue = "none")]
+
+extern crate realcore;
+
+#[unstable(feature = "rustc_private", issue = "none")]
+pub struct EndianSlice;
+
+#[unstable(feature = "rustc_private", issue = "none")]
+impl realcore::Deref for EndianSlice {}
diff --git a/tests/rustdoc/auxiliary/realcore.rs b/tests/rustdoc/auxiliary/realcore.rs
new file mode 100644
index 000000000..e0a906df0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/realcore.rs
@@ -0,0 +1,15 @@
+#![crate_name = "realcore"]
+#![feature(staged_api)]
+#![unstable(feature = "extremely_unstable", issue = "none")]
+
+#[unstable(feature = "extremely_unstable_foo", issue = "none")]
+pub struct Foo {}
+
+#[unstable(feature = "extremely_unstable_foo", issue = "none")]
+pub trait Join {}
+
+#[unstable(feature = "extremely_unstable_foo", issue = "none")]
+impl Join for Foo {}
+
+#[stable(feature = "faked_deref", since = "1.47.0")]
+pub trait Deref {}
diff --git a/tests/rustdoc/auxiliary/reexp-stripped.rs b/tests/rustdoc/auxiliary/reexp-stripped.rs
new file mode 100644
index 000000000..ccc3dc11f
--- /dev/null
+++ b/tests/rustdoc/auxiliary/reexp-stripped.rs
@@ -0,0 +1,11 @@
+pub use private::Quz;
+pub use hidden::Bar;
+
+mod private {
+ pub struct Quz;
+}
+
+#[doc(hidden)]
+pub mod hidden {
+ pub struct Bar;
+}
diff --git a/tests/rustdoc/auxiliary/reexport-check.rs b/tests/rustdoc/auxiliary/reexport-check.rs
new file mode 100644
index 000000000..672ccb1cf
--- /dev/null
+++ b/tests/rustdoc/auxiliary/reexport-check.rs
@@ -0,0 +1,2 @@
+/// Docs in original
+pub struct S;
diff --git a/tests/rustdoc/auxiliary/reexport-doc-aux.rs b/tests/rustdoc/auxiliary/reexport-doc-aux.rs
new file mode 100644
index 000000000..3400717eb
--- /dev/null
+++ b/tests/rustdoc/auxiliary/reexport-doc-aux.rs
@@ -0,0 +1,5 @@
+pub struct Foo;
+
+impl Foo {
+ pub fn foo() {}
+}
diff --git a/tests/rustdoc/auxiliary/reexports.rs b/tests/rustdoc/auxiliary/reexports.rs
new file mode 100644
index 000000000..4336993a3
--- /dev/null
+++ b/tests/rustdoc/auxiliary/reexports.rs
@@ -0,0 +1,66 @@
+#![feature(decl_macro)]
+
+pub macro addr_of($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_crate($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_super($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_self($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_local($place:expr) {
+ &raw const $place
+}
+
+pub struct Foo;
+pub struct FooCrate;
+pub struct FooSuper;
+pub struct FooSelf;
+pub struct FooLocal;
+
+pub enum Bar { Foo, }
+pub enum BarCrate { Foo, }
+pub enum BarSuper { Foo, }
+pub enum BarSelf { Foo, }
+pub enum BarLocal { Foo, }
+
+pub fn foo() {}
+pub fn foo_crate() {}
+pub fn foo_super() {}
+pub fn foo_self() {}
+pub fn foo_local() {}
+
+pub type Type = i32;
+pub type TypeCrate = i32;
+pub type TypeSuper = i32;
+pub type TypeSelf = i32;
+pub type TypeLocal = i32;
+
+pub union Union {
+ a: i8,
+ b: i8,
+}
+pub union UnionCrate {
+ a: i8,
+ b: i8,
+}
+pub union UnionSuper {
+ a: i8,
+ b: i8,
+}
+pub union UnionSelf {
+ a: i8,
+ b: i8,
+}
+pub union UnionLocal {
+ a: i8,
+ b: i8,
+}
diff --git a/tests/rustdoc/auxiliary/rustdoc-default-impl.rs b/tests/rustdoc/auxiliary/rustdoc-default-impl.rs
new file mode 100644
index 000000000..032db3b25
--- /dev/null
+++ b/tests/rustdoc/auxiliary/rustdoc-default-impl.rs
@@ -0,0 +1,23 @@
+#![feature(auto_traits)]
+
+pub mod bar {
+ use std::marker;
+
+ pub auto trait Bar {}
+
+ pub trait Foo {
+ fn foo(&self) {}
+ }
+
+ impl Foo {
+ pub fn test<T: Bar>(&self) {}
+ }
+
+ pub struct TypeId;
+
+ impl TypeId {
+ pub fn of<T: Bar + ?Sized>() -> TypeId {
+ panic!()
+ }
+ }
+}
diff --git a/tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs b/tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs
new file mode 100644
index 000000000..12934238a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/rustdoc-extern-default-method.rs
@@ -0,0 +1,11 @@
+#![crate_type="lib"]
+
+pub trait Trait {
+ fn provided(&self) {}
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+ fn provided(&self) {}
+}
diff --git a/tests/rustdoc/auxiliary/rustdoc-extern-method.rs b/tests/rustdoc/auxiliary/rustdoc-extern-method.rs
new file mode 100644
index 000000000..e493048d9
--- /dev/null
+++ b/tests/rustdoc/auxiliary/rustdoc-extern-method.rs
@@ -0,0 +1,7 @@
+#![crate_type="lib"]
+#![feature(unboxed_closures)]
+
+pub trait Foo {
+ extern "rust-call" fn foo(&self, _: ()) -> i32;
+ extern "rust-call" fn foo_(&self, _: ()) -> i32 { 0 }
+}
diff --git a/tests/rustdoc/auxiliary/rustdoc-ffi.rs b/tests/rustdoc/auxiliary/rustdoc-ffi.rs
new file mode 100644
index 000000000..b74d190b5
--- /dev/null
+++ b/tests/rustdoc/auxiliary/rustdoc-ffi.rs
@@ -0,0 +1,6 @@
+#![crate_type="lib"]
+
+extern "C" {
+ // @has lib/fn.foreigner.html //pre 'pub unsafe fn foreigner(cold_as_ice: u32)'
+ pub fn foreigner(cold_as_ice: u32);
+}
diff --git a/tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs b/tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
new file mode 100644
index 000000000..135987fc0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
@@ -0,0 +1,3 @@
+#![feature(auto_traits)]
+
+pub auto trait AnAutoTrait {}
diff --git a/tests/rustdoc/auxiliary/source-code-bar.rs b/tests/rustdoc/auxiliary/source-code-bar.rs
new file mode 100644
index 000000000..8700d688e
--- /dev/null
+++ b/tests/rustdoc/auxiliary/source-code-bar.rs
@@ -0,0 +1,17 @@
+//! just some other file. :)
+
+use crate::Foo;
+
+pub struct Bar {
+ field: Foo,
+}
+
+pub struct Bar2 {
+ field: crate::Foo,
+}
+
+pub mod sub {
+ pub trait Trait {
+ fn tadam() {}
+ }
+}
diff --git a/tests/rustdoc/auxiliary/source_code.rs b/tests/rustdoc/auxiliary/source_code.rs
new file mode 100644
index 000000000..72a5c1a0a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/source_code.rs
@@ -0,0 +1 @@
+pub struct SourceCode;
diff --git a/tests/rustdoc/auxiliary/src-links-external.rs b/tests/rustdoc/auxiliary/src-links-external.rs
new file mode 100644
index 000000000..4a835673a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/src-links-external.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/tests/rustdoc/auxiliary/trait-alias-mention.rs b/tests/rustdoc/auxiliary/trait-alias-mention.rs
new file mode 100644
index 000000000..6df06c87a
--- /dev/null
+++ b/tests/rustdoc/auxiliary/trait-alias-mention.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SomeAlias = std::fmt::Debug + std::marker::Copy;
diff --git a/tests/rustdoc/auxiliary/trait-visibility.rs b/tests/rustdoc/auxiliary/trait-visibility.rs
new file mode 100644
index 000000000..1e8d0b8e0
--- /dev/null
+++ b/tests/rustdoc/auxiliary/trait-visibility.rs
@@ -0,0 +1,3 @@
+pub trait Bar {
+ fn foo();
+}
diff --git a/tests/rustdoc/auxiliary/unit-return.rs b/tests/rustdoc/auxiliary/unit-return.rs
new file mode 100644
index 000000000..7b9986162
--- /dev/null
+++ b/tests/rustdoc/auxiliary/unit-return.rs
@@ -0,0 +1,3 @@
+pub fn f2<F: FnMut(u32) + Clone>(f: F) {}
+
+pub fn f3<F: FnMut(u64) -> () + Clone>(f: F) {}
diff --git a/tests/rustdoc/auxiliary/unstable-trait.rs b/tests/rustdoc/auxiliary/unstable-trait.rs
new file mode 100644
index 000000000..6f06a6e26
--- /dev/null
+++ b/tests/rustdoc/auxiliary/unstable-trait.rs
@@ -0,0 +1,26 @@
+#![feature(staged_api)]
+#![stable(feature = "private_general", since = "1.0.0")]
+
+#[unstable(feature = "private_trait", issue = "none")]
+pub trait Bar {}
+
+#[stable(feature = "private_general", since = "1.0.0")]
+pub struct Foo {
+ // nothing
+}
+
+impl Foo {
+ #[stable(feature = "private_general", since = "1.0.0")]
+ pub fn stable_impl() {}
+}
+
+impl Foo {
+ #[unstable(feature = "private_trait", issue = "none")]
+ pub fn bar() {}
+
+ #[stable(feature = "private_general", since = "1.0.0")]
+ pub fn bar2() {}
+}
+
+#[stable(feature = "private_general", since = "1.0.0")]
+impl Bar for Foo {}
diff --git a/tests/rustdoc/auxiliary/variant-struct.rs b/tests/rustdoc/auxiliary/variant-struct.rs
new file mode 100644
index 000000000..0f3d2e5f1
--- /dev/null
+++ b/tests/rustdoc/auxiliary/variant-struct.rs
@@ -0,0 +1,5 @@
+pub enum Foo {
+ Bar {
+ qux: (),
+ }
+}
diff --git a/tests/rustdoc/bad-codeblock-syntax.rs b/tests/rustdoc/bad-codeblock-syntax.rs
new file mode 100644
index 000000000..9ec089fd7
--- /dev/null
+++ b/tests/rustdoc/bad-codeblock-syntax.rs
@@ -0,0 +1,44 @@
+#![allow(rustdoc::invalid_rust_codeblocks)]
+
+// @has bad_codeblock_syntax/fn.foo.html
+// @has - '//*[@class="docblock"]' '\_'
+/// ```
+/// \_
+/// ```
+pub fn foo() {}
+
+// @has bad_codeblock_syntax/fn.bar.html
+// @has - '//*[@class="docblock"]' '`baz::foobar`'
+/// ```
+/// `baz::foobar`
+/// ```
+pub fn bar() {}
+
+// @has bad_codeblock_syntax/fn.quux.html
+// @has - '//*[@class="docblock"]' '\_'
+/// ```rust
+/// \_
+/// ```
+pub fn quux() {}
+
+// @has bad_codeblock_syntax/fn.ok.html
+// @has - '//*[@class="docblock"]' '\_'
+/// ```text
+/// \_
+/// ```
+pub fn ok() {}
+
+// @has bad_codeblock_syntax/fn.escape.html
+// @has - '//*[@class="docblock"]' '\_ <script>alert("not valid Rust");</script>'
+/// ```
+/// \_
+/// <script>alert("not valid Rust");</script>
+/// ```
+pub fn escape() {}
+
+// @has bad_codeblock_syntax/fn.unterminated.html
+// @has - '//*[@class="docblock"]' '"unterminated'
+/// ```
+/// "unterminated
+/// ```
+pub fn unterminated() {}
diff --git a/tests/rustdoc/blanket-reexport-item.rs b/tests/rustdoc/blanket-reexport-item.rs
new file mode 100644
index 000000000..437f0001f
--- /dev/null
+++ b/tests/rustdoc/blanket-reexport-item.rs
@@ -0,0 +1,8 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header"]' 'impl<T, U> Into<U> for T'
+pub struct S2 {}
+mod m {
+ pub struct S {}
+}
+pub use m::*;
diff --git a/tests/rustdoc/bounds-in-multiple-parts.rs b/tests/rustdoc/bounds-in-multiple-parts.rs
new file mode 100644
index 000000000..279e3c148
--- /dev/null
+++ b/tests/rustdoc/bounds-in-multiple-parts.rs
@@ -0,0 +1,20 @@
+#![crate_name = "foo"]
+
+pub trait Eq {}
+pub trait Eq2 {}
+
+// Checking that "where predicates" and "generics params" are merged.
+// @has 'foo/trait.T.html'
+// @has - "//*[@id='tymethod.f']/h4" "fn f<'a, 'b, 'c, T>()where Self: Eq, T: Eq + 'a, 'c: 'b + 'a,"
+pub trait T {
+ fn f<'a, 'b, 'c: 'a, T: Eq + 'a>()
+ where Self: Eq, Self: Eq, T: Eq, 'c: 'b;
+}
+
+// Checking that a duplicated "where predicate" is removed.
+// @has 'foo/trait.T2.html'
+// @has - "//*[@id='tymethod.f']/h4" "fn f<T>()where Self: Eq + Eq2, T: Eq2 + Eq,"
+pub trait T2 {
+ fn f<T: Eq>()
+ where Self: Eq, Self: Eq2, T: Eq2;
+}
diff --git a/tests/rustdoc/cap-lints.rs b/tests/rustdoc/cap-lints.rs
new file mode 100644
index 000000000..08a353396
--- /dev/null
+++ b/tests/rustdoc/cap-lints.rs
@@ -0,0 +1,9 @@
+// This should fail a normal compile due to non_camel_case_types,
+// It should pass a doc-compile as it only needs to type-check and
+// therefore should not concern itself with the lints.
+#[deny(warnings)]
+
+// @has cap_lints/struct.Foo.html //* 'Foo'
+pub struct Foo {
+ field: i32,
+}
diff --git a/tests/rustdoc/cfg-doctest.rs b/tests/rustdoc/cfg-doctest.rs
new file mode 100644
index 000000000..6a9d26a4b
--- /dev/null
+++ b/tests/rustdoc/cfg-doctest.rs
@@ -0,0 +1,6 @@
+// @!has cfg_doctest/struct.SomeStruct.html
+// @!has cfg_doctest/index.html '//a/@href' 'struct.SomeStruct.html'
+
+/// Sneaky, this isn't actually part of docs.
+#[cfg(doctest)]
+pub struct SomeStruct;
diff --git a/tests/rustdoc/cfg_doc_reexport.rs b/tests/rustdoc/cfg_doc_reexport.rs
new file mode 100644
index 000000000..addb6709d
--- /dev/null
+++ b/tests/rustdoc/cfg_doc_reexport.rs
@@ -0,0 +1,33 @@
+#![feature(doc_cfg)]
+#![feature(no_core)]
+
+#![crate_name = "foo"]
+#![no_core]
+
+// @has 'foo/index.html'
+// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'foobar'
+// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'bar'
+
+#[doc(cfg(feature = "foobar"))]
+mod imp_priv {
+ // @has 'foo/struct.BarPriv.html'
+ // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on crate feature foobar only.'
+ pub struct BarPriv {}
+ impl BarPriv {
+ pub fn test() {}
+ }
+}
+#[doc(cfg(feature = "foobar"))]
+pub use crate::imp_priv::*;
+
+pub mod bar {
+ // @has 'foo/bar/struct.Bar.html'
+ // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on crate feature bar only.'
+ #[doc(cfg(feature = "bar"))]
+ pub struct Bar;
+}
+
+#[doc(cfg(feature = "bar"))]
+pub use bar::Bar;
diff --git a/tests/rustdoc/check-source-code-urls-to-def-std.rs b/tests/rustdoc/check-source-code-urls-to-def-std.rs
new file mode 100644
index 000000000..e12d8445f
--- /dev/null
+++ b/tests/rustdoc/check-source-code-urls-to-def-std.rs
@@ -0,0 +1,42 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
+
+#![crate_name = "foo"]
+
+// @has 'src/foo/check-source-code-urls-to-def-std.rs.html'
+
+fn babar() {}
+
+// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str'
+// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//a[@href="#7"]' 'babar'
+pub fn foo(a: u32, b: &str, c: String) {
+ let x = 12;
+ let y: bool = true;
+ babar();
+}
+
+macro_rules! yolo { () => {}}
+
+fn bar(a: i32) {}
+
+macro_rules! bar {
+ ($a:ident) => { bar($a) }
+}
+
+macro_rules! data {
+ ($x:expr) => { $x * 2 }
+}
+
+pub fn another_foo() {
+ // This is known limitation: if the macro doesn't generate anything, the visitor
+ // can't find any item or anything that could tell us that it comes from expansion.
+ // @!has - '//a[@href="#19"]' 'yolo!'
+ yolo!();
+ // @has - '//a[@href="{{channel}}/std/macro.eprintln.html"]' 'eprintln!'
+ eprintln!();
+ // @has - '//a[@href="#27-29"]' 'data!'
+ let x = data!(4);
+ // @has - '//a[@href="#23-25"]' 'bar!'
+ bar!(x);
+}
diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/check-source-code-urls-to-def.rs
new file mode 100644
index 000000000..5959f9c7c
--- /dev/null
+++ b/tests/rustdoc/check-source-code-urls-to-def.rs
@@ -0,0 +1,69 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
+// aux-build:source_code.rs
+// build-aux-docs
+
+#![feature(rustdoc_internals)]
+
+#![crate_name = "foo"]
+
+extern crate source_code;
+
+// @has 'src/foo/check-source-code-urls-to-def.rs.html'
+
+// @has - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#1-17"]' 'bar'
+#[path = "auxiliary/source-code-bar.rs"]
+pub mod bar;
+
+// @count - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#5"]' 4
+use bar::Bar;
+// @has - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#13"]' 'self'
+// @has - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#14"]' 'Trait'
+use bar::sub::{self, Trait};
+
+pub struct Foo;
+
+impl Foo {
+ fn hello(&self) {}
+}
+
+fn babar() {}
+
+// @has - '//pre[@class="rust"]//a/@href' '/struct.String.html'
+// @has - '//pre[@class="rust"]//a/@href' '/primitive.u32.html'
+// @has - '//pre[@class="rust"]//a/@href' '/primitive.str.html'
+// @count - '//pre[@class="rust"]//a[@href="#23"]' 5
+// @has - '//pre[@class="rust"]//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
+pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
+ let x = 12;
+ let y: Foo = Foo;
+ let z: Bar = bar::Bar { field: Foo };
+ babar();
+ // @has - '//pre[@class="rust"]//a[@href="#26"]' 'hello'
+ y.hello();
+}
+
+// @has - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#14"]' 'bar::sub::Trait'
+// @has - '//pre[@class="rust"]//a[@href="auxiliary/source-code-bar.rs.html#14"]' 'Trait'
+pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {}
+
+pub trait AnotherTrait {}
+pub trait WhyNot {}
+
+// @has - '//pre[@class="rust"]//a[@href="#49"]' 'AnotherTrait'
+// @has - '//pre[@class="rust"]//a[@href="#50"]' 'WhyNot'
+pub fn foo3<T, V>(t: &T, v: &V)
+where
+ T: AnotherTrait,
+ V: WhyNot
+{}
+
+pub trait AnotherTrait2 {}
+
+// @has - '//pre[@class="rust"]//a[@href="#60"]' 'AnotherTrait2'
+pub fn foo4() {
+ let x: Vec<AnotherTrait2> = Vec::new();
+}
+
+// @has - '//pre[@class="rust"]//a[@href="../../foo/primitive.bool.html"]' 'bool'
+#[doc(primitive = "bool")]
+mod whatever {}
diff --git a/tests/rustdoc/check-styled-link.rs b/tests/rustdoc/check-styled-link.rs
new file mode 100644
index 000000000..ed4a5ea21
--- /dev/null
+++ b/tests/rustdoc/check-styled-link.rs
@@ -0,0 +1,8 @@
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @has foo/struct.Bar.html '//a[@href="struct.Foo.html"]' 'Foo'
+
+/// Code-styled reference to [`Foo`].
+pub struct Bar;
diff --git a/tests/rustdoc/check.rs b/tests/rustdoc/check.rs
new file mode 100644
index 000000000..1fb4b35dd
--- /dev/null
+++ b/tests/rustdoc/check.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Z unstable-options --check
+
+// @!has check/fn.foo.html
+// @!has check/index.html
+pub fn foo() {}
diff --git a/tests/rustdoc/codeblock-title.rs b/tests/rustdoc/codeblock-title.rs
new file mode 100644
index 000000000..b9b0b0d1a
--- /dev/null
+++ b/tests/rustdoc/codeblock-title.rs
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html '//*[@class="example-wrap compile_fail"]/*[@class="tooltip"]' "ⓘ"
+// @has foo/fn.bar.html '//*[@class="example-wrap ignore"]/*[@class="tooltip"]' "ⓘ"
+// @has foo/fn.bar.html '//*[@class="example-wrap should_panic"]/*[@class="tooltip"]' "ⓘ"
+// @has foo/fn.bar.html '//*[@data-edition="2018"]' "ⓘ"
+
+/// foo
+///
+/// ```compile_fail
+/// foo();
+/// ```
+///
+/// ```ignore (tidy)
+/// goo();
+/// ```
+///
+/// ```should_panic
+/// hoo();
+/// ```
+///
+/// ```edition2018
+/// let x = 0;
+/// ```
+pub fn bar() -> usize { 2 }
diff --git a/tests/rustdoc/comment-in-doctest.rs b/tests/rustdoc/comment-in-doctest.rs
new file mode 100644
index 000000000..5691d1735
--- /dev/null
+++ b/tests/rustdoc/comment-in-doctest.rs
@@ -0,0 +1,20 @@
+// compile-flags:--test
+
+// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into
+// thinking that everything after it was part of the regular program. combined with the librustc_ast
+// parser loop failing to detect the manual main function, it would wrap everything in `fn main`,
+// which would cause the doctest to fail as the "extern crate" declaration was no longer valid.
+// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see
+// https://github.com/rust-lang/rust/issues/56727
+
+//! ```
+//! // crate: proc-macro-test
+//! //! this is a test
+//!
+//! // used to pull in proc-macro specific items
+//! extern crate proc_macro;
+//!
+//! use proc_macro::TokenStream;
+//!
+//! # fn main() {}
+//! ```
diff --git a/tests/rustdoc/const-display.rs b/tests/rustdoc/const-display.rs
new file mode 100644
index 000000000..594501b22
--- /dev/null
+++ b/tests/rustdoc/const-display.rs
@@ -0,0 +1,86 @@
+#![crate_name = "foo"]
+
+#![unstable(feature = "humans",
+ reason = "who ever let humans program computers, we're apparently really bad at it",
+ issue = "none")]
+
+#![feature(foo, foo2)]
+#![feature(staged_api)]
+
+// @has 'foo/fn.foo.html' '//pre' 'pub fn foo() -> u32'
+// @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
+pub const fn foo() -> u32 { 42 }
+
+// @has 'foo/fn.foo_unsafe.html' '//pre' 'pub unsafe fn foo_unsafe() -> u32'
+// @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
+pub const unsafe fn foo_unsafe() -> u32 { 42 }
+
+// @has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32'
+// @!hasraw - '//span[@class="since"]'
+#[unstable(feature = "humans", issue = "none")]
+pub const fn foo2() -> u32 { 42 }
+
+// @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32'
+// @has - //span '1.0.0 (const: 1.0.0)'
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+pub const fn bar2() -> u32 { 42 }
+
+
+// @has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32'
+// @!hasraw - '//span[@class="since"]'
+#[unstable(feature = "foo2", issue = "none")]
+pub const unsafe fn foo2_gated() -> u32 { 42 }
+
+// @has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32'
+// @has - '//span[@class="since"]' '1.0.0 (const: 1.0.0)'
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+pub const unsafe fn bar2_gated() -> u32 { 42 }
+
+// @has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32'
+// @!hasraw - '//span[@class="since"]'
+pub const unsafe fn bar_not_gated() -> u32 { 42 }
+
+pub struct Foo;
+
+impl Foo {
+ // @has 'foo/struct.Foo.html' '//*[@id="method.gated"]/h4[@class="code-header"]' 'pub fn gated() -> u32'
+ // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature="foo", issue = "none")]
+ pub const fn gated() -> u32 { 42 }
+
+ // @has 'foo/struct.Foo.html' '//*[@id="method.gated_unsafe"]/h4[@class="code-header"]' 'pub unsafe fn gated_unsafe() -> u32'
+ // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature="foo", issue = "none")]
+ pub const unsafe fn gated_unsafe() -> u32 { 42 }
+
+ // @has 'foo/struct.Foo.html' '//*[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32'
+ // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const2", since = "1.2.0")]
+ pub const fn stable_impl() -> u32 { 42 }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Bar;
+
+impl Bar {
+ // Do not show non-const stabilities that are the same as the enclosing item.
+ // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const2", since = "1.2.0")]
+ pub const fn stable_impl() -> u32 { 42 }
+
+ // Show const-stability even for unstable functions.
+ // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$'
+ #[unstable(feature = "foo2", issue = "none")]
+ #[rustc_const_stable(feature = "const3", since = "1.3.0")]
+ pub const fn const_stable_unstable() -> u32 { 42 }
+}
diff --git a/tests/rustdoc/const-doc.rs b/tests/rustdoc/const-doc.rs
new file mode 100644
index 000000000..74ab4af61
--- /dev/null
+++ b/tests/rustdoc/const-doc.rs
@@ -0,0 +1,19 @@
+use std::marker::PhantomData;
+
+pub struct Foo<'a> {
+ f: PhantomData<&'a u32>,
+}
+
+pub struct ContentType {
+ pub ttype: Foo<'static>,
+ pub subtype: Foo<'static>,
+ pub params: Option<Foo<'static>>,
+}
+
+impl ContentType {
+ // @has const_doc/struct.ContentType.html
+ // @has - '//*[@id="associatedconstant.Any"]' 'const Any: ContentType'
+ pub const Any: ContentType = ContentType { ttype: Foo { f: PhantomData, },
+ subtype: Foo { f: PhantomData, },
+ params: None, };
+}
diff --git a/tests/rustdoc/const-fn.rs b/tests/rustdoc/const-fn.rs
new file mode 100644
index 000000000..4366ad4d0
--- /dev/null
+++ b/tests/rustdoc/const-fn.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const fn bar() -> '
+/// foo
+pub const fn bar() -> usize {
+ 2
+}
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="method has-srclink"]' 'const fn new()'
+pub struct Foo(usize);
+
+impl Foo {
+ pub const fn new() -> Foo { Foo(0) }
+}
diff --git a/tests/rustdoc/const-generics/add-impl.rs b/tests/rustdoc/const-generics/add-impl.rs
new file mode 100644
index 000000000..b5226ad3f
--- /dev/null
+++ b/tests/rustdoc/const-generics/add-impl.rs
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+use std::ops::Add;
+
+// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Simd<T, const WIDTH: usize>'
+pub struct Simd<T, const WIDTH: usize> {
+ inner: T,
+}
+
+// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
+impl Add for Simd<u8, 16> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self::Output {
+ Self { inner: 0 }
+ }
+}
diff --git a/tests/rustdoc/const-generics/auxiliary/extern_crate.rs b/tests/rustdoc/const-generics/auxiliary/extern_crate.rs
new file mode 100644
index 000000000..55b632a48
--- /dev/null
+++ b/tests/rustdoc/const-generics/auxiliary/extern_crate.rs
@@ -0,0 +1,16 @@
+// edition:2018
+pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]> {
+ [[0; N]; N].iter().copied()
+}
+
+pub struct ExternTy<const N: usize> {
+ pub inner: [u8; N],
+}
+
+pub type TyAlias<const N: usize> = ExternTy<N>;
+
+pub trait WTrait<const N: usize, const M: usize> {
+ fn hey<const P: usize>() -> usize {
+ N + M + P
+ }
+}
diff --git a/tests/rustdoc/const-generics/const-generic-defaults.rs b/tests/rustdoc/const-generics/const-generic-defaults.rs
new file mode 100644
index 000000000..acc3b853e
--- /dev/null
+++ b/tests/rustdoc/const-generics/const-generic-defaults.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);'
+pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);
diff --git a/tests/rustdoc/const-generics/const-generic-slice.rs b/tests/rustdoc/const-generics/const-generic-slice.rs
new file mode 100644
index 000000000..4279de91f
--- /dev/null
+++ b/tests/rustdoc/const-generics/const-generic-slice.rs
@@ -0,0 +1,11 @@
+#![crate_name = "foo"]
+
+pub trait Array {
+ type Item;
+}
+
+// @has foo/trait.Array.html
+// @has - '//*[@class="impl has-srclink"]' 'impl<T, const N: usize> Array for [T; N]'
+impl<T, const N: usize> Array for [T; N] {
+ type Item = T;
+}
diff --git a/tests/rustdoc/const-generics/const-generics-docs.rs b/tests/rustdoc/const-generics/const-generics-docs.rs
new file mode 100644
index 000000000..543332d2c
--- /dev/null
+++ b/tests/rustdoc/const-generics/const-generics-docs.rs
@@ -0,0 +1,128 @@
+// edition:2018
+// aux-build: extern_crate.rs
+#![crate_name = "foo"]
+
+extern crate extern_crate;
+// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]>'
+pub use extern_crate::extern_fn;
+// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub struct ExternTy<const N: usize> {'
+pub use extern_crate::ExternTy;
+// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'type TyAlias<const N: usize> = ExternTy<N>;'
+pub use extern_crate::TyAlias;
+// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub trait WTrait<const N: usize, const M: usize>'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey<const P: usize>() -> usize'
+pub use extern_crate::WTrait;
+
+// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub trait Trait<const N: usize>'
+// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8'
+// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8'
+// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<{1 + 2}> for u8'
+// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header"]' \
+// 'impl<const N: usize> Trait<N> for [u8; N]'
+pub trait Trait<const N: usize> {}
+impl Trait<1> for u8 {}
+impl Trait<2> for u8 {}
+impl Trait<{1 + 2}> for u8 {}
+impl<const N: usize> Trait<N> for [u8; N] {}
+
+// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub struct Foo<const N: usize>where u8: Trait<N>'
+pub struct Foo<const N: usize> where u8: Trait<N>;
+// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Bar<T, const N: usize>(_)'
+pub struct Bar<T, const N: usize>([T; N]);
+
+// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
+impl<const M: usize> Foo<M> where u8: Trait<M> {
+ // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
+ pub const FOO_ASSOC: usize = M + 13;
+
+ // @has - '//*[@id="method.hey"]' 'pub fn hey<const N: usize>(&self) -> Bar<u8, N>'
+ pub fn hey<const N: usize>(&self) -> Bar<u8, N> {
+ Bar([0; N])
+ }
+}
+
+// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Bar<u8, M>'
+impl<const M: usize> Bar<u8, M> {
+ // @has - '//*[@id="method.hey"]' \
+ // 'pub fn hey<const N: usize>(&self) -> Foo<N>where u8: Trait<N>'
+ pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N> {
+ Foo
+ }
+}
+
+// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
+pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
+ 2u8
+}
+
+// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N>'
+pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
+ v
+}
+
+// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub async fn b_sink<const N: usize>(_: impl Trait<N>)'
+pub async fn b_sink<const N: usize>(_: impl Trait<N>) {}
+
+// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub fn concrete() -> [u8; 22]'
+pub fn concrete() -> [u8; 3 + std::mem::size_of::<u64>() << 1] {
+ Default::default()
+}
+
+// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'type Faz<const N: usize> = [u8; N];'
+pub type Faz<const N: usize> = [u8; N];
+// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'type Fiz<const N: usize> = [[u8; N]; 48];'
+pub type Fiz<const N: usize> = [[u8; N]; 3 << 4];
+
+macro_rules! define_me {
+ ($t:tt<$q:tt>) => {
+ pub struct $t<const $q: usize>([u8; $q]);
+ }
+}
+
+// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub struct Foz<const N: usize>(_);'
+define_me!(Foz<N>);
+
+trait Q {
+ const ASSOC: usize;
+}
+
+impl<const N: usize> Q for [u8; N] {
+ const ASSOC: usize = N;
+}
+
+// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub fn q_user() -> [u8; 13]'
+pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {
+ [0; <[u8; 13] as Q>::ASSOC]
+}
+
+// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub union Union<const N: usize>'
+pub union Union<const N: usize> {
+ // @has - //pre "pub arr: [u8; N]"
+ pub arr: [u8; N],
+ // @has - //pre "pub another_arr: [(); N]"
+ pub another_arr: [(); N],
+}
+
+// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub enum Enum<const N: usize>'
+pub enum Enum<const N: usize> {
+ // @has - //pre "Variant([u8; N])"
+ Variant([u8; N]),
+ // @has - //pre "EmptyVariant"
+ EmptyVariant,
+}
diff --git a/tests/rustdoc/const-generics/const-impl.rs b/tests/rustdoc/const-generics/const-impl.rs
new file mode 100644
index 000000000..726fb8f0c
--- /dev/null
+++ b/tests/rustdoc/const-generics/const-impl.rs
@@ -0,0 +1,37 @@
+#![allow(incomplete_features)]
+#![feature(adt_const_params)]
+#![crate_name = "foo"]
+
+#[derive(PartialEq, Eq)]
+pub enum Order {
+ Sorted,
+ Unsorted,
+}
+
+// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
+pub struct VSet<T, const ORDER: Order> {
+ inner: Vec<T>,
+}
+
+// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Sorted }>'
+impl<T> VSet<T, { Order::Sorted }> {
+ pub fn new() -> Self {
+ Self { inner: Vec::new() }
+ }
+}
+
+// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Unsorted }>'
+impl<T> VSet<T, { Order::Unsorted }> {
+ pub fn new() -> Self {
+ Self { inner: Vec::new() }
+ }
+}
+
+pub struct Escape<const S: &'static str>;
+
+// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
+impl Escape<r#"<script>alert("Escape");</script>"#> {
+ pub fn f() {}
+}
diff --git a/tests/rustdoc/const-generics/generic_const_exprs.rs b/tests/rustdoc/const-generics/generic_const_exprs.rs
new file mode 100644
index 000000000..c53cf6dcd
--- /dev/null
+++ b/tests/rustdoc/const-generics/generic_const_exprs.rs
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
+// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub struct Ice<const N: usize>;'
+pub struct Ice<const N: usize> where [(); N + 1]:;
diff --git a/tests/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/tests/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
new file mode 100644
index 000000000..310e89a35
--- /dev/null
+++ b/tests/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
@@ -0,0 +1,18 @@
+#![crate_name = "foo"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate,
+// which previously caused an ICE.
+
+pub struct Hasher<T> {
+ cv_stack: T,
+}
+
+unsafe impl<T: Default> Send for Hasher<T> {}
+
+// @has foo/struct.Foo.html
+// @has - '//h3[@class="code-header"]' 'impl Send for Foo'
+pub struct Foo {
+ hasher: Hasher<[u8; 3]>,
+}
diff --git a/tests/rustdoc/const-generics/type-alias.rs b/tests/rustdoc/const-generics/type-alias.rs
new file mode 100644
index 000000000..72473a112
--- /dev/null
+++ b/tests/rustdoc/const-generics/type-alias.rs
@@ -0,0 +1,4 @@
+#![crate_name = "foo"]
+
+// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex<const D: usize> = [i64; D];'
+pub type CellIndex<const D: usize> = [i64; D];
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
new file mode 100644
index 000000000..42f6ac792
--- /dev/null
+++ b/tests/rustdoc/const-intrinsic.rs
@@ -0,0 +1,25 @@
+#![feature(intrinsics)]
+#![feature(staged_api)]
+
+#![crate_name = "foo"]
+#![stable(since="1.0.0", feature="rust1")]
+
+extern "rust-intrinsic" {
+ // @has 'foo/fn.transmute.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
+ #[stable(since="1.0.0", feature="rust1")]
+ #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
+ pub fn transmute<T, U>(_: T) -> U;
+
+ // @has 'foo/fn.unreachable.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ #[stable(since="1.0.0", feature="rust1")]
+ pub fn unreachable() -> !;
+}
+
+extern "C" {
+ // @has 'foo/fn.needs_drop.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ #[stable(since="1.0.0", feature="rust1")]
+ pub fn needs_drop() -> !;
+}
diff --git a/tests/rustdoc/const-underscore.rs b/tests/rustdoc/const-underscore.rs
new file mode 100644
index 000000000..0d4809409
--- /dev/null
+++ b/tests/rustdoc/const-underscore.rs
@@ -0,0 +1,7 @@
+// compile-flags: --document-private-items
+
+// @!has const_underscore/constant._.html
+const _: () = {
+ #[no_mangle]
+ extern "C" fn implementation_detail() {}
+};
diff --git a/tests/rustdoc/const-value-display.rs b/tests/rustdoc/const-value-display.rs
new file mode 100644
index 000000000..8d95f0de9
--- /dev/null
+++ b/tests/rustdoc/const-value-display.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+// @has 'foo/constant.HOUR_IN_SECONDS.html'
+// @has - '//*[@class="item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+pub const HOUR_IN_SECONDS: u64 = 60 * 60;
+
+// @has 'foo/constant.NEGATIVE.html'
+// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+pub const NEGATIVE: i64 = -60 * 60;
diff --git a/tests/rustdoc/const.rs b/tests/rustdoc/const.rs
new file mode 100644
index 000000000..587ad4db4
--- /dev/null
+++ b/tests/rustdoc/const.rs
@@ -0,0 +1,10 @@
+#![crate_type="lib"]
+
+pub struct Foo;
+
+impl Foo {
+ // @has const/struct.Foo.html '//*[@id="method.new"]//h4[@class="code-header"]' 'const unsafe fn new'
+ pub const unsafe fn new() -> Foo {
+ Foo
+ }
+}
diff --git a/tests/rustdoc/constructor-imports.rs b/tests/rustdoc/constructor-imports.rs
new file mode 100644
index 000000000..26795c274
--- /dev/null
+++ b/tests/rustdoc/constructor-imports.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+
+pub mod a {
+ pub struct Foo;
+ pub enum Bar {
+ Baz,
+ }
+}
+
+// @count 'foo/index.html' '//*[code="pub use a::Foo;"]' 1
+#[doc(no_inline)]
+pub use a::Foo;
+// @count 'foo/index.html' '//*[code="pub use a::Bar::Baz;"]' 1
+#[doc(no_inline)]
+pub use a::Bar::Baz;
diff --git a/tests/rustdoc/crate-version-escape.rs b/tests/rustdoc/crate-version-escape.rs
new file mode 100644
index 000000000..8413709f1
--- /dev/null
+++ b/tests/rustdoc/crate-version-escape.rs
@@ -0,0 +1,5 @@
+// compile-flags: --crate-version=<script>alert("hi")</script> -Z unstable-options
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html' '//li[@class="version"]' 'Version <script>alert("hi")</script>'
diff --git a/tests/rustdoc/crate-version.rs b/tests/rustdoc/crate-version.rs
new file mode 100644
index 000000000..2592c9853
--- /dev/null
+++ b/tests/rustdoc/crate-version.rs
@@ -0,0 +1,3 @@
+// compile-flags: --crate-version=1.3.37
+
+// @has 'crate_version/index.html' '//*[@class="version"]' 'Version 1.3.37'
diff --git a/tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs b/tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs
new file mode 100644
index 000000000..d02bc4fe7
--- /dev/null
+++ b/tests/rustdoc/cross-crate-hidden-assoc-trait-items.rs
@@ -0,0 +1,23 @@
+// Regression test for issue #95717
+// Hide cross-crate `#[doc(hidden)]` associated items in trait impls.
+
+#![crate_name = "dependent"]
+// edition:2021
+// aux-crate:dependency=cross-crate-hidden-assoc-trait-items.rs
+
+// The trait `Tr` contains 2 hidden and 2 visisible associated items.
+// Instead of checking for the absence of the hidden items, check for the presence of the
+// visible items instead and assert that there are *exactly two* associated items
+// (by counting the number of `section`s). This is more robust and future-proof.
+
+// @has dependent/struct.Ty.html
+// @has - '//*[@id="associatedtype.VisibleAssoc"]' 'type VisibleAssoc = ()'
+// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC"]' 'const VISIBLE_ASSOC: ()'
+// @count - '//*[@class="impl-items"]/section' 2
+
+// @has dependent/trait.Tr.html
+// @has - '//*[@id="associatedtype.VisibleAssoc-1"]' 'type VisibleAssoc = ()'
+// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC-1"]' 'const VISIBLE_ASSOC: ()'
+// @count - '//*[@class="impl-items"]/section' 2
+
+pub use dependency::{Tr, Ty};
diff --git a/tests/rustdoc/cross-crate-hidden-impl-parameter.rs b/tests/rustdoc/cross-crate-hidden-impl-parameter.rs
new file mode 100644
index 000000000..eb2ced2f7
--- /dev/null
+++ b/tests/rustdoc/cross-crate-hidden-impl-parameter.rs
@@ -0,0 +1,35 @@
+// Issue #86448: test for cross-crate `doc(hidden)`
+#![crate_name = "foo"]
+
+// aux-build:cross-crate-hidden-impl-parameter.rs
+extern crate cross_crate_hidden_impl_parameter;
+
+pub use ::cross_crate_hidden_impl_parameter::{HiddenType, HiddenTrait}; // OK, not re-exported
+
+pub enum MyLibType {}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From<HiddenType> for MyLibType'
+impl From<HiddenType> for MyLibType {
+ fn from(it: HiddenType) -> MyLibType {
+ match it {}
+ }
+}
+
+pub struct T<T>(T);
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From<T<T<T<T<HiddenType>>>>> for MyLibType'
+impl From<T<T<T<T<HiddenType>>>>> for MyLibType {
+ fn from(it: T<T<T<T<HiddenType>>>>) -> MyLibType {
+ todo!()
+ }
+}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType'
+impl HiddenTrait for MyLibType {}
+
+// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From<MyLibType> for T<T<T<T<HiddenType>>>>'
+impl From<MyLibType> for T<T<T<T<HiddenType>>>> {
+ fn from(it: MyLibType) -> T<T<T<T<HiddenType>>>> {
+ match it {}
+ }
+}
diff --git a/tests/rustdoc/cross-crate-links.rs b/tests/rustdoc/cross-crate-links.rs
new file mode 100644
index 000000000..7c736a4cc
--- /dev/null
+++ b/tests/rustdoc/cross-crate-links.rs
@@ -0,0 +1,59 @@
+// aux-build:all-item-types.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate all_item_types;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/foo_mod/index.html"]' 'foo_mod'
+#[doc(no_inline)]
+pub use all_item_types::foo_mod;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_ffn.html"]' 'foo_ffn'
+#[doc(no_inline)]
+pub use all_item_types::foo_ffn;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_FSTATIC.html"]' 'FOO_FSTATIC'
+#[doc(no_inline)]
+pub use all_item_types::FOO_FSTATIC;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/foreigntype.FooFType.html"]' 'FooFType'
+#[doc(no_inline)]
+pub use all_item_types::FooFType;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_fn.html"]' 'foo_fn'
+#[doc(no_inline)]
+pub use all_item_types::foo_fn;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/trait.FooTrait.html"]' 'FooTrait'
+#[doc(no_inline)]
+pub use all_item_types::FooTrait;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/struct.FooStruct.html"]' 'FooStruct'
+#[doc(no_inline)]
+pub use all_item_types::FooStruct;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/enum.FooEnum.html"]' 'FooEnum'
+#[doc(no_inline)]
+pub use all_item_types::FooEnum;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/union.FooUnion.html"]' 'FooUnion'
+#[doc(no_inline)]
+pub use all_item_types::FooUnion;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/type.FooType.html"]' 'FooType'
+#[doc(no_inline)]
+pub use all_item_types::FooType;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_STATIC.html"]' 'FOO_STATIC'
+#[doc(no_inline)]
+pub use all_item_types::FOO_STATIC;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/constant.FOO_CONSTANT.html"]' 'FOO_CONSTANT'
+#[doc(no_inline)]
+pub use all_item_types::FOO_CONSTANT;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/macro.foo_macro.html"]' 'foo_macro'
+#[doc(no_inline)]
+pub use all_item_types::foo_macro;
diff --git a/tests/rustdoc/cross-crate-primitive-doc.rs b/tests/rustdoc/cross-crate-primitive-doc.rs
new file mode 100644
index 000000000..4ba296ee0
--- /dev/null
+++ b/tests/rustdoc/cross-crate-primitive-doc.rs
@@ -0,0 +1,13 @@
+// aux-build:primitive-doc.rs
+// compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
+// only-linux
+
+#![feature(no_core)]
+#![no_core]
+
+extern crate primitive_doc;
+
+// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize'
+// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link'
+/// [link](usize)
+pub fn foo() -> usize { 0 }
diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html
new file mode 100644
index 000000000..02b51b344
--- /dev/null
+++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html
@@ -0,0 +1,7 @@
+<code>pub trait Write {
+ fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;buf: &amp;mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+
+ fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;bufs: &amp;[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt; { ... }
+}</code> \ No newline at end of file
diff --git a/tests/rustdoc/decl-trailing-whitespace.rs b/tests/rustdoc/decl-trailing-whitespace.rs
new file mode 100644
index 000000000..e47edc132
--- /dev/null
+++ b/tests/rustdoc/decl-trailing-whitespace.rs
@@ -0,0 +1,30 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/98803>.
+
+#![crate_name = "foo"]
+
+pub struct Error;
+
+// @has 'foo/trait.Write.html'
+
+pub trait Write {
+ // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
+ fn poll_write(
+ self: Option<String>,
+ cx: &mut Option<String>,
+ buf: &mut [usize]
+ ) -> Option<Result<usize, Error>>;
+ fn poll_flush(
+ self: Option<String>,
+ cx: &mut Option<String>
+ ) -> Option<Result<(), Error>>;
+ fn poll_close(
+ self: Option<String>,
+ cx: &mut Option<String>,
+ ) -> Option<Result<(), Error>>;
+
+ fn poll_write_vectored(
+ self: Option<String>,
+ cx: &mut Option<String>,
+ bufs: &[usize]
+ ) -> Option<Result<usize, Error>> {}
+}
diff --git a/tests/rustdoc/decl_macro.rs b/tests/rustdoc/decl_macro.rs
new file mode 100644
index 000000000..94ade31b5
--- /dev/null
+++ b/tests/rustdoc/decl_macro.rs
@@ -0,0 +1,56 @@
+// compile-flags: --document-private-items
+
+#![feature(decl_macro)]
+
+// @has decl_macro/macro.my_macro.html //pre 'pub macro my_macro() {'
+// @has - //pre '...'
+// @has - //pre '}'
+pub macro my_macro() {
+
+}
+
+// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok:tt)*) {'
+// @has - //pre '...'
+// @has - //pre '}'
+pub macro my_macro_2($($tok:tt)*) {
+
+}
+
+// @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {'
+// @has - //pre '(_) => { ... },'
+// @has - //pre '($foo:ident . $bar:expr) => { ... },'
+// @has - //pre '($($foo:literal),+) => { ... },'
+// @has - //pre '}'
+pub macro my_macro_multi {
+ (_) => {
+
+ },
+ ($foo:ident . $bar:expr) => {
+
+ },
+ ($($foo:literal),+) => {
+
+ }
+}
+
+// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo:expr) {'
+// @has - //pre '...'
+// @has - //pre '}'
+pub macro by_example_single {
+ ($foo:expr) => {}
+}
+
+mod a {
+ mod b {
+ // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {'
+ pub(in super) macro by_example_vis {
+ ($foo:expr) => {}
+ }
+ mod c {
+ // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
+ pub(in a) macro by_example_vis_named {
+ ($foo:expr) => {}
+ }
+ }
+ }
+}
diff --git a/tests/rustdoc/decl_macro_priv.rs b/tests/rustdoc/decl_macro_priv.rs
new file mode 100644
index 000000000..4e1279e34
--- /dev/null
+++ b/tests/rustdoc/decl_macro_priv.rs
@@ -0,0 +1,14 @@
+// compile-flags: --document-private-items
+
+#![feature(decl_macro)]
+
+// @has decl_macro_priv/macro.crate_macro.html //pre 'pub(crate) macro crate_macro() {'
+// @has - //pre '...'
+// @has - //pre '}'
+pub(crate) macro crate_macro() {}
+
+// @has decl_macro_priv/macro.priv_macro.html //pre 'macro priv_macro() {'
+// @!has - //pre 'pub macro priv_macro() {'
+// @has - //pre '...'
+// @has - //pre '}'
+macro priv_macro() {}
diff --git a/tests/rustdoc/deep-structures.rs b/tests/rustdoc/deep-structures.rs
new file mode 100644
index 000000000..cd3b0d3ec
--- /dev/null
+++ b/tests/rustdoc/deep-structures.rs
@@ -0,0 +1,104 @@
+// This test verifies that we do not hit recursion limit trying to prove auto-trait bounds for
+// reasonably deep structures.
+
+#![crate_type="rlib"]
+
+pub struct A01(A02);
+pub struct A02(A03);
+pub struct A03(A04);
+pub struct A04(A05);
+pub struct A05(A06);
+pub struct A06(A07);
+pub struct A07(A08);
+pub struct A08(A09);
+pub struct A09(A10);
+pub struct A10(A11);
+pub struct A11(A12);
+pub struct A12(A13);
+pub struct A13(A14);
+pub struct A14(A15);
+pub struct A15(A16);
+pub struct A16(A17);
+pub struct A17(A18);
+pub struct A18(A19);
+pub struct A19(A20);
+pub struct A20(A21);
+pub struct A21(A22);
+pub struct A22(A23);
+pub struct A23(A24);
+pub struct A24(A25);
+pub struct A25(A26);
+pub struct A26(A27);
+pub struct A27(A28);
+pub struct A28(A29);
+pub struct A29(A30);
+pub struct A30(A31);
+pub struct A31(A32);
+pub struct A32(A33);
+pub struct A33(A34);
+pub struct A34(A35);
+pub struct A35(A36);
+pub struct A36(A37);
+pub struct A37(A38);
+pub struct A38(A39);
+pub struct A39(A40);
+pub struct A40(A41);
+pub struct A41(A42);
+pub struct A42(A43);
+pub struct A43(A44);
+pub struct A44(A45);
+pub struct A45(A46);
+pub struct A46(A47);
+pub struct A47(A48);
+pub struct A48(A49);
+pub struct A49(A50);
+pub struct A50(A51);
+pub struct A51(A52);
+pub struct A52(A53);
+pub struct A53(A54);
+pub struct A54(A55);
+pub struct A55(A56);
+pub struct A56(A57);
+pub struct A57(A58);
+pub struct A58(A59);
+pub struct A59(A60);
+pub struct A60(A61);
+pub struct A61(A62);
+pub struct A62(A63);
+pub struct A63(A64);
+pub struct A64(A65);
+pub struct A65(A66);
+pub struct A66(A67);
+pub struct A67(A68);
+pub struct A68(A69);
+pub struct A69(A70);
+pub struct A70(A71);
+pub struct A71(A72);
+pub struct A72(A73);
+pub struct A73(A74);
+pub struct A74(A75);
+pub struct A75(A76);
+pub struct A76(A77);
+pub struct A77(A78);
+pub struct A78(A79);
+pub struct A79(A80);
+pub struct A80(A81);
+pub struct A81(A82);
+pub struct A82(A83);
+pub struct A83(A84);
+pub struct A84(A85);
+pub struct A85(A86);
+pub struct A86(A87);
+pub struct A87(A88);
+pub struct A88(A89);
+pub struct A89(A90);
+pub struct A90(A91);
+pub struct A91(A92);
+pub struct A92(A93);
+pub struct A93(A94);
+pub struct A94(A95);
+pub struct A95(A96);
+pub struct A96(A97);
+pub struct A97(A98);
+pub struct A98(A99);
+pub struct A99;
diff --git a/tests/rustdoc/default-impl.rs b/tests/rustdoc/default-impl.rs
new file mode 100644
index 000000000..f11b3b29b
--- /dev/null
+++ b/tests/rustdoc/default-impl.rs
@@ -0,0 +1,9 @@
+// aux-build:rustdoc-default-impl.rs
+// ignore-cross-compile
+
+extern crate rustdoc_default_impl as foo;
+
+pub use foo::bar;
+
+pub fn wut<T: bar::Bar>() {
+}
diff --git a/tests/rustdoc/default-theme.rs b/tests/rustdoc/default-theme.rs
new file mode 100644
index 000000000..ecb8f0b3b
--- /dev/null
+++ b/tests/rustdoc/default-theme.rs
@@ -0,0 +1,7 @@
+// compile-flags: --default-theme ayu
+
+// @has default_theme/index.html
+// @has - '//script[@id="default-settings"]/@data-theme' 'ayu'
+// @has - '//script[@id="default-settings"]/@data-use_system_theme' 'false'
+
+pub fn whatever() {}
diff --git a/tests/rustdoc/default-trait-method-link.rs b/tests/rustdoc/default-trait-method-link.rs
new file mode 100644
index 000000000..7bcd2a3c1
--- /dev/null
+++ b/tests/rustdoc/default-trait-method-link.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html '//a[@href="trait.Foo.html#tymethod.req"]' 'req'
+// @has foo/trait.Foo.html '//a[@href="trait.Foo.html#method.prov"]' 'prov'
+
+/// Always make sure to implement [`req`], but you don't have to implement [`prov`].
+///
+/// [`req`]: Foo::req
+/// [`prov`]: Foo::prov
+pub trait Foo {
+ /// Required
+ fn req();
+ /// Provided
+ fn prov() {}
+}
diff --git a/tests/rustdoc/default-trait-method.rs b/tests/rustdoc/default-trait-method.rs
new file mode 100644
index 000000000..6d0e339c4
--- /dev/null
+++ b/tests/rustdoc/default-trait-method.rs
@@ -0,0 +1,26 @@
+#![feature(min_specialization)]
+
+// @has default_trait_method/trait.Item.html
+// @has - '//*[@id="tymethod.foo"]' 'fn foo()'
+// @!has - '//*[@id="tymethod.foo"]' 'default fn foo()'
+// @has - '//*[@id="tymethod.bar"]' 'fn bar()'
+// @!has - '//*[@id="tymethod.bar"]' 'default fn bar()'
+// @has - '//*[@id="method.baz"]' 'fn baz()'
+// @!has - '//*[@id="method.baz"]' 'default fn baz()'
+pub trait Item {
+ fn foo();
+ fn bar();
+ fn baz() {}
+}
+
+// @has default_trait_method/struct.Foo.html
+// @has - '//*[@id="method.foo"]' 'default fn foo()'
+// @has - '//*[@id="method.bar"]' 'fn bar()'
+// @!has - '//*[@id="method.bar"]' 'default fn bar()'
+// @has - '//*[@id="method.baz"]' 'fn baz()'
+// @!has - '//*[@id="method.baz"]' 'default fn baz()'
+pub struct Foo;
+impl Item for Foo {
+ default fn foo() {}
+ fn bar() {}
+}
diff --git a/tests/rustdoc/deprecated-future-staged-api.rs b/tests/rustdoc/deprecated-future-staged-api.rs
new file mode 100644
index 000000000..2670e7f5d
--- /dev/null
+++ b/tests/rustdoc/deprecated-future-staged-api.rs
@@ -0,0 +1,18 @@
+#![feature(staged_api)]
+#![stable(feature = "deprecated-future-staged-api", since = "1.0.0")]
+
+// @has deprecated_future_staged_api/index.html '//*[@class="stab deprecated"]' \
+// 'Deprecation planned'
+// @has deprecated_future_staged_api/struct.S1.html '//*[@class="stab deprecated"]' \
+// 'Deprecating in 99.99.99: effectively never'
+#[deprecated(since = "99.99.99", note = "effectively never")]
+#[stable(feature = "deprecated-future-staged-api", since = "1.0.0")]
+pub struct S1;
+
+// @has deprecated_future_staged_api/index.html '//*[@class="stab deprecated"]' \
+// 'Deprecation planned'
+// @has deprecated_future_staged_api/struct.S2.html '//*[@class="stab deprecated"]' \
+// 'Deprecating in a future Rust version: literally never'
+#[deprecated(since = "TBD", note = "literally never")]
+#[stable(feature = "deprecated-future-staged-api", since = "1.0.0")]
+pub struct S2;
diff --git a/tests/rustdoc/deprecated-future.rs b/tests/rustdoc/deprecated-future.rs
new file mode 100644
index 000000000..7db8cc602
--- /dev/null
+++ b/tests/rustdoc/deprecated-future.rs
@@ -0,0 +1,6 @@
+// @has deprecated_future/index.html '//*[@class="stab deprecated"]' \
+// 'Deprecated'
+// @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \
+// 'Deprecated since 99.99.99: effectively never'
+#[deprecated(since = "99.99.99", note = "effectively never")]
+pub struct S;
diff --git a/tests/rustdoc/deprecated-impls.rs b/tests/rustdoc/deprecated-impls.rs
new file mode 100644
index 000000000..e419d2631
--- /dev/null
+++ b/tests/rustdoc/deprecated-impls.rs
@@ -0,0 +1,118 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo0.html
+pub struct Foo0;
+
+impl Foo0 {
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.1: fn_with_doc'
+ // @hasraw - 'fn_with_doc short'
+ // @hasraw - 'fn_with_doc full'
+ /// fn_with_doc short
+ ///
+ /// fn_with_doc full
+ #[deprecated(since = "1.0.1", note = "fn_with_doc")]
+ pub fn fn_with_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.2: fn_without_doc'
+ #[deprecated(since = "1.0.2", note = "fn_without_doc")]
+ pub fn fn_without_doc() {}
+}
+
+pub trait Bar {
+ /// fn_empty_with_doc short
+ ///
+ /// fn_empty_with_doc full
+ #[deprecated(since = "1.0.3", note = "fn_empty_with_doc")]
+ fn fn_empty_with_doc();
+
+ #[deprecated(since = "1.0.4", note = "fn_empty_without_doc")]
+ fn fn_empty_without_doc();
+
+ /// fn_def_with_doc short
+ ///
+ /// fn_def_with_doc full
+ #[deprecated(since = "1.0.5", note = "fn_def_with_doc")]
+ fn fn_def_with_doc() {}
+
+ #[deprecated(since = "1.0.6", note = "fn_def_without_doc")]
+ fn fn_def_without_doc() {}
+
+ /// fn_def_def_with_doc short
+ ///
+ /// fn_def_def_with_doc full
+ #[deprecated(since = "1.0.7", note = "fn_def_def_with_doc")]
+ fn fn_def_def_with_doc() {}
+
+ #[deprecated(since = "1.0.8", note = "fn_def_def_without_doc")]
+ fn fn_def_def_without_doc() {}
+}
+
+// @has foo/struct.Foo1.html
+pub struct Foo1;
+
+impl Bar for Foo1 {
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.3: fn_empty_with_doc'
+ // @hasraw - 'fn_empty_with_doc_impl short'
+ // @hasraw - 'fn_empty_with_doc_impl full'
+ /// fn_empty_with_doc_impl short
+ ///
+ /// fn_empty_with_doc_impl full
+ fn fn_empty_with_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.4: fn_empty_without_doc'
+ fn fn_empty_without_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.5: fn_def_with_doc'
+ // @hasraw - 'fn_def_with_doc_impl short'
+ // @hasraw - 'fn_def_with_doc_impl full'
+ /// fn_def_with_doc_impl short
+ ///
+ /// fn_def_with_doc_impl full
+ fn fn_def_with_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.6: fn_def_without_doc'
+ fn fn_def_without_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.7: fn_def_def_with_doc'
+ // @hasraw - 'fn_def_def_with_doc short'
+ // @!hasraw - 'fn_def_def_with_doc full'
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.8: fn_def_def_without_doc'
+}
+
+// @has foo/struct.Foo2.html
+pub struct Foo2;
+
+impl Bar for Foo2 {
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.3: fn_empty_with_doc'
+ // @hasraw - 'fn_empty_with_doc short'
+ // @!hasraw - 'fn_empty_with_doc full'
+ fn fn_empty_with_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.4: fn_empty_without_doc'
+ // @hasraw - 'fn_empty_without_doc_impl short'
+ // @hasraw - 'fn_empty_without_doc_impl full'
+ /// fn_empty_without_doc_impl short
+ ///
+ /// fn_empty_without_doc_impl full
+ fn fn_empty_without_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.5: fn_def_with_doc'
+ // @hasraw - 'fn_def_with_doc short'
+ // @!hasraw - 'fn_def_with_doc full'
+ fn fn_def_with_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.6: fn_def_without_doc'
+ // @hasraw - 'fn_def_without_doc_impl short'
+ // @hasraw - 'fn_def_without_doc_impl full'
+ /// fn_def_without_doc_impl short
+ ///
+ /// fn_def_without_doc_impl full
+ fn fn_def_without_doc() {}
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.7: fn_def_def_with_doc'
+ // @hasraw - 'fn_def_def_with_doc short'
+ // @!hasraw - 'fn_def_def_with_doc full'
+
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.8: fn_def_def_without_doc'
+}
diff --git a/tests/rustdoc/deprecated.rs b/tests/rustdoc/deprecated.rs
new file mode 100644
index 000000000..b3178da98
--- /dev/null
+++ b/tests/rustdoc/deprecated.rs
@@ -0,0 +1,33 @@
+// @has deprecated/index.html '//*[@class="item-left module-item"]/span[@class="stab deprecated"]' \
+// 'Deprecated'
+// @has - '//*[@class="item-right docblock-short"]' 'Deprecated docs'
+
+// @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \
+// 'Deprecated since 1.0.0: text'
+/// Deprecated docs
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct S;
+
+// @matches deprecated/index.html '//*[@class="item-right docblock-short"]' '^Docs'
+/// Docs
+pub struct T;
+
+// @matches deprecated/struct.U.html '//*[@class="stab deprecated"]' \
+// 'Deprecated since 1.0.0$'
+#[deprecated(since = "1.0.0")]
+pub struct U;
+
+// @matches deprecated/struct.V.html '//*[@class="stab deprecated"]' \
+// 'Deprecated: text$'
+#[deprecated(note = "text")]
+pub struct V;
+
+// @matches deprecated/struct.W.html '//*[@class="stab deprecated"]' \
+// 'Deprecated$'
+#[deprecated]
+pub struct W;
+
+// @matches deprecated/struct.X.html '//*[@class="stab deprecated"]' \
+// 'Deprecated: shorthand reason$'
+#[deprecated = "shorthand reason"]
+pub struct X;
diff --git a/tests/rustdoc/deref-const-fn.rs b/tests/rustdoc/deref-const-fn.rs
new file mode 100644
index 000000000..8ecca6d12
--- /dev/null
+++ b/tests/rustdoc/deref-const-fn.rs
@@ -0,0 +1,38 @@
+// This test ensures that the const methods from Deref aren't shown as const.
+// For more information, see https://github.com/rust-lang/rust/issues/90855.
+
+#![crate_name = "foo"]
+
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// @has 'foo/struct.Bar.html'
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Bar;
+
+impl Bar {
+ // @has - '//*[@id="method.len"]' 'pub const fn len(&self) -> usize'
+ // @has - '//*[@id="method.len"]//span[@class="since"]' 'const: 1.0.0'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+ pub const fn len(&self) -> usize { 0 }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Foo {
+ value: Bar,
+}
+
+// @has 'foo/struct.Foo.html'
+// @has - '//*[@id="method.len"]' 'pub fn len(&self) -> usize'
+// @!has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0'
+// @!has - '//*[@id="method.len"]//span[@class="since"]' '(const: 1.0.0)'
+#[stable(feature = "rust1", since = "1.0.0")]
+impl std::ops::Deref for Foo {
+ type Target = Bar;
+
+ fn deref(&self) -> &Self::Target {
+ &self.value
+ }
+}
diff --git a/tests/rustdoc/deref-mut-methods.rs b/tests/rustdoc/deref-mut-methods.rs
new file mode 100644
index 000000000..fdf843422
--- /dev/null
+++ b/tests/rustdoc/deref-mut-methods.rs
@@ -0,0 +1,29 @@
+#![crate_name = "foo"]
+
+use std::ops;
+
+pub struct Foo;
+
+impl Foo {
+ pub fn foo(&mut self) {}
+}
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.foo"]' 'foo'
+pub struct Bar {
+ foo: Foo,
+}
+
+impl ops::Deref for Bar {
+ type Target = Foo;
+
+ fn deref(&self) -> &Foo {
+ &self.foo
+ }
+}
+
+impl ops::DerefMut for Bar {
+ fn deref_mut(&mut self) -> &mut Foo {
+ &mut self.foo
+ }
+}
diff --git a/tests/rustdoc/deref-recursive-pathbuf.rs b/tests/rustdoc/deref-recursive-pathbuf.rs
new file mode 100644
index 000000000..be2b42b5a
--- /dev/null
+++ b/tests/rustdoc/deref-recursive-pathbuf.rs
@@ -0,0 +1,25 @@
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels and across multiple crates.
+// For `Deref` on non-foreign types, look at `deref-recursive.rs`.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
+// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
+// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
+// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+use std::path::PathBuf;
+
+pub struct Foo(PathBuf);
+
+impl Deref for Foo {
+ type Target = PathBuf;
+ fn deref(&self) -> &PathBuf { &self.0 }
+}
diff --git a/tests/rustdoc/deref-recursive.rs b/tests/rustdoc/deref-recursive.rs
new file mode 100644
index 000000000..0436f2f86
--- /dev/null
+++ b/tests/rustdoc/deref-recursive.rs
@@ -0,0 +1,41 @@
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels if needed.
+// For `Deref` on foreign types, look at `deref-recursive-pathbuf.rs`.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
+// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+
+pub struct Foo(Bar);
+pub struct Bar(Baz);
+pub struct Baz;
+
+impl Deref for Foo {
+ type Target = Bar;
+ fn deref(&self) -> &Bar { &self.0 }
+}
+
+impl Deref for Bar {
+ type Target = Baz;
+ fn deref(&self) -> &Baz { &self.0 }
+}
+
+impl Bar {
+ /// This appears under `Foo` methods
+ pub fn bar(&self) {}
+}
+
+impl Baz {
+ /// This should also appear in `Foo` methods when recursing
+ pub fn baz(&self) {}
+}
diff --git a/tests/rustdoc/deref-slice-core.rs b/tests/rustdoc/deref-slice-core.rs
new file mode 100644
index 000000000..cccf273a8
--- /dev/null
+++ b/tests/rustdoc/deref-slice-core.rs
@@ -0,0 +1,22 @@
+// https://github.com/rust-lang/rust/issues/95325
+//
+// Show methods reachable from Deref of primitive.
+#![no_std]
+
+use core::ops::Deref;
+
+// @has 'deref_slice_core/struct.MyArray.html'
+// @has '-' '//*[@id="deref-methods-%5BT%5D"]' 'Methods from Deref<Target = [T]>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.len"]' 'pub fn len(&self)'
+
+pub struct MyArray<T> {
+ array: [T; 10],
+}
+
+impl<T> Deref for MyArray<T> {
+ type Target = [T];
+
+ fn deref(&self) -> &Self::Target {
+ &self.array
+ }
+}
diff --git a/tests/rustdoc/deref-to-primitive.rs b/tests/rustdoc/deref-to-primitive.rs
new file mode 100644
index 000000000..527de780d
--- /dev/null
+++ b/tests/rustdoc/deref-to-primitive.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Foo.html'
+// @has - '//*[@id="deref-methods-i32"]' 'Methods from Deref<Target = i32>'
+// @has - '//*[@id="deref-methods-i32-1"]//*[@id="associatedconstant.BITS"]/h4' \
+// 'pub const BITS: u32 = 32u32'
+pub struct Foo(i32);
+
+impl std::ops::Deref for Foo {
+ type Target = i32;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
diff --git a/tests/rustdoc/deref-typedef.rs b/tests/rustdoc/deref-typedef.rs
new file mode 100644
index 000000000..32424d13e
--- /dev/null
+++ b/tests/rustdoc/deref-typedef.rs
@@ -0,0 +1,46 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Bar.html'
+// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c'
+// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_j"]' 'foo_j'
+
+pub struct FooA;
+pub type FooB = FooA;
+pub type FooC = FooB;
+pub type FooD = FooC;
+pub type FooE = FooD;
+pub type FooF = FooE;
+pub type FooG = FooF;
+pub type FooH = FooG;
+pub type FooI = FooH;
+pub type FooJ = FooI;
+
+impl FooA {
+ pub fn foo_a(&self) {}
+}
+
+impl FooB {
+ pub fn foo_b(&self) {}
+}
+
+impl FooC {
+ pub fn foo_c(&self) {}
+}
+
+impl FooJ {
+ pub fn foo_j(&self) {}
+}
+
+pub struct Bar;
+impl std::ops::Deref for Bar {
+ type Target = FooJ;
+ fn deref(&self) -> &Self::Target { unimplemented!() }
+}
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
new file mode 100644
index 000000000..05ec42822
--- /dev/null
+++ b/tests/rustdoc/description.rs
@@ -0,0 +1,24 @@
+#![crate_name = "foo"]
+//! # Description test crate
+//!
+//! This is the contents of the test crate docstring.
+//! It should not show up in the description.
+
+// @has 'foo/index.html' '//meta[@name="description"]/@content' \
+// 'Description test crate'
+// @!has - '//meta[@name="description"]/@content' 'should not show up'
+
+// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \
+// 'First paragraph description.'
+// @!has - '//meta[@name="description"]/@content' 'Second paragraph'
+/// First paragraph description.
+///
+/// Second paragraph should not show up.
+pub mod foo_mod {
+ pub struct __Thing {}
+}
+
+// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \
+// 'Only paragraph.'
+/// Only paragraph.
+pub fn foo_fn() {}
diff --git a/tests/rustdoc/description_default.rs b/tests/rustdoc/description_default.rs
new file mode 100644
index 000000000..21d8e04d3
--- /dev/null
+++ b/tests/rustdoc/description_default.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+// @has 'foo/index.html' '//meta[@name="description"]/@content' \
+// 'API documentation for the Rust `foo` crate.'
+
+// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \
+// 'API documentation for the Rust `foo_mod` mod in crate `foo`.'
+pub mod foo_mod {
+ pub struct __Thing {}
+}
+
+// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \
+// 'API documentation for the Rust `foo_fn` fn in crate `foo`.'
+pub fn foo_fn() {}
diff --git a/tests/rustdoc/doc-assoc-item.rs b/tests/rustdoc/doc-assoc-item.rs
new file mode 100644
index 000000000..4f1541865
--- /dev/null
+++ b/tests/rustdoc/doc-assoc-item.rs
@@ -0,0 +1,18 @@
+pub struct Foo<T> {
+ x: T,
+}
+
+pub trait Bar {
+ type Fuu;
+
+ fn foo(foo: Self::Fuu);
+}
+
+// @has doc_assoc_item/struct.Foo.html '//*[@class="impl has-srclink"]' 'impl<T: Bar<Fuu = u32>> Foo<T>'
+impl<T: Bar<Fuu = u32>> Foo<T> {
+ pub fn new(t: T) -> Foo<T> {
+ Foo {
+ x: t,
+ }
+ }
+}
diff --git a/tests/rustdoc/doc-auto-cfg.rs b/tests/rustdoc/doc-auto-cfg.rs
new file mode 100644
index 000000000..7842ee69c
--- /dev/null
+++ b/tests/rustdoc/doc-auto-cfg.rs
@@ -0,0 +1,35 @@
+#![feature(doc_auto_cfg)]
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meowmeow'
+#[cfg(not(meowmeow))]
+pub fn foo() {}
+
+// @has foo/fn.bar.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doctest'
+#[cfg(any(meowmeow, test, doc, doctest))]
+pub fn bar() {}
+
+// @has foo/fn.appear_1.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
+#[cfg(any(meowmeow, doc, not(test)))]
+pub fn appear_1() {} // issue #98065
+
+// @has foo/fn.appear_2.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
+#[cfg(any(meowmeow, doc, all(test)))]
+pub fn appear_2() {} // issue #98065
+
+// @has foo/fn.appear_3.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+#[cfg(any(meowmeow, doc, all()))]
+pub fn appear_3() {} // issue #98065
diff --git a/tests/rustdoc/doc-cfg-hide.rs b/tests/rustdoc/doc-cfg-hide.rs
new file mode 100644
index 000000000..636957fe9
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-hide.rs
@@ -0,0 +1,32 @@
+#![crate_name = "oud"]
+#![feature(doc_auto_cfg, doc_cfg, doc_cfg_hide)]
+
+#![doc(cfg_hide(feature = "solecism"))]
+
+// @has 'oud/struct.Solecism.html'
+// @count - '//*[@class="stab portability"]' 0
+// compile-flags:--cfg feature="solecism"
+#[cfg(feature = "solecism")]
+pub struct Solecism;
+
+// @has 'oud/struct.Scribacious.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature solecism'
+#[cfg(feature = "solecism")]
+#[doc(cfg(feature = "solecism"))]
+pub struct Scribacious;
+
+// @has 'oud/struct.Hyperdulia.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature hyperdulia'
+// compile-flags:--cfg feature="hyperdulia"
+#[cfg(feature = "solecism")]
+#[cfg(feature = "hyperdulia")]
+pub struct Hyperdulia;
+
+// @has 'oud/struct.Oystercatcher.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature oystercatcher only'
+// compile-flags:--cfg feature="oystercatcher"
+#[cfg(all(feature = "solecism", feature = "oystercatcher"))]
+pub struct Oystercatcher;
diff --git a/tests/rustdoc/doc-cfg-implicit-gate.rs b/tests/rustdoc/doc-cfg-implicit-gate.rs
new file mode 100644
index 000000000..92804d372
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-implicit-gate.rs
@@ -0,0 +1,7 @@
+// compile-flags:--cfg feature="worricow"
+#![crate_name = "xenogenous"]
+
+// @has 'xenogenous/struct.Worricow.html'
+// @count - '//*[@class="stab portability"]' 0
+#[cfg(feature = "worricow")]
+pub struct Worricow;
diff --git a/tests/rustdoc/doc-cfg-implicit.rs b/tests/rustdoc/doc-cfg-implicit.rs
new file mode 100644
index 000000000..5d17a4ede
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-implicit.rs
@@ -0,0 +1,31 @@
+#![crate_name = "funambulism"]
+#![feature(doc_auto_cfg, doc_cfg)]
+
+// @has 'funambulism/struct.Disorbed.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature disorbed'
+// compile-flags:--cfg feature="disorbed"
+#[cfg(feature = "disorbed")]
+pub struct Disorbed;
+
+// @has 'funambulism/struct.Aesthesia.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia'
+// compile-flags:--cfg feature="aesthesia"
+#[doc(cfg(feature = "aesthesia"))]
+pub struct Aesthesia;
+
+// @has 'funambulism/struct.Pliothermic.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic'
+// compile-flags:--cfg feature="epopoeist"
+#[cfg(feature = "epopoeist")]
+#[doc(cfg(feature = "pliothermic"))]
+pub struct Pliothermic;
+
+// @has 'funambulism/struct.Simillimum.html'
+// @count - '//*[@class="stab portability"]' 0
+// compile-flags:--cfg feature="simillimum"
+#[cfg(feature = "simillimum")]
+#[doc(cfg(all()))]
+pub struct Simillimum;
diff --git a/tests/rustdoc/doc-cfg-simplification.rs b/tests/rustdoc/doc-cfg-simplification.rs
new file mode 100644
index 000000000..633df661b
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-simplification.rs
@@ -0,0 +1,182 @@
+#![crate_name = "globuliferous"]
+#![feature(doc_cfg)]
+
+// @has 'globuliferous/index.html'
+// @count - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' '^ratel$'
+
+// @has 'globuliferous/ratel/index.html'
+// @count - '//*[@class="stab portability"]' 8
+// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+// @matches - '//*[@class="stab portability"]' '^zoonosology$'
+// @matches - '//*[@class="stab portability"]' '^yusho$'
+// @matches - '//*[@class="stab portability"]' '^nunciative$'
+// @matches - '//*[@class="stab portability"]' '^thionic$'
+// @matches - '//*[@class="stab portability"]' '^zincic$'
+// @matches - '//*[@class="stab portability"]' '^cosmotellurian$'
+// @matches - '//*[@class="stab portability"]' '^aposiopesis$'
+#[doc(cfg(feature = "ratel"))]
+pub mod ratel {
+ // @has 'globuliferous/ratel/fn.ovicide.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ pub fn ovicide() {}
+
+ // @has 'globuliferous/ratel/fn.zoonosology.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and zoonosology'
+ #[doc(cfg(feature = "zoonosology"))]
+ pub fn zoonosology() {}
+
+ // @has 'globuliferous/ratel/constant.DIAGRAPHICS.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ pub const DIAGRAPHICS: () = ();
+
+ // @has 'globuliferous/ratel/constant.YUSHO.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and yusho'
+ #[doc(cfg(feature = "yusho"))]
+ pub const YUSHO: () = ();
+
+ // @has 'globuliferous/ratel/static.KEYBUGLE.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ pub static KEYBUGLE: () = ();
+
+ // @has 'globuliferous/ratel/static.NUNCIATIVE.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and nunciative'
+ #[doc(cfg(feature = "nunciative"))]
+ pub static NUNCIATIVE: () = ();
+
+ // @has 'globuliferous/ratel/type.Wrick.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ pub type Wrick = ();
+
+ // @has 'globuliferous/ratel/type.Thionic.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and thionic'
+ #[doc(cfg(feature = "thionic"))]
+ pub type Thionic = ();
+
+ // @has 'globuliferous/ratel/struct.Eventration.html'
+ // @count - '//*[@class="stab portability"]' 1
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ pub struct Eventration;
+
+ // @has 'globuliferous/ratel/struct.Zincic.html'
+ // @count - '//*[@class="stab portability"]' 2
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and zincic'
+ // @matches - '//*[@class="stab portability"]' 'crate feature rutherford'
+ #[doc(cfg(feature = "zincic"))]
+ pub struct Zincic {
+ pub rectigrade: (),
+
+ #[doc(cfg(feature = "rutherford"))]
+ pub rutherford: (),
+ }
+
+ // @has 'globuliferous/ratel/enum.Cosmotellurian.html'
+ // @count - '//*[@class="stab portability"]' 10
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and cosmotellurian'
+ // @matches - '//*[@class="stab portability"]' 'crate feature biotaxy'
+ // @matches - '//*[@class="stab portability"]' 'crate feature xiphopagus'
+ // @matches - '//*[@class="stab portability"]' 'crate feature juxtapositive'
+ // @matches - '//*[@class="stab portability"]' 'crate feature fuero'
+ // @matches - '//*[@class="stab portability"]' 'crate feature palaeophile'
+ // @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
+ // @matches - '//*[@class="stab portability"]' 'crate features broadcloth and xanthocomic'
+ // @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
+ // @matches - '//*[@class="stab portability"]' 'crate features broadcloth and whosoever'
+ #[doc(cfg(feature = "cosmotellurian"))]
+ pub enum Cosmotellurian {
+ Groundsel {
+ jagger: (),
+
+ #[doc(cfg(feature = "xiphopagus"))]
+ xiphopagus: (),
+ },
+
+ #[doc(cfg(feature = "biotaxy"))]
+ Biotaxy {
+ glossography: (),
+
+ #[doc(cfg(feature = "juxtapositive"))]
+ juxtapositive: (),
+ },
+ }
+
+ impl Cosmotellurian {
+ pub fn uxoricide() {}
+
+ #[doc(cfg(feature = "fuero"))]
+ pub fn fuero() {}
+
+ pub const MAMELLE: () = ();
+
+ #[doc(cfg(feature = "palaeophile"))]
+ pub const PALAEOPHILE: () = ();
+ }
+
+ #[doc(cfg(feature = "broadcloth"))]
+ impl Cosmotellurian {
+ pub fn trabeculated() {}
+
+ #[doc(cfg(feature = "xanthocomic"))]
+ pub fn xanthocomic() {}
+
+ pub const BRACHIFEROUS: () = ();
+
+ #[doc(cfg(feature = "whosoever"))]
+ pub const WHOSOEVER: () = ();
+ }
+
+ // @has 'globuliferous/ratel/trait.Gnotobiology.html'
+ // @count - '//*[@class="stab portability"]' 4
+ // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+ // @matches - '//*[@class="stab portability"]' 'crate feature unzymotic'
+ // @matches - '//*[@class="stab portability"]' 'crate feature summate'
+ // @matches - '//*[@class="stab portability"]' 'crate feature unctuous'
+ pub trait Gnotobiology {
+ const XYLOTHERAPY: ();
+
+ #[doc(cfg(feature = "unzymotic"))]
+ const UNZYMOTIC: ();
+
+ type Lepadoid;
+
+ #[doc(cfg(feature = "summate"))]
+ type Summate;
+
+ fn decalcomania();
+
+ #[doc(cfg(feature = "unctuous"))]
+ fn unctuous();
+ }
+
+ // @has 'globuliferous/ratel/trait.Aposiopesis.html'
+ // @count - '//*[@class="stab portability"]' 4
+ // @matches - '//*[@class="stab portability"]' 'crate features ratel and aposiopesis'
+ // @matches - '//*[@class="stab portability"]' 'crate feature umbracious'
+ // @matches - '//*[@class="stab portability"]' 'crate feature uakari'
+ // @matches - '//*[@class="stab portability"]' 'crate feature rotograph'
+ #[doc(cfg(feature = "aposiopesis"))]
+ pub trait Aposiopesis {
+ const REDHIBITION: ();
+
+ #[doc(cfg(feature = "umbracious"))]
+ const UMBRACIOUS: ();
+
+ type Ophthalmoscope;
+
+ #[doc(cfg(feature = "uakari"))]
+ type Uakari;
+
+ fn meseems();
+
+ #[doc(cfg(feature = "rotograph"))]
+ fn rotograph();
+ }
+}
diff --git a/tests/rustdoc/doc-cfg-target-feature.rs b/tests/rustdoc/doc-cfg-target-feature.rs
new file mode 100644
index 000000000..f1b000dc8
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-target-feature.rs
@@ -0,0 +1,21 @@
+// only-x86_64
+// compile-flags:--test
+// should-fail
+// no-system-llvm
+
+// #49723: rustdoc didn't add target features when extracting or running doctests
+
+#![feature(doc_cfg)]
+
+/// Foo
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cfg_target_feature)]
+///
+/// #[cfg(target_feature = "sse")]
+/// assert!(false);
+/// ```
+#[doc(cfg(target_feature = "sse"))]
+pub unsafe fn foo() {}
diff --git a/tests/rustdoc/doc-cfg-traits.rs b/tests/rustdoc/doc-cfg-traits.rs
new file mode 100644
index 000000000..13407b2c7
--- /dev/null
+++ b/tests/rustdoc/doc-cfg-traits.rs
@@ -0,0 +1,124 @@
+#![crate_name = "myrmecophagous"]
+#![feature(doc_cfg, associated_type_defaults)]
+
+// @has 'myrmecophagous/index.html'
+// @count - '//*[@class="stab portability"]' 2
+// @matches - '//*[@class="stab portability"]' '^jurisconsult$'
+// @matches - '//*[@class="stab portability"]' '^quarter$'
+
+pub trait Lea {}
+
+// @has 'myrmecophagous/trait.Vortoscope.html'
+// @count - '//*[@class="stab portability"]' 6
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+// @matches - '//*[@class="stab portability"]' 'crate feature lea'
+// @matches - '//*[@class="stab portability"]' 'crate feature unit'
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+pub trait Vortoscope {
+ type Batology = ();
+
+ #[doc(cfg(feature = "zibib"))]
+ type Zibib = ();
+
+ const YAHRZEIT: () = ();
+
+ #[doc(cfg(feature = "poriform"))]
+ const PORIFORM: () = ();
+
+ fn javanais() {}
+
+ #[doc(cfg(feature = "ethopoeia"))]
+ fn ethopoeia() {}
+}
+
+#[doc(cfg(feature = "lea"))]
+impl<T: Lea> Vortoscope for T {}
+
+#[doc(cfg(feature = "unit"))]
+impl Vortoscope for () {}
+
+// @has 'myrmecophagous/trait.Jurisconsult.html'
+// @count - '//*[@class="stab portability"]' 7
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+// @matches - '//*[@class="stab portability"]' 'crate feature lea'
+// @matches - '//*[@class="stab portability"]' 'crate feature unit'
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+#[doc(cfg(feature = "jurisconsult"))]
+pub trait Jurisconsult {
+ type Urbanist = ();
+
+ #[doc(cfg(feature = "lithomancy"))]
+ type Lithomancy = ();
+
+ const UNIFILAR: () = ();
+
+ #[doc(cfg(feature = "boodle"))]
+ const BOODLE: () = ();
+
+ fn mersion() {}
+
+ #[doc(cfg(feature = "mistetch"))]
+ fn mistetch() {}
+}
+
+#[doc(cfg(feature = "lea"))]
+impl<T: Lea> Jurisconsult for T {}
+
+#[doc(cfg(feature = "unit"))]
+impl Jurisconsult for () {}
+
+// @has 'myrmecophagous/struct.Ultimogeniture.html'
+// @count - '//*[@class="stab portability"]' 8
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature copy'
+#[derive(Clone)]
+pub struct Ultimogeniture;
+
+impl Vortoscope for Ultimogeniture {}
+
+#[doc(cfg(feature = "jurisconsult"))]
+impl Jurisconsult for Ultimogeniture {}
+
+#[doc(cfg(feature = "copy"))]
+impl Copy for Ultimogeniture {}
+
+// @has 'myrmecophagous/struct.Quarter.html'
+// @count - '//*[@class="stab portability"]' 9
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature copy'
+#[doc(cfg(feature = "quarter"))]
+#[derive(Clone)]
+pub struct Quarter;
+
+#[doc(cfg(feature = "quarter"))]
+impl Vortoscope for Quarter {}
+
+#[doc(cfg(all(feature = "jurisconsult", feature = "quarter")))]
+impl Jurisconsult for Quarter {}
+
+#[doc(cfg(all(feature = "copy", feature = "quarter")))]
+impl Copy for Quarter {}
diff --git a/tests/rustdoc/doc-cfg.rs b/tests/rustdoc/doc-cfg.rs
new file mode 100644
index 000000000..4cddb0b76
--- /dev/null
+++ b/tests/rustdoc/doc-cfg.rs
@@ -0,0 +1,101 @@
+#![feature(doc_cfg)]
+#![feature(target_feature, cfg_target_feature)]
+
+// @has doc_cfg/struct.Portable.html
+// @!has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' ''
+// @has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()'
+// @has - '//*[@class="stab portability"]' 'Available on Unix and ARM only.'
+// @has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()'
+// @has - '//*[@class="stab portability"]' 'Available on WASI and WebAssembly only.'
+pub struct Portable;
+
+// @has doc_cfg/unix_only/index.html \
+// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+// 'Available on Unix only.'
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z'
+// @count - '//*[@class="stab portability"]' 2
+#[doc(cfg(unix))]
+pub mod unix_only {
+ // @has doc_cfg/unix_only/fn.unix_only_function.html \
+ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on Unix only.'
+ // @count - '//*[@class="stab portability"]' 1
+ pub fn unix_only_function() {
+ content::should::be::irrelevant();
+ }
+
+ // @has doc_cfg/unix_only/trait.ArmOnly.html \
+ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on Unix and ARM only.'
+ // @count - '//*[@class="stab portability"]' 1
+ #[doc(cfg(target_arch = "arm"))]
+ pub trait ArmOnly {
+ fn unix_and_arm_only_function();
+ }
+
+ #[doc(cfg(target_arch = "arm"))]
+ impl ArmOnly for super::Portable {
+ fn unix_and_arm_only_function() {}
+ }
+}
+
+// @has doc_cfg/wasi_only/index.html \
+// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+// 'Available on WASI only.'
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
+// @count - '//*[@class="stab portability"]' 2
+#[doc(cfg(target_os = "wasi"))]
+pub mod wasi_only {
+ // @has doc_cfg/wasi_only/fn.wasi_only_function.html \
+ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on WASI only.'
+ // @count - '//*[@class="stab portability"]' 1
+ pub fn wasi_only_function() {
+ content::should::be::irrelevant();
+ }
+
+ // @has doc_cfg/wasi_only/trait.Wasm32Only.html \
+ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+ // 'Available on WASI and WebAssembly only.'
+ // @count - '//*[@class="stab portability"]' 1
+ #[doc(cfg(target_arch = "wasm32"))]
+ pub trait Wasm32Only {
+ fn wasi_and_wasm32_only_function();
+ }
+
+ #[doc(cfg(target_arch = "wasm32"))]
+ impl Wasm32Only for super::Portable {
+ fn wasi_and_wasm32_only_function() {}
+ }
+}
+
+// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
+// item as well
+
+// the portability header is different on the module view versus the full view
+// @has doc_cfg/index.html
+// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+
+// @has doc_cfg/fn.uses_target_feature.html
+// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+// 'Available with target feature avx only.'
+#[target_feature(enable = "avx")]
+pub unsafe fn uses_target_feature() {
+ content::should::be::irrelevant();
+}
+
+// @has doc_cfg/fn.uses_cfg_target_feature.html
+// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+// 'Available with target feature avx only.'
+#[doc(cfg(target_feature = "avx"))]
+pub fn uses_cfg_target_feature() {
+ uses_target_feature();
+}
+
+// multiple attributes should be allowed
+// @has doc_cfg/fn.multiple_attrs.html \
+// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+// 'Available on x and y and z only.'
+#[doc(cfg(x))]
+#[doc(cfg(y), cfg(z))]
+pub fn multiple_attrs() {}
diff --git a/tests/rustdoc/doc-notable_trait-mut_t_is_not_an_iterator.rs b/tests/rustdoc/doc-notable_trait-mut_t_is_not_an_iterator.rs
new file mode 100644
index 000000000..bfce46cf4
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait-mut_t_is_not_an_iterator.rs
@@ -0,0 +1,23 @@
+//! Test case for [#80737].
+//!
+//! A SomeTrait that is implemented for `&mut T where T: SomeTrait`
+//! should not be marked as "notable" for return values that do not
+//! have bounds on the trait itself.
+//!
+//! [#80737]: https://github.com/rust-lang/rust/issues/80737
+
+#![feature(rustdoc_internals)]
+#![no_std]
+
+#[doc(primitive = "reference")]
+/// Some useless docs, wouhou!
+///
+/// We need to put this in here, because notable traits
+/// that are implemented on foreign types don't show up.
+mod reference {}
+
+// @has doc_notable_trait_mut_t_is_not_an_iterator/fn.fn_no_matches.html
+// @!has - '//code[@class="content"]' 'Iterator'
+pub fn fn_no_matches<'a, T: 'a>() -> &'a mut T {
+ panic!()
+}
diff --git a/tests/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs b/tests/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs
new file mode 100644
index 000000000..b359dcea0
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs
@@ -0,0 +1,21 @@
+//! Test case for [#78160].
+//!
+//! A SomeTrait that is implemented for `&mut T` should not be marked as
+//! "notable" for return values that are `&T`.
+//!
+//! [#78160]: https://github.com/rust-lang/rust/issues/78160
+
+#![feature(rustdoc_internals)]
+
+#[doc(primitive = "reference")]
+/// Some useless docs, wouhou!
+///
+/// We need to put this in here, because notable traits
+/// that are implemented on foreign types don't show up.
+mod reference {}
+
+// @has doc_notable_trait_mut_t_is_not_ref_t/fn.fn_no_matches.html
+// @!has - '//code[@class="content"]' "impl<'_, I> Iterator for &'_ mut I"
+pub fn fn_no_matches<'a, T: Iterator + 'a>() -> &'a T {
+ loop {}
+}
diff --git a/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html b/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html
new file mode 100644
index 000000000..46be00a08
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"&amp;'static [SomeStruct]":"&lt;h3&gt;Notable traits for &lt;code&gt;&amp;amp;[&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\"&gt;SomeStruct&lt;/a&gt;]&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait_slice::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &amp;amp;[&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\"&gt;SomeStruct&lt;/a&gt;]&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/doc-notable_trait-slice.rs b/tests/rustdoc/doc-notable_trait-slice.rs
new file mode 100644
index 000000000..2411da8cd
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait-slice.rs
@@ -0,0 +1,20 @@
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+pub trait SomeTrait {}
+
+pub struct SomeStruct;
+pub struct OtherStruct;
+impl SomeTrait for &[SomeStruct] {}
+
+// @has doc_notable_trait_slice/fn.bare_fn_matches.html
+// @snapshot bare_fn_matches - '//script[@id="notable-traits-data"]'
+pub fn bare_fn_matches() -> &'static [SomeStruct] {
+ &[]
+}
+
+// @has doc_notable_trait_slice/fn.bare_fn_no_matches.html
+// @count - '//script[@id="notable-traits-data"]' 0
+pub fn bare_fn_no_matches() -> &'static [OtherStruct] {
+ &[]
+}
diff --git a/tests/rustdoc/doc-notable_trait.bare-fn.html b/tests/rustdoc/doc-notable_trait.bare-fn.html
new file mode 100644
index 000000000..f592e3b37
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait.bare-fn.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/doc-notable_trait.rs b/tests/rustdoc/doc-notable_trait.rs
new file mode 100644
index 000000000..279faf554
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait.rs
@@ -0,0 +1,38 @@
+#![feature(doc_notable_trait)]
+
+pub struct Wrapper<T> {
+ inner: T,
+}
+
+impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
+
+#[doc(notable_trait)]
+pub trait SomeTrait {
+ // @has doc_notable_trait/trait.SomeTrait.html
+ // @has - '//a[@class="notable-traits"]/@data-ty' 'Wrapper<Self>'
+ // @snapshot wrap-me - '//script[@id="notable-traits-data"]'
+ fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
+ Wrapper {
+ inner: self,
+ }
+ }
+}
+
+pub struct SomeStruct;
+impl SomeTrait for SomeStruct {}
+
+impl SomeStruct {
+ // @has doc_notable_trait/struct.SomeStruct.html
+ // @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
+ // @snapshot some-struct-new - '//script[@id="notable-traits-data"]'
+ pub fn new() -> SomeStruct {
+ SomeStruct
+ }
+}
+
+// @has doc_notable_trait/fn.bare_fn.html
+// @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
+// @snapshot bare-fn - '//script[@id="notable-traits-data"]'
+pub fn bare_fn() -> SomeStruct {
+ SomeStruct
+}
diff --git a/tests/rustdoc/doc-notable_trait.some-struct-new.html b/tests/rustdoc/doc-notable_trait.some-struct-new.html
new file mode 100644
index 000000000..384be6689
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait.some-struct-new.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/doc-notable_trait.wrap-me.html b/tests/rustdoc/doc-notable_trait.wrap-me.html
new file mode 100644
index 000000000..0cc1ee10f
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait.wrap-me.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs b/tests/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs
new file mode 100644
index 000000000..3fb00c7db
--- /dev/null
+++ b/tests/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs
@@ -0,0 +1,38 @@
+#![feature(doc_notable_trait)]
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+#[lang = "owned_box"]
+pub struct Box<T>;
+
+impl<T> Box<T> {
+ pub fn new(x: T) -> Box<T> {
+ Box
+ }
+}
+
+#[doc(notable_trait)]
+pub trait FakeIterator {}
+
+impl<I: FakeIterator> FakeIterator for Box<I> {}
+
+#[lang = "pin"]
+pub struct Pin<T>;
+
+impl<T> Pin<T> {
+ pub fn new(x: T) -> Pin<T> {
+ Pin
+ }
+}
+
+impl<I: FakeIterator> FakeIterator for Pin<I> {}
+
+// @!has doc_notable_trait_box_is_not_an_iterator/fn.foo.html '//*' 'Notable'
+pub fn foo<T>(x: T) -> Box<T> {
+ Box::new(x)
+}
+
+// @!has doc_notable_trait_box_is_not_an_iterator/fn.bar.html '//*' 'Notable'
+pub fn bar<T>(x: T) -> Pin<T> {
+ Pin::new(x)
+}
diff --git a/tests/rustdoc/doc-proc-macro.rs b/tests/rustdoc/doc-proc-macro.rs
new file mode 100644
index 000000000..19172ffa4
--- /dev/null
+++ b/tests/rustdoc/doc-proc-macro.rs
@@ -0,0 +1,8 @@
+// Issue #52129: ICE when trying to document the `quote` proc-macro from proc_macro
+
+// As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't
+// crash when we try.
+
+extern crate proc_macro;
+
+pub use proc_macro::*;
diff --git a/tests/rustdoc/doc_auto_cfg_nested_impl.rs b/tests/rustdoc/doc_auto_cfg_nested_impl.rs
new file mode 100644
index 000000000..4d73e0d82
--- /dev/null
+++ b/tests/rustdoc/doc_auto_cfg_nested_impl.rs
@@ -0,0 +1,24 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/101129>.
+
+#![feature(doc_auto_cfg)]
+#![crate_type = "lib"]
+#![crate_name = "foo"]
+
+pub struct S;
+pub trait MyTrait1 {}
+pub trait MyTrait2 {}
+
+// @has foo/struct.S.html
+// @has - '//*[@id="impl-MyTrait1-for-S"]//*[@class="stab portability"]' \
+// 'Available on non-crate feature coolstuff only.'
+#[cfg(not(feature = "coolstuff"))]
+impl MyTrait1 for S {}
+
+#[cfg(not(feature = "coolstuff"))]
+mod submod {
+ use crate::{S, MyTrait2};
+ // This impl should also have the `not(feature = "coolstuff")`.
+ // @has - '//*[@id="impl-MyTrait2-for-S"]//*[@class="stab portability"]' \
+ // 'Available on non-crate feature coolstuff only.'
+ impl MyTrait2 for S {}
+}
diff --git a/tests/rustdoc/doctest-manual-crate-name.rs b/tests/rustdoc/doctest-manual-crate-name.rs
new file mode 100644
index 000000000..3a5e3734e
--- /dev/null
+++ b/tests/rustdoc/doctest-manual-crate-name.rs
@@ -0,0 +1,7 @@
+// compile-flags:--test
+
+//! ```
+//! #![crate_name="asdf"]
+//!
+//! println!("yo");
+//! ```
diff --git a/tests/rustdoc/double-quote-escape.rs b/tests/rustdoc/double-quote-escape.rs
new file mode 100644
index 000000000..350c89741
--- /dev/null
+++ b/tests/rustdoc/double-quote-escape.rs
@@ -0,0 +1,11 @@
+#![crate_name = "foo"]
+
+pub trait Foo<T> {
+ fn foo() {}
+}
+
+pub struct Bar;
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E-for-Bar"]' 'Foo<unsafe extern "C" fn()>'
+impl Foo<unsafe extern "C" fn()> for Bar {}
diff --git a/tests/rustdoc/duplicate-cfg.rs b/tests/rustdoc/duplicate-cfg.rs
new file mode 100644
index 000000000..18f3900b2
--- /dev/null
+++ b/tests/rustdoc/duplicate-cfg.rs
@@ -0,0 +1,53 @@
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$'
+// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@class="stab portability"]' 'sync'
+#[doc(cfg(feature = "sync"))]
+#[doc(cfg(feature = "sync"))]
+/// my feature sync struct
+pub struct Foo;
+
+// @has 'foo/bar/index.html'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
+#[doc(cfg(feature = "sync"))]
+pub mod bar {
+ // @has 'foo/bar/struct.Bar.html'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
+ #[doc(cfg(feature = "sync"))]
+ pub struct Bar;
+}
+
+// @has 'foo/baz/index.html'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
+#[doc(cfg(all(feature = "sync", feature = "send")))]
+pub mod baz {
+ // @has 'foo/baz/struct.Baz.html'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
+ #[doc(cfg(feature = "sync"))]
+ pub struct Baz;
+}
+
+// @has 'foo/qux/index.html'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
+#[doc(cfg(feature = "sync"))]
+pub mod qux {
+ // @has 'foo/qux/struct.Qux.html'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
+ #[doc(cfg(all(feature = "sync", feature = "send")))]
+ pub struct Qux;
+}
+
+// @has 'foo/quux/index.html'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo only.'
+#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
+pub mod quux {
+ // @has 'foo/quux/struct.Quux.html'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo and bar only.'
+ #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
+ pub struct Quux;
+}
diff --git a/tests/rustdoc/duplicate-flags.rs b/tests/rustdoc/duplicate-flags.rs
new file mode 100644
index 000000000..dde36df2c
--- /dev/null
+++ b/tests/rustdoc/duplicate-flags.rs
@@ -0,0 +1,4 @@
+// compile-flags: --document-private-items --document-private-items
+
+// @has duplicate_flags/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/duplicate_impls/impls.rs b/tests/rustdoc/duplicate_impls/impls.rs
new file mode 100644
index 000000000..6875ad272
--- /dev/null
+++ b/tests/rustdoc/duplicate_impls/impls.rs
@@ -0,0 +1,12 @@
+pub struct Foo;
+
+// just so that `Foo` doesn't show up on `Bar`s sidebar
+pub mod bar {
+ pub trait Bar {}
+}
+
+impl Foo {
+ pub fn new() -> Foo { Foo }
+}
+
+impl bar::Bar for Foo {}
diff --git a/tests/rustdoc/duplicate_impls/issue-33054.rs b/tests/rustdoc/duplicate_impls/issue-33054.rs
new file mode 100644
index 000000000..c1f95ac91
--- /dev/null
+++ b/tests/rustdoc/duplicate_impls/issue-33054.rs
@@ -0,0 +1,14 @@
+// ignore-tidy-linelength
+
+// @has issue_33054/impls/struct.Foo.html
+// @has - '//h3[@class="code-header"]' 'impl Foo'
+// @has - '//h3[@class="code-header"]' 'impl Bar for Foo'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1
+// @has issue_33054/impls/bar/trait.Bar.html
+// @has - '//h3[@class="code-header"]' 'impl Bar for Foo'
+// @count - '//*[@class="struct"]' 1
+pub mod impls;
+
+#[doc(inline)]
+pub use impls as impls2;
diff --git a/tests/rustdoc/duplicated_impl.rs b/tests/rustdoc/duplicated_impl.rs
new file mode 100644
index 000000000..4e901b31c
--- /dev/null
+++ b/tests/rustdoc/duplicated_impl.rs
@@ -0,0 +1,14 @@
+// This test ensures that the same implementation doesn't show more than once.
+// It's a regression test for https://github.com/rust-lang/rust/issues/96036.
+
+#![crate_name = "foo"]
+
+// We check that there is only one "impl<T> Something<Whatever> for T" listed in the
+// blanket implementations.
+
+// @has 'foo/struct.Whatever.html'
+// @count - '//*[@id="blanket-implementations-list"]/section[@class="impl has-srclink"]' 1
+
+pub trait Something<T> { }
+pub struct Whatever;
+impl<T> Something<Whatever> for T {}
diff --git a/tests/rustdoc/early-unindent.rs b/tests/rustdoc/early-unindent.rs
new file mode 100644
index 000000000..791a452c9
--- /dev/null
+++ b/tests/rustdoc/early-unindent.rs
@@ -0,0 +1,26 @@
+// This is a regression for https://github.com/rust-lang/rust/issues/96079.
+
+#![crate_name = "foo"]
+
+pub mod app {
+ pub struct S;
+
+ impl S {
+ // @has 'foo/app/struct.S.html'
+ // @has - '//a[@href="../enums/enum.Foo.html#method.by_name"]' 'Foo::by_name'
+ /**
+ Doc comment hello! [`Foo::by_name`](`crate::enums::Foo::by_name`).
+ */
+ pub fn whatever(&self) {}
+ }
+}
+
+pub mod enums {
+ pub enum Foo {
+ Bar,
+ }
+
+ impl Foo {
+ pub fn by_name(&self) {}
+ }
+}
diff --git a/tests/rustdoc/edition-doctest.rs b/tests/rustdoc/edition-doctest.rs
new file mode 100644
index 000000000..6de25996b
--- /dev/null
+++ b/tests/rustdoc/edition-doctest.rs
@@ -0,0 +1,44 @@
+// compile-flags:--test
+
+/// ```rust,edition2018
+/// #![feature(try_blocks)]
+///
+/// use std::num::ParseIntError;
+///
+/// let result: Result<i32, ParseIntError> = try {
+/// "1".parse::<i32>()?
+/// + "2".parse::<i32>()?
+/// + "3".parse::<i32>()?
+/// };
+/// assert_eq!(result, Ok(6));
+///
+/// let result: Result<i32, ParseIntError> = try {
+/// "1".parse::<i32>()?
+/// + "foo".parse::<i32>()?
+/// + "3".parse::<i32>()?
+/// };
+/// assert!(result.is_err());
+/// ```
+
+
+/// ```rust,edition2015,compile_fail,E0574
+/// #![feature(try_blocks)]
+///
+/// use std::num::ParseIntError;
+///
+/// let result: Result<i32, ParseIntError> = try {
+/// "1".parse::<i32>()?
+/// + "2".parse::<i32>()?
+/// + "3".parse::<i32>()?
+/// };
+/// assert_eq!(result, Ok(6));
+///
+/// let result: Result<i32, ParseIntError> = try {
+/// "1".parse::<i32>()?
+/// + "foo".parse::<i32>()?
+/// + "3".parse::<i32>()?
+/// };
+/// assert!(result.is_err());
+/// ```
+
+pub fn foo() {}
diff --git a/tests/rustdoc/edition-flag.rs b/tests/rustdoc/edition-flag.rs
new file mode 100644
index 000000000..e54c7d296
--- /dev/null
+++ b/tests/rustdoc/edition-flag.rs
@@ -0,0 +1,11 @@
+// compile-flags:--test
+// edition:2018
+
+/// ```rust
+/// fn main() {
+/// let _ = async { };
+/// }
+/// ```
+fn main() {
+ let _ = async { };
+}
diff --git a/tests/rustdoc/elided-lifetime.rs b/tests/rustdoc/elided-lifetime.rs
new file mode 100644
index 000000000..006132ef8
--- /dev/null
+++ b/tests/rustdoc/elided-lifetime.rs
@@ -0,0 +1,43 @@
+// aux-build:elided-lifetime.rs
+//
+// rust-lang/rust#75225
+//
+// Since Rust 2018 we encourage writing out <'_> explicitly to make it clear
+// that borrowing is occurring. Make sure rustdoc is following the same idiom.
+
+#![crate_name = "foo"]
+
+pub struct Ref<'a>(&'a u32);
+type ARef<'a> = Ref<'a>;
+
+// @has foo/fn.test1.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+pub fn test1(a: &u32) -> Ref {
+ Ref(a)
+}
+
+// @has foo/fn.test2.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+pub fn test2(a: &u32) -> Ref<'_> {
+ Ref(a)
+}
+
+// @has foo/fn.test3.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+pub fn test3(a: &u32) -> ARef {
+ Ref(a)
+}
+
+// @has foo/fn.test4.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+pub fn test4(a: &u32) -> ARef<'_> {
+ Ref(a)
+}
+
+// Ensure external paths in inlined docs also display elided lifetime
+// @has foo/bar/fn.test5.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+// @has foo/bar/fn.test6.html
+// @matchesraw - "Ref</a>&lt;'_&gt;"
+#[doc(inline)]
+pub extern crate bar;
diff --git a/tests/rustdoc/empty-doc-comment.rs b/tests/rustdoc/empty-doc-comment.rs
new file mode 100644
index 000000000..b1dae930e
--- /dev/null
+++ b/tests/rustdoc/empty-doc-comment.rs
@@ -0,0 +1,22 @@
+// Ensure that empty doc comments don't panic.
+
+/*!
+*/
+
+///
+///
+pub struct Foo;
+
+#[doc = "
+"]
+pub mod Mod {
+ //!
+ //!
+}
+
+/**
+*/
+pub mod Another {
+ #![doc = "
+"]
+}
diff --git a/tests/rustdoc/empty-impl-block-private-with-doc.rs b/tests/rustdoc/empty-impl-block-private-with-doc.rs
new file mode 100644
index 000000000..439719961
--- /dev/null
+++ b/tests/rustdoc/empty-impl-block-private-with-doc.rs
@@ -0,0 +1,44 @@
+// compile-flags: --document-private-items
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Foo.html'
+pub struct Foo;
+
+// There are 3 impl blocks with public item and one that should not be displayed
+// by default because it only contains private items (but not in this case because
+// we used `--document-private-items`).
+// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 4
+
+// Impl block only containing private items should not be displayed unless the
+// `--document-private-items` flag is used.
+/// Private
+impl Foo {
+ const BAR: u32 = 0;
+ type FOO = i32;
+ fn hello() {}
+}
+
+// But if any element of the impl block is public, it should be displayed.
+/// Not private
+impl Foo {
+ pub const BAR: u32 = 0;
+ type FOO = i32;
+ fn hello() {}
+}
+
+/// Not private
+impl Foo {
+ const BAR: u32 = 0;
+ pub type FOO = i32;
+ fn hello() {}
+}
+
+/// Not private
+impl Foo {
+ const BAR: u32 = 0;
+ type FOO = i32;
+ pub fn hello() {}
+}
diff --git a/tests/rustdoc/empty-impl-block-private.rs b/tests/rustdoc/empty-impl-block-private.rs
new file mode 100644
index 000000000..5caf02065
--- /dev/null
+++ b/tests/rustdoc/empty-impl-block-private.rs
@@ -0,0 +1,40 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Foo.html'
+pub struct Foo;
+
+// There are 3 impl blocks with public item and one that should not be displayed
+// because it only contains private items.
+// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 3
+
+// Impl block only containing private items should not be displayed.
+/// Private
+impl Foo {
+ const BAR: u32 = 0;
+ type FOO = i32;
+ fn hello() {}
+}
+
+// But if any element of the impl block is public, it should be displayed.
+/// Not private
+impl Foo {
+ pub const BAR: u32 = 0;
+ type FOO = i32;
+ fn hello() {}
+}
+
+/// Not private
+impl Foo {
+ const BAR: u32 = 0;
+ pub type FOO = i32;
+ fn hello() {}
+}
+
+/// Not private
+impl Foo {
+ const BAR: u32 = 0;
+ type FOO = i32;
+ pub fn hello() {}
+}
diff --git a/tests/rustdoc/empty-impl-block.rs b/tests/rustdoc/empty-impl-block.rs
new file mode 100644
index 000000000..95d4db06b
--- /dev/null
+++ b/tests/rustdoc/empty-impl-block.rs
@@ -0,0 +1,20 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Foo.html'
+pub struct Foo;
+
+// @has - '//*[@class="docblock"]' 'Hello empty impl block!'
+// @has - '//*[@class="item-info"]' 'This impl block contains no items.'
+/// Hello empty impl block!
+impl Foo {}
+// We ensure that this empty impl block without doc isn't rendered.
+// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 1
+impl Foo {}
+
+// Just to ensure that empty trait impl blocks are rendered.
+pub struct Another;
+pub trait Bar {}
+
+// @has 'foo/struct.Another.html'
+// @has - '//h3[@class="code-header"]' 'impl Bar for Another'
+impl Bar for Another {}
diff --git a/tests/rustdoc/empty-impls.rs b/tests/rustdoc/empty-impls.rs
new file mode 100644
index 000000000..83902d6f7
--- /dev/null
+++ b/tests/rustdoc/empty-impls.rs
@@ -0,0 +1,19 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//div[@id="synthetic-implementations-list"]/*[@id="impl-Send-for-Foo"]' 'impl Send for Foo'
+pub struct Foo;
+
+pub trait EmptyTrait {}
+
+// @has - '//div[@id="trait-implementations-list"]/*[@id="impl-EmptyTrait-for-Foo"]' 'impl EmptyTrait for Foo'
+impl EmptyTrait for Foo {}
+
+pub trait NotEmpty {
+ fn foo(&self);
+}
+
+// @has - '//div[@id="trait-implementations-list"]/details/summary/*[@id="impl-NotEmpty-for-Foo"]' 'impl NotEmpty for Foo'
+impl NotEmpty for Foo {
+ fn foo(&self) {}
+}
diff --git a/tests/rustdoc/empty-mod-private.rs b/tests/rustdoc/empty-mod-private.rs
new file mode 100644
index 000000000..147e11e58
--- /dev/null
+++ b/tests/rustdoc/empty-mod-private.rs
@@ -0,0 +1,16 @@
+// compile-flags: --document-private-items
+
+// @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo'
+// @hasraw 'empty_mod_private/sidebar-items.js' 'foo'
+// @matches 'empty_mod_private/foo/index.html' '//h1' 'Module empty_mod_private::foo'
+mod foo {}
+
+// @has 'empty_mod_private/index.html' '//a[@href="bar/index.html"]' 'bar'
+// @hasraw 'empty_mod_private/sidebar-items.js' 'bar'
+// @matches 'empty_mod_private/bar/index.html' '//h1' 'Module empty_mod_private::bar'
+mod bar {
+ // @has 'empty_mod_private/bar/index.html' '//a[@href="baz/index.html"]' 'baz'
+ // @hasraw 'empty_mod_private/bar/sidebar-items.js' 'baz'
+ // @matches 'empty_mod_private/bar/baz/index.html' '//h1' 'Module empty_mod_private::bar::baz'
+ mod baz {}
+}
diff --git a/tests/rustdoc/empty-mod-public.rs b/tests/rustdoc/empty-mod-public.rs
new file mode 100644
index 000000000..c0bac4021
--- /dev/null
+++ b/tests/rustdoc/empty-mod-public.rs
@@ -0,0 +1,14 @@
+// @has 'empty_mod_public/index.html' '//a[@href="foo/index.html"]' 'foo'
+// @hasraw 'empty_mod_public/sidebar-items.js' 'foo'
+// @matches 'empty_mod_public/foo/index.html' '//h1' 'Module empty_mod_public::foo'
+pub mod foo {}
+
+// @has 'empty_mod_public/index.html' '//a[@href="bar/index.html"]' 'bar'
+// @hasraw 'empty_mod_public/sidebar-items.js' 'bar'
+// @matches 'empty_mod_public/bar/index.html' '//h1' 'Module empty_mod_public::bar'
+pub mod bar {
+ // @has 'empty_mod_public/bar/index.html' '//a[@href="baz/index.html"]' 'baz'
+ // @hasraw 'empty_mod_public/bar/sidebar-items.js' 'baz'
+ // @matches 'empty_mod_public/bar/baz/index.html' '//h1' 'Module empty_mod_public::bar::baz'
+ pub mod baz {}
+}
diff --git a/tests/rustdoc/empty-section.rs b/tests/rustdoc/empty-section.rs
new file mode 100644
index 000000000..d8241ab96
--- /dev/null
+++ b/tests/rustdoc/empty-section.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+#![feature(negative_impls)]
+
+pub struct Foo;
+
+// @has foo/struct.Foo.html
+// @!hasraw - 'Auto Trait Implementations'
+impl !Send for Foo {}
+impl !Sync for Foo {}
+impl !std::marker::Unpin for Foo {}
+impl !std::panic::RefUnwindSafe for Foo {}
+impl !std::panic::UnwindSafe for Foo {}
diff --git a/tests/rustdoc/ensure-src-link.rs b/tests/rustdoc/ensure-src-link.rs
new file mode 100644
index 000000000..c65387080
--- /dev/null
+++ b/tests/rustdoc/ensure-src-link.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// This test ensures that the [src] link is present on traits items.
+
+// @has foo/trait.Iterator.html '//*[@id="method.zip"]//a[@class="srclink rightside"]' "source"
+pub use std::iter::Iterator;
diff --git a/tests/rustdoc/enum-headings.rs b/tests/rustdoc/enum-headings.rs
new file mode 100644
index 000000000..2e5c34391
--- /dev/null
+++ b/tests/rustdoc/enum-headings.rs
@@ -0,0 +1,40 @@
+#![crate_name = "foo"]
+// @has foo/enum.Token.html
+/// A token!
+/// # First
+/// Some following text...
+// @has - '//h2[@id="first"]' "First"
+pub enum Token {
+ /// A declaration!
+ /// # Variant-First
+ /// Some following text...
+ // @has - '//h4[@id="variant-first"]' "Variant-First"
+ Declaration {
+ /// A version!
+ /// # Variant-Field-First
+ /// Some following text...
+ // @has - '//h5[@id="variant-field-first"]' "Variant-Field-First"
+ version: String,
+ },
+ /// A Zoople!
+ /// # Variant-First
+ Zoople(
+ // @has - '//h5[@id="variant-tuple-field-first"]' "Variant-Tuple-Field-First"
+ /// Zoople's first variant!
+ /// # Variant-Tuple-Field-First
+ /// Some following text...
+ usize,
+ ),
+ /// Unfinished business!
+ /// # Non-Exhaustive-First
+ /// Some following text...
+ // @has - '//h4[@id="non-exhaustive-first"]' "Non-Exhaustive-First"
+ #[non_exhaustive]
+ Unfinished {
+ /// This is x.
+ /// # X-First
+ /// Some following text...
+ // @has - '//h5[@id="x-first"]' "X-First"
+ x: usize,
+ },
+}
diff --git a/tests/rustdoc/escape-deref-methods.rs b/tests/rustdoc/escape-deref-methods.rs
new file mode 100644
index 000000000..66919d73e
--- /dev/null
+++ b/tests/rustdoc/escape-deref-methods.rs
@@ -0,0 +1,35 @@
+#![crate_name = "foo"]
+
+use std::ops::{Deref, DerefMut};
+
+#[derive(Debug, Clone)]
+pub struct Title {
+ name: String,
+}
+
+#[derive(Debug, Clone)]
+pub struct TitleList {
+ pub members: Vec<Title>,
+}
+
+impl TitleList {
+ pub fn new() -> Self {
+ TitleList { members: Vec::new() }
+ }
+}
+
+impl Deref for TitleList {
+ type Target = Vec<Title>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.members
+ }
+}
+
+// @has foo/struct.TitleList.html
+// @has - '//div[@class="sidebar-elems"]//h3' 'Methods from Deref<Target=Vec<Title>>'
+impl DerefMut for TitleList {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.members
+ }
+}
diff --git a/tests/rustdoc/extern-default-method.no_href_on_anchor.html b/tests/rustdoc/extern-default-method.no_href_on_anchor.html
new file mode 100644
index 000000000..ef14836cc
--- /dev/null
+++ b/tests/rustdoc/extern-default-method.no_href_on_anchor.html
@@ -0,0 +1 @@
+<a class="fn">provided</a>(&amp;self) \ No newline at end of file
diff --git a/tests/rustdoc/extern-default-method.rs b/tests/rustdoc/extern-default-method.rs
new file mode 100644
index 000000000..fc28b230a
--- /dev/null
+++ b/tests/rustdoc/extern-default-method.rs
@@ -0,0 +1,23 @@
+// aux-build:rustdoc-extern-default-method.rs
+// ignore-cross-compile
+// ignore-tidy-linelength
+
+extern crate rustdoc_extern_default_method as ext;
+
+// For this test, the dependency is compiled but not documented.
+//
+// Still, the struct from the external crate and its impl should be documented since
+// the struct is re-exported from this crate.
+// However, the method in the trait impl should *not* have a link (an `href` attribute) to
+// its corresponding item in the trait declaration since it would otherwise be broken.
+//
+// In older versions of rustdoc, the impl item (`a[@class="fn"]`) used to link to
+// `#method.provided` – i.e. "to itself". Put in quotes since that was actually incorrect in
+// general: If the type `Struct` also had an inherent method called `provided`, the impl item
+// would link to that one even though those two methods are distinct items!
+
+// @count extern_default_method/struct.Struct.html '//*[@id="method.provided"]' 1
+// @count extern_default_method/struct.Struct.html '//*[@id="method.provided"]//a[@class="fn"]' 1
+// @snapshot no_href_on_anchor - '//*[@id="method.provided"]//a[@class="fn"]'
+// @has extern_default_method/struct.Struct.html '//*[@id="method.provided"]//a[@class="anchor"]/@href' #method.provided
+pub use ext::Struct;
diff --git a/tests/rustdoc/extern-html-root-url-precedence.rs b/tests/rustdoc/extern-html-root-url-precedence.rs
new file mode 100644
index 000000000..def6767ea
--- /dev/null
+++ b/tests/rustdoc/extern-html-root-url-precedence.rs
@@ -0,0 +1,7 @@
+// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0 --extern-html-root-takes-precedence
+
+// @has extern_html_root_url_precedence/index.html
+// --extern-html-root should take precedence if `--takes-precedence` is passed
+// @has - '//a/@href' 'https://example.com/core/0.1.0/core/iter/index.html'
+#[doc(no_inline)]
+pub use std::iter;
diff --git a/tests/rustdoc/extern-html-root-url.rs b/tests/rustdoc/extern-html-root-url.rs
new file mode 100644
index 000000000..17eedcf2a
--- /dev/null
+++ b/tests/rustdoc/extern-html-root-url.rs
@@ -0,0 +1,18 @@
+// compile-flags:-Z unstable-options --extern-html-root-url html_root=https://example.com/override --extern-html-root-url no_html_root=https://example.com/override
+// aux-build:html_root.rs
+// aux-build:no_html_root.rs
+// NOTE: intentionally does not build any auxiliary docs
+
+extern crate html_root;
+extern crate no_html_root;
+
+// @has extern_html_root_url/index.html
+// `html_root_url` should override `--extern-html-root-url`
+// @has - '//a/@href' 'https://example.com/html_root/html_root/fn.foo.html'
+#[doc(no_inline)]
+pub use html_root::foo;
+
+#[doc(no_inline)]
+// `--extern-html-root-url` should apply if no `html_root_url` is given
+// @has - '//a/@href' 'https://example.com/override/no_html_root/fn.bar.html'
+pub use no_html_root::bar;
diff --git a/tests/rustdoc/extern-impl-trait.rs b/tests/rustdoc/extern-impl-trait.rs
new file mode 100644
index 000000000..8ab026afd
--- /dev/null
+++ b/tests/rustdoc/extern-impl-trait.rs
@@ -0,0 +1,11 @@
+// aux-build:extern-impl-trait.rs
+
+#![crate_name = "foo"]
+
+extern crate extern_impl_trait;
+
+// @has 'foo/struct.X.html' '//h4[@class="code-header"]' "impl Foo<Associated = ()> + 'a"
+pub use extern_impl_trait::X;
+
+// @has 'foo/struct.Y.html' '//h4[@class="code-header"]' "impl ?Sized + Foo<Associated = ()> + 'a"
+pub use extern_impl_trait::Y;
diff --git a/tests/rustdoc/extern-impl.rs b/tests/rustdoc/extern-impl.rs
new file mode 100644
index 000000000..fd1bc2140
--- /dev/null
+++ b/tests/rustdoc/extern-impl.rs
@@ -0,0 +1,27 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+pub struct Foo;
+
+impl Foo {
+ // @has - '//h4[@class="code-header"]' 'fn rust0()'
+ pub fn rust0() {}
+ // @has - '//h4[@class="code-header"]' 'fn rust1()'
+ pub extern "Rust" fn rust1() {}
+ // @has - '//h4[@class="code-header"]' 'extern "C" fn c0()'
+ pub extern fn c0() {}
+ // @has - '//h4[@class="code-header"]' 'extern "C" fn c1()'
+ pub extern "C" fn c1() {}
+ // @has - '//h4[@class="code-header"]' 'extern "system" fn system0()'
+ pub extern "system" fn system0() {}
+}
+
+// @has foo/trait.Bar.html
+pub trait Bar {}
+
+// @has - '//h3[@class="code-header"]' 'impl Bar for fn()'
+impl Bar for fn() {}
+// @has - '//h3[@class="code-header"]' 'impl Bar for extern "C" fn()'
+impl Bar for extern fn() {}
+// @has - '//h3[@class="code-header"]' 'impl Bar for extern "system" fn()'
+impl Bar for extern "system" fn() {}
diff --git a/tests/rustdoc/extern-links.rs b/tests/rustdoc/extern-links.rs
new file mode 100644
index 000000000..0383ccf7d
--- /dev/null
+++ b/tests/rustdoc/extern-links.rs
@@ -0,0 +1,21 @@
+// aux-build:extern-links.rs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+pub extern crate extern_links;
+
+// @!has foo/index.html '//a' 'extern_links'
+#[doc(no_inline)]
+pub use extern_links as extern_links2;
+
+// @!has foo/index.html '//a' 'Foo'
+#[doc(no_inline)]
+pub use extern_links::Foo;
+
+#[doc(hidden)]
+pub mod hidden {
+ // @!has foo/hidden/extern_links/index.html
+ // @!has foo/hidden/extern_links/struct.Foo.html
+ pub use extern_links;
+}
diff --git a/tests/rustdoc/extern-method.rs b/tests/rustdoc/extern-method.rs
new file mode 100644
index 000000000..9cf5fc190
--- /dev/null
+++ b/tests/rustdoc/extern-method.rs
@@ -0,0 +1,19 @@
+// aux-build:rustdoc-extern-method.rs
+// ignore-cross-compile
+
+#![feature(unboxed_closures)]
+
+extern crate rustdoc_extern_method as foo;
+
+// @has extern_method/trait.Foo.html //pre "pub trait Foo"
+// @has - '//*[@id="tymethod.foo"]//h4[@class="code-header"]' 'extern "rust-call" fn foo'
+// @has - '//*[@id="method.foo_"]//h4[@class="code-header"]' 'extern "rust-call" fn foo_'
+pub use foo::Foo;
+
+// @has extern_method/trait.Bar.html //pre "pub trait Bar"
+pub trait Bar {
+ // @has - '//*[@id="tymethod.bar"]//h4[@class="code-header"]' 'extern "rust-call" fn bar'
+ extern "rust-call" fn bar(&self, _: ());
+ // @has - '//*[@id="method.bar_"]//h4[@class="code-header"]' 'extern "rust-call" fn bar_'
+ extern "rust-call" fn bar_(&self, _: ()) { }
+}
diff --git a/tests/rustdoc/external-cross.rs b/tests/rustdoc/external-cross.rs
new file mode 100644
index 000000000..3f8e16882
--- /dev/null
+++ b/tests/rustdoc/external-cross.rs
@@ -0,0 +1,10 @@
+// aux-build:external-cross.rs
+// ignore-cross-compile
+
+#![crate_name="host"]
+
+extern crate external_cross;
+
+// @has host/struct.NeedMoreDocs.html
+// @has - '//h2' 'Cross-crate imported docs'
+pub use external_cross::NeedMoreDocs;
diff --git a/tests/rustdoc/external-doc.rs b/tests/rustdoc/external-doc.rs
new file mode 100644
index 000000000..bd322d67a
--- /dev/null
+++ b/tests/rustdoc/external-doc.rs
@@ -0,0 +1,14 @@
+// @has external_doc/struct.IncludeStrDocs.html
+// @has - '//h2' 'External Docs'
+// @has - '//h3' 'Inline Docs'
+#[doc = include_str!("auxiliary/external-doc.md")]
+/// ## Inline Docs
+pub struct IncludeStrDocs;
+
+macro_rules! dir { () => { "auxiliary" } }
+
+// @has external_doc/struct.EagerExpansion.html
+// @has - '//h2' 'External Docs'
+#[doc = include_str!(concat!(dir!(), "/external-doc.md"))]
+/// ## Inline Docs
+pub struct EagerExpansion;
diff --git a/tests/rustdoc/external-macro-src.rs b/tests/rustdoc/external-macro-src.rs
new file mode 100644
index 000000000..359551ab7
--- /dev/null
+++ b/tests/rustdoc/external-macro-src.rs
@@ -0,0 +1,12 @@
+// aux-build:external-macro-src.rs
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate external_macro_src;
+
+// @has foo/index.html '//a[@href="../src/foo/external-macro-src.rs.html#3-12"]' 'source'
+
+// @has foo/struct.Foo.html
+// @has - '//a[@href="../src/foo/external-macro-src.rs.html#12"]' 'source'
+make_foo!();
diff --git a/tests/rustdoc/feature-gate-doc_auto_cfg.rs b/tests/rustdoc/feature-gate-doc_auto_cfg.rs
new file mode 100644
index 000000000..da76381e4
--- /dev/null
+++ b/tests/rustdoc/feature-gate-doc_auto_cfg.rs
@@ -0,0 +1,8 @@
+#![feature(doc_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @count - '//*[@class="item-info"]/*[@class="stab portability"]' 0
+#[cfg(not(test))]
+pub fn foo() {}
diff --git a/tests/rustdoc/ffi.rs b/tests/rustdoc/ffi.rs
new file mode 100644
index 000000000..8140dfc72
--- /dev/null
+++ b/tests/rustdoc/ffi.rs
@@ -0,0 +1,12 @@
+// aux-build:rustdoc-ffi.rs
+// ignore-cross-compile
+
+extern crate rustdoc_ffi as lib;
+
+// @has ffi/fn.foreigner.html //pre 'pub unsafe extern "C" fn foreigner(cold_as_ice: u32)'
+pub use lib::foreigner;
+
+extern "C" {
+ // @has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)'
+ pub fn another(cold_as_ice: u32);
+}
diff --git a/tests/rustdoc/fn-bound.rs b/tests/rustdoc/fn-bound.rs
new file mode 100644
index 000000000..9e060ff20
--- /dev/null
+++ b/tests/rustdoc/fn-bound.rs
@@ -0,0 +1,21 @@
+// Regression test for #100143
+
+use std::iter::Peekable;
+
+pub struct Span<F: Fn(&i32)> {
+ inner: Peekable<ConditionalIterator<F>>,
+}
+
+pub struct ConditionalIterator<F> {
+ f: F,
+}
+
+
+// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>'
+impl<F: Fn(&i32)> Iterator for ConditionalIterator<F> {
+ type Item = ();
+
+ fn next(&mut self) -> Option<Self::Item> {
+ todo!()
+ }
+}
diff --git a/tests/rustdoc/fn-pointer-arg-name.rs b/tests/rustdoc/fn-pointer-arg-name.rs
new file mode 100644
index 000000000..96c64ac4e
--- /dev/null
+++ b/tests/rustdoc/fn-pointer-arg-name.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+pub fn f(callback: fn(len: usize, foo: u32)) {}
diff --git a/tests/rustdoc/fn-sidebar.rs b/tests/rustdoc/fn-sidebar.rs
new file mode 100644
index 000000000..2fe8ebec1
--- /dev/null
+++ b/tests/rustdoc/fn-sidebar.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html
+// @has - '//*[@class="sidebar-elems"]' ''
+pub fn bar() {}
+
+// @has foo/constant.BAR.html
+// @has - '//*[@class="sidebar-elems"]' ''
+pub const BAR: u32 = 0;
diff --git a/tests/rustdoc/fn-type.rs b/tests/rustdoc/fn-type.rs
new file mode 100644
index 000000000..3959aeb6c
--- /dev/null
+++ b/tests/rustdoc/fn-type.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+#![crate_type = "lib"]
+
+pub struct Foo<'a, T> {
+ pub generic: fn(val: &T) -> T,
+
+ pub lifetime: fn(val: &'a i32) -> i32,
+ pub hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32),
+}
+
+// @has 'foo/struct.Foo.html' '//span[@id="structfield.generic"]' "generic: fn(val: &T) -> T"
+// @has 'foo/struct.Foo.html' '//span[@id="structfield.lifetime"]' "lifetime: fn(val: &'a i32) -> i32"
+// @has 'foo/struct.Foo.html' '//span[@id="structfield.hrtb_lifetime"]' "hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32)"
diff --git a/tests/rustdoc/force-target-feature.rs b/tests/rustdoc/force-target-feature.rs
new file mode 100644
index 000000000..b6c10e834
--- /dev/null
+++ b/tests/rustdoc/force-target-feature.rs
@@ -0,0 +1,11 @@
+// only-x86_64
+// compile-flags:--test -C target-feature=+avx
+// should-fail
+
+/// (written on a spider's web) Some Struct
+///
+/// ```
+/// panic!("oh no");
+/// ```
+#[doc(cfg(target_feature = "avx"))]
+pub struct SomeStruct;
diff --git a/tests/rustdoc/foreigntype-reexport.rs b/tests/rustdoc/foreigntype-reexport.rs
new file mode 100644
index 000000000..1dec0ef3e
--- /dev/null
+++ b/tests/rustdoc/foreigntype-reexport.rs
@@ -0,0 +1,56 @@
+#![feature(extern_types)]
+
+mod sub {
+ extern "C" {
+ /// Another extern type.
+ pub type C2;
+ pub fn f2();
+ pub static K: usize;
+ }
+}
+
+pub mod sub2 {
+ extern "C" {
+ // @has foreigntype_reexport/sub2/foreigntype.C.html
+ pub type C;
+ // @has foreigntype_reexport/sub2/fn.f.html
+ pub fn f();
+ // @has foreigntype_reexport/sub2/static.K3.html
+ pub static K3: usize;
+ }
+}
+
+mod sub3 {
+ extern "C" {
+ pub type C4;
+ pub fn f4();
+ pub static K4: usize;
+ type X4;
+ }
+}
+
+// @has foreigntype_reexport/foreigntype.C2.html
+// @has foreigntype_reexport/fn.f2.html
+// @has foreigntype_reexport/static.K2.html
+// @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C2'
+// @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f2'
+// @has foreigntype_reexport/index.html '//a[@class="static"]' 'K2'
+pub use self::sub::{f2, C2, K as K2};
+
+// @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C'
+// @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f'
+// @has foreigntype_reexport/index.html '//a[@class="static"]' 'K3'
+// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::C as C3;'
+// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::f as f3;'
+// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::K3;'
+pub use self::sub2::{f as f3, C as C3, K3};
+
+// @has foreigntype_reexport/foreigntype.C4.html
+// @has foreigntype_reexport/fn.f4.html
+// @has foreigntype_reexport/static.K4.html
+// @!has foreigntype_reexport/foreigntype.X4.html
+// @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C4'
+// @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f4'
+// @has foreigntype_reexport/index.html '//a[@class="static"]' 'K4'
+// @!has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'X4'
+pub use self::sub3::*;
diff --git a/tests/rustdoc/foreigntype.rs b/tests/rustdoc/foreigntype.rs
new file mode 100644
index 000000000..29f9c2926
--- /dev/null
+++ b/tests/rustdoc/foreigntype.rs
@@ -0,0 +1,18 @@
+#![feature(extern_types)]
+
+extern "C" {
+ // @has foreigntype/foreigntype.ExtType.html
+ pub type ExtType;
+}
+
+impl ExtType {
+ // @has - '//a[@class="fn"]' 'do_something'
+ pub fn do_something(&self) {}
+}
+
+pub trait Trait {}
+
+// @has foreigntype/trait.Trait.html '//a[@class="foreigntype"]' 'ExtType'
+impl Trait for ExtType {}
+
+// @has foreigntype/index.html '//a[@class="foreigntype"]' 'ExtType'
diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs
new file mode 100644
index 000000000..bcead3115
--- /dev/null
+++ b/tests/rustdoc/generic-associated-types/gats.rs
@@ -0,0 +1,33 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.LendingIterator.html
+pub trait LendingIterator {
+ // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a"
+ type Item<'a> where Self: 'a;
+
+ // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \
+ // "fn next<'a>(&'a self) -> Self::Item<'a>"
+ // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]//a[@href="trait.LendingIterator.html#associatedtype.Item"]' \
+ // "Item"
+ fn next<'a>(&'a self) -> Self::Item<'a>;
+}
+
+// @has foo/trait.LendingIterator.html
+// @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item<'a> = ()"
+impl LendingIterator for () {
+ type Item<'a> = ();
+
+ fn next<'a>(&self) -> () {}
+}
+
+pub struct Infinite<T>(T);
+
+// @has foo/trait.LendingIterator.html
+// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T"
+impl<T> LendingIterator for Infinite<T> {
+ type Item<'a> where Self: 'a = &'a T;
+
+ fn next<'a>(&'a self) -> Self::Item<'a> {
+ &self.0
+ }
+}
diff --git a/tests/rustdoc/generic-associated-types/issue-94683.rs b/tests/rustdoc/generic-associated-types/issue-94683.rs
new file mode 100644
index 000000000..985c7e983
--- /dev/null
+++ b/tests/rustdoc/generic-associated-types/issue-94683.rs
@@ -0,0 +1,12 @@
+#![crate_name = "foo"]
+
+pub trait Trait {
+ type Gat<'a>;
+}
+
+// Make sure that the elided lifetime shows up
+
+// @has foo/type.T.html
+// @hasraw - "pub type T = "
+// @hasraw - "&lt;'_&gt;"
+pub type T = fn(&<() as Trait>::Gat<'_>);
diff --git a/tests/rustdoc/generic-impl.rs b/tests/rustdoc/generic-impl.rs
new file mode 100644
index 000000000..6f68b1574
--- /dev/null
+++ b/tests/rustdoc/generic-impl.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+use std::fmt;
+
+// @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' ''
+pub struct Bar;
+
+// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header"]' 'impl<T> ToString for T'
+pub struct Foo;
+// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString'
+
+impl fmt::Display for Foo {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "Foo")
+ }
+}
diff --git a/tests/rustdoc/generic_const_exprs.rs b/tests/rustdoc/generic_const_exprs.rs
new file mode 100644
index 000000000..6ff591639
--- /dev/null
+++ b/tests/rustdoc/generic_const_exprs.rs
@@ -0,0 +1,24 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/92859>.
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+#![crate_name = "foo"]
+
+// @has 'foo/trait.Foo.html'
+
+pub trait Foo: Sized {
+ const WIDTH: usize;
+
+ fn arrayify(self) -> [Self; Self::WIDTH];
+}
+
+impl<T: Sized> Foo for T {
+ const WIDTH: usize = 1;
+
+ // @has - '//*[@id="tymethod.arrayify"]/*[@class="code-header"]' \
+ // 'fn arrayify(self) -> [Self; Self::WIDTH]'
+ fn arrayify(self) -> [Self; Self::WIDTH] {
+ [self]
+ }
+}
diff --git a/tests/rustdoc/glob-shadowing-const.rs b/tests/rustdoc/glob-shadowing-const.rs
new file mode 100644
index 000000000..5b786cf53
--- /dev/null
+++ b/tests/rustdoc/glob-shadowing-const.rs
@@ -0,0 +1,20 @@
+// https://github.com/rust-lang/rust/pull/83872#issuecomment-820101008
+#![crate_name="foo"]
+
+mod sub4 {
+ /// 0
+ pub const X: usize = 0;
+ pub mod inner {
+ pub use super::*;
+ /// 1
+ pub const X: usize = 1;
+ }
+}
+
+#[doc(inline)]
+pub use sub4::inner::*;
+
+// @has 'foo/index.html'
+// @has - '//div[@class="item-right docblock-short"]' '1'
+// @!has - '//div[@class="item-right docblock-short"]' '0'
+fn main() { assert_eq!(X, 1); }
diff --git a/tests/rustdoc/glob-shadowing.rs b/tests/rustdoc/glob-shadowing.rs
new file mode 100644
index 000000000..66a31c42b
--- /dev/null
+++ b/tests/rustdoc/glob-shadowing.rs
@@ -0,0 +1,86 @@
+// @has 'glob_shadowing/index.html'
+// @count - '//div[@class="item-left module-item"]' 6
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe'
+// @has - '//div[@class="item-right docblock-short"]' 'sub2::describe'
+
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe2'
+
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::prelude'
+// @has - '//div[@class="item-right docblock-short"]' 'mod::prelude'
+
+// @has - '//div[@class="item-right docblock-short"]' 'sub1::Foo (struct)'
+// @has - '//div[@class="item-right docblock-short"]' 'mod::Foo (function)'
+
+// @has - '//div[@class="item-right docblock-short"]' 'sub4::inner::X'
+
+// @has 'glob_shadowing/fn.describe.html'
+// @has - '//div[@class="docblock"]' 'sub2::describe'
+
+mod sub1 {
+ // this should be shadowed by sub2::describe
+ /// sub1::describe
+ pub fn describe() -> &'static str {
+ "sub1::describe"
+ }
+
+ // this should be shadowed by mod::prelude
+ /// sub1::prelude
+ pub mod prelude {
+ }
+
+ // this should *not* be shadowed, because sub1::Foo and mod::Foo are in different namespaces
+ /// sub1::Foo (struct)
+ pub struct Foo;
+
+ // this should be shadowed,
+ // because both sub1::describe2 and sub3::describe2 are from glob reexport
+ /// sub1::describe2
+ pub fn describe2() -> &'static str {
+ "sub1::describe2"
+ }
+}
+
+mod sub2 {
+ /// sub2::describe
+ pub fn describe() -> &'static str {
+ "sub2::describe"
+ }
+}
+
+mod sub3 {
+ // this should be shadowed
+ // because both sub1::describe2 and sub3::describe2 are from glob reexport
+ /// sub3::describe2
+ pub fn describe2() -> &'static str {
+ "sub3::describe2"
+ }
+}
+
+mod sub4 {
+ // this should be shadowed by sub4::inner::X
+ /// sub4::X
+ pub const X: usize = 0;
+ pub mod inner {
+ pub use super::*;
+ /// sub4::inner::X
+ pub const X: usize = 1;
+ }
+}
+
+/// mod::Foo (function)
+pub fn Foo() {}
+
+#[doc(inline)]
+pub use sub2::describe;
+
+#[doc(inline)]
+pub use sub1::*;
+
+#[doc(inline)]
+pub use sub3::*;
+
+#[doc(inline)]
+pub use sub4::inner::*;
+
+/// mod::prelude
+pub mod prelude {}
diff --git a/tests/rustdoc/hidden-impls.rs b/tests/rustdoc/hidden-impls.rs
new file mode 100644
index 000000000..26e2e0e06
--- /dev/null
+++ b/tests/rustdoc/hidden-impls.rs
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+mod hidden {
+ #[derive(Clone)]
+ pub struct Foo;
+}
+
+#[doc(hidden)]
+pub mod __hidden {
+ pub use hidden::Foo;
+}
+
+// @has foo/trait.Clone.html
+// @!hasraw - 'Foo'
+// @has implementors/core/clone/trait.Clone.js
+// @!hasraw - 'Foo'
+pub use std::clone::Clone;
diff --git a/tests/rustdoc/hidden-line.rs b/tests/rustdoc/hidden-line.rs
new file mode 100644
index 000000000..00a05a7c2
--- /dev/null
+++ b/tests/rustdoc/hidden-line.rs
@@ -0,0 +1,19 @@
+/// The '# ' lines should be removed from the output, but the #[derive] should be
+/// retained.
+///
+/// ```rust
+/// # #[derive(PartialEq)] // invisible
+/// # struct Foo; // invisible
+///
+/// #[derive(PartialEq)] // Bar
+/// struct Bar(Foo);
+///
+/// fn test() {
+/// let x = Bar(Foo);
+/// assert_eq!(x, x); // check that the derivings worked
+/// }
+/// ```
+pub fn foo() {}
+
+// @!hasraw hidden_line/fn.foo.html invisible
+// @matches - //pre "#\[derive\(PartialEq\)\] // Bar"
diff --git a/tests/rustdoc/hidden-methods.rs b/tests/rustdoc/hidden-methods.rs
new file mode 100644
index 000000000..543d8f768
--- /dev/null
+++ b/tests/rustdoc/hidden-methods.rs
@@ -0,0 +1,29 @@
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub mod hidden {
+ pub struct Foo;
+
+ impl Foo {
+ #[doc(hidden)]
+ pub fn this_should_be_hidden() {}
+ }
+
+ pub struct Bar;
+
+ impl Bar {
+ fn this_should_be_hidden() {}
+ }
+}
+
+// @has foo/struct.Foo.html
+// @!hasraw - 'Methods'
+// @!has - '//code' 'impl Foo'
+// @!hasraw - 'this_should_be_hidden'
+pub use hidden::Foo;
+
+// @has foo/struct.Bar.html
+// @!hasraw - 'Methods'
+// @!has - '//code' 'impl Bar'
+// @!hasraw - 'this_should_be_hidden'
+pub use hidden::Bar;
diff --git a/tests/rustdoc/hidden-trait-methods-with-document-hidden-items.rs b/tests/rustdoc/hidden-trait-methods-with-document-hidden-items.rs
new file mode 100644
index 000000000..95b3e9b65
--- /dev/null
+++ b/tests/rustdoc/hidden-trait-methods-with-document-hidden-items.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Z unstable-options --document-hidden-items
+
+// test for trait methods with `doc(hidden)` with `--document-hidden-items` passed.
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+// @has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @has - '//*[@id="tymethod.f"]' 'fn f()'
+// @has - '//*[@id="tymethod.g"]' 'fn g()'
+pub trait Trait {
+ #[doc(hidden)]
+ type Foo;
+ type Bar;
+ #[doc(hidden)]
+ fn f();
+ fn g();
+}
+
+// @has foo/struct.S.html
+// @has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @has - '//*[@id="method.f"]' 'fn f()'
+// @has - '//*[@id="method.g"]' 'fn g()'
+pub struct S;
+impl Trait for S {
+ type Foo = ();
+ type Bar = ();
+ fn f() {}
+ fn g() {}
+}
diff --git a/tests/rustdoc/hidden-trait-methods.rs b/tests/rustdoc/hidden-trait-methods.rs
new file mode 100644
index 000000000..e924ba7d0
--- /dev/null
+++ b/tests/rustdoc/hidden-trait-methods.rs
@@ -0,0 +1,29 @@
+// test for trait methods with `doc(hidden)`.
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @!has - '//*[@id="tymethod.f"]' 'fn f()'
+// @has - '//*[@id="tymethod.g"]' 'fn g()'
+pub trait Trait {
+ #[doc(hidden)]
+ type Foo;
+ type Bar;
+ #[doc(hidden)]
+ fn f();
+ fn g();
+}
+
+// @has foo/struct.S.html
+// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @!has - '//*[@id="method.f"]' 'fn f()'
+// @has - '//*[@id="method.g"]' 'fn g()'
+pub struct S;
+impl Trait for S {
+ type Foo = ();
+ type Bar = ();
+ fn f() {}
+ fn g() {}
+}
diff --git a/tests/rustdoc/hidden-trait-struct-impls.rs b/tests/rustdoc/hidden-trait-struct-impls.rs
new file mode 100644
index 000000000..cc3f63377
--- /dev/null
+++ b/tests/rustdoc/hidden-trait-struct-impls.rs
@@ -0,0 +1,22 @@
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub trait Foo {}
+
+trait Dark {}
+
+pub trait Bam {}
+
+pub struct Bar;
+
+struct Hidden;
+
+// @!has foo/struct.Bar.html '//*[@id="impl-Foo-for-Bar"]' 'impl Foo for Bar'
+impl Foo for Bar {}
+// @!has foo/struct.Bar.html '//*[@id="impl-Dark-for-Bar"]' 'impl Dark for Bar'
+impl Dark for Bar {}
+// @has foo/struct.Bar.html '//*[@id="impl-Bam-for-Bar"]' 'impl Bam for Bar'
+// @has foo/trait.Bam.html '//*[@id="implementors-list"]' 'impl Bam for Bar'
+impl Bam for Bar {}
+// @!has foo/trait.Bam.html '//*[@id="implementors-list"]' 'impl Bam for Hidden'
+impl Bam for Hidden {}
diff --git a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
new file mode 100644
index 000000000..406157ce2
--- /dev/null
+++ b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
@@ -0,0 +1,82 @@
+// Test that certain unevaluated constant expression arguments that are
+// deemed too verbose or complex and that may leak private or
+// `doc(hidden)` struct fields are not displayed in the documentation.
+//
+// Read the documentation of `rustdoc::clean::utils::print_const_expr`
+// for further details.
+#![feature(const_trait_impl, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// @has hide_complex_unevaluated_const_arguments/trait.Stage.html
+pub trait Stage {
+ // A helper constant that prevents const expressions containing it
+ // from getting fully evaluated since it doesn't have a body and
+ // thus is non-reducible. This allows us to specifically test the
+ // pretty-printing of *unevaluated* consts.
+ const ABSTRACT: usize;
+
+ // Currently considered "overly complex" by the `generic_const_exprs`
+ // feature. If / once this expression kind gets supported, this
+ // unevaluated const expression could leak the private struct field.
+ //
+ // FIXME: Once the line below compiles, make this a test that
+ // ensures that the private field is not printed.
+ //
+ //const ARRAY0: [u8; Struct { private: () } + Self::ABSTRACT];
+
+ // This assoc. const could leak the private assoc. function `Struct::new`.
+ // Ensure that this does not happen.
+ //
+ // @has - '//*[@id="associatedconstant.ARRAY1"]' \
+ // 'const ARRAY1: [u8; { _ }]'
+ const ARRAY1: [u8; Struct::new(/* ... */) + Self::ABSTRACT * 1_000];
+
+ // @has - '//*[@id="associatedconstant.VERBOSE"]' \
+ // 'const VERBOSE: [u16; { _ }]'
+ const VERBOSE: [u16; compute("thing", 9 + 9) * Self::ABSTRACT];
+
+ // Check that we do not leak the private struct field contained within
+ // the path. The output could definitely be improved upon
+ // (e.g. printing sth. akin to `<Self as Helper<{ _ }>>::OUT`) but
+ // right now “safe is safe”.
+ //
+ // @has - '//*[@id="associatedconstant.PATH"]' \
+ // 'const PATH: usize = _'
+ const PATH: usize = <Self as Helper<{ Struct { private: () } }>>::OUT;
+}
+
+const fn compute(input: &str, extra: usize) -> usize {
+ input.len() + extra
+}
+
+pub trait Helper<const S: Struct> {
+ const OUT: usize;
+}
+
+impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St {
+ const OUT: usize = St::ABSTRACT;
+}
+
+// Currently in rustdoc, const arguments are not evaluated in this position
+// and therefore they fall under the realm of `print_const_expr`.
+// If rustdoc gets patched to evaluate const arguments, it is fine to replace
+// this test as long as one can ensure that private fields are not leaked!
+//
+// @has hide_complex_unevaluated_const_arguments/trait.Sub.html \
+// '//div[@class="item-decl"]/pre[@class="rust"]' \
+// 'pub trait Sub: Sup<{ _ }, { _ }> { }'
+pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {}
+
+pub trait Sup<const N: usize, const S: Struct> {}
+
+pub struct Struct { private: () }
+
+impl Struct {
+ const fn new() -> Self { Self { private: () } }
+}
+
+impl const std::ops::Add<usize> for Struct {
+ type Output = usize;
+
+ fn add(self, _: usize) -> usize { 0 }
+}
diff --git a/tests/rustdoc/hide-complex-unevaluated-consts.rs b/tests/rustdoc/hide-complex-unevaluated-consts.rs
new file mode 100644
index 000000000..ba623246a
--- /dev/null
+++ b/tests/rustdoc/hide-complex-unevaluated-consts.rs
@@ -0,0 +1,71 @@
+// Regression test for issue #97933.
+//
+// Test that certain unevaluated constant expressions that are
+// deemed too verbose or complex and that may leak private or
+// `doc(hidden)` struct fields are not displayed in the documentation.
+//
+// Read the documentation of `rustdoc::clean::utils::print_const_expr`
+// for further details.
+
+// @has hide_complex_unevaluated_consts/trait.Container.html
+pub trait Container {
+ // A helper constant that prevents const expressions containing it
+ // from getting fully evaluated since it doesn't have a body and
+ // thus is non-reducible. This allows us to specifically test the
+ // pretty-printing of *unevaluated* consts.
+ const ABSTRACT: i32;
+
+ // Ensure that the private field does not get leaked:
+ //
+ // @has - '//*[@id="associatedconstant.STRUCT0"]' \
+ // 'const STRUCT0: Struct = _'
+ const STRUCT0: Struct = Struct { private: () };
+
+ // @has - '//*[@id="associatedconstant.STRUCT1"]' \
+ // 'const STRUCT1: (Struct,) = _'
+ const STRUCT1: (Struct,) = (Struct{private: /**/()},);
+
+ // Although the struct field is public here, check that it is not
+ // displayed. In a future version of rustdoc, we definitely want to
+ // show it. However for the time being, the printing logic is a bit
+ // conservative.
+ //
+ // @has - '//*[@id="associatedconstant.STRUCT2"]' \
+ // 'const STRUCT2: Record = _'
+ const STRUCT2: Record = Record { public: 5 };
+
+ // Test that we do not show the incredibly verbose match expr:
+ //
+ // @has - '//*[@id="associatedconstant.MATCH0"]' \
+ // 'const MATCH0: i32 = _'
+ const MATCH0: i32 = match 234 {
+ 0 => 1,
+ _ => Self::ABSTRACT,
+ };
+
+ // @has - '//*[@id="associatedconstant.MATCH1"]' \
+ // 'const MATCH1: bool = _'
+ const MATCH1: bool = match Self::ABSTRACT {
+ _ => true,
+ };
+
+ // Check that we hide complex (arithmetic) operations.
+ // In this case, it is a bit unfortunate since the expression
+ // is not *that* verbose and it might be quite useful to the reader.
+ //
+ // However in general, the expression might be quite large and
+ // contain match expressions and structs with private fields.
+ // We would need to recurse over the whole expression and even more
+ // importantly respect operator precedence when pretty-printing
+ // the potentially partially censored expression.
+ // For now, the implementation is quite simple and the choices
+ // rather conservative.
+ //
+ // @has - '//*[@id="associatedconstant.ARITH_OPS"]' \
+ // 'const ARITH_OPS: i32 = _'
+ const ARITH_OPS: i32 = Self::ABSTRACT * 2 + 1;
+}
+
+pub struct Struct { private: () }
+
+pub struct Record { pub public: i32 }
diff --git a/tests/rustdoc/hide-unstable-trait.rs b/tests/rustdoc/hide-unstable-trait.rs
new file mode 100644
index 000000000..0bf7cabc4
--- /dev/null
+++ b/tests/rustdoc/hide-unstable-trait.rs
@@ -0,0 +1,11 @@
+// aux-build:unstable-trait.rs
+
+#![crate_name = "foo"]
+#![feature(private_trait)]
+
+extern crate unstable_trait;
+
+// @hasraw foo/struct.Foo.html 'bar'
+// @hasraw foo/struct.Foo.html 'bar2'
+#[doc(inline)]
+pub use unstable_trait::Foo;
diff --git a/tests/rustdoc/higher-ranked-trait-bounds.rs b/tests/rustdoc/higher-ranked-trait-bounds.rs
new file mode 100644
index 000000000..3493ae6d2
--- /dev/null
+++ b/tests/rustdoc/higher-ranked-trait-bounds.rs
@@ -0,0 +1,61 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+pub trait Trait<'x> {}
+
+// @has foo/fn.test1.html
+// @has - '//pre' "pub fn test1<T>()where for<'a> &'a T: Iterator,"
+pub fn test1<T>()
+where
+ for<'a> &'a T: Iterator,
+{
+}
+
+// @has foo/fn.test2.html
+// @has - '//pre' "pub fn test2<T>()where for<'a, 'b> &'a T: Trait<'b>,"
+pub fn test2<T>()
+where
+ for<'a, 'b> &'a T: Trait<'b>,
+{
+}
+
+// @has foo/fn.test3.html
+// @has - '//pre' "pub fn test3<F>()where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
+pub fn test3<F>()
+where
+ F: for<'a, 'b> Fn(&'a u8, &'b u8),
+{
+}
+
+// @has foo/struct.Foo.html
+pub struct Foo<'a> {
+ _x: &'a u8,
+ pub some_trait: &'a dyn for<'b> Trait<'b>,
+ pub some_func: for<'c> fn(val: &'c i32) -> i32,
+}
+
+// @has - '//span[@id="structfield.some_func"]' "some_func: for<'c> fn(val: &'c i32) -> i32"
+// @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>"
+
+impl<'a> Foo<'a> {
+ // @has - '//h4[@class="code-header"]' "pub fn bar<T>()where T: Trait<'a>,"
+ pub fn bar<T>()
+ where
+ T: Trait<'a>,
+ {
+ }
+}
+
+// @has foo/trait.B.html
+pub trait B<'x> {}
+
+// @has - '//h3[@class="code-header"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
+impl<'a> B<'a> for dyn for<'b> Trait<'b> {}
+
+// @has foo/struct.Bar.html
+// @has - '//span[@id="structfield.bar"]' "bar: &'a (dyn for<'b> Trait<'b> + Unpin)"
+// @has - '//span[@id="structfield.baz"]' "baz: &'a (dyn Unpin + for<'b> Trait<'b>)"
+pub struct Bar<'a> {
+ pub bar: &'a (dyn for<'b> Trait<'b> + Unpin),
+ pub baz: &'a (dyn Unpin + for<'b> Trait<'b>),
+}
diff --git a/tests/rustdoc/impl-box.rs b/tests/rustdoc/impl-box.rs
new file mode 100644
index 000000000..592b6c985
--- /dev/null
+++ b/tests/rustdoc/impl-box.rs
@@ -0,0 +1,16 @@
+// https://github.com/rust-lang/rust/issues/92940
+//
+// Show traits implemented on fundamental types that wrap local ones.
+
+pub struct MyType;
+
+// @has 'impl_box/struct.MyType.html'
+// @has '-' '//*[@id="impl-Iterator-for-Box%3CMyType%3E"]' 'impl Iterator for Box<MyType>'
+
+impl Iterator for Box<MyType> {
+ type Item = ();
+
+ fn next(&mut self) -> Option<Self::Item> {
+ todo!()
+ }
+}
diff --git a/tests/rustdoc/impl-disambiguation.rs b/tests/rustdoc/impl-disambiguation.rs
new file mode 100644
index 000000000..9e74ede8f
--- /dev/null
+++ b/tests/rustdoc/impl-disambiguation.rs
@@ -0,0 +1,30 @@
+#![crate_name = "foo"]
+
+pub trait Foo {}
+
+pub struct Bar<T> { field: T }
+
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl Foo for Bar<u8>"
+impl Foo for Bar<u8> {}
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl Foo for Bar<u16>"
+impl Foo for Bar<u16> {}
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl<'a> Foo for &'a Bar<u8>"
+impl<'a> Foo for &'a Bar<u8> {}
+
+pub mod mod1 {
+ pub struct Baz {}
+}
+
+pub mod mod2 {
+ pub enum Baz {}
+}
+
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl Foo for foo::mod1::Baz"
+impl Foo for mod1::Baz {}
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl<'a> Foo for &'a foo::mod2::Baz"
+impl<'a> Foo for &'a mod2::Baz {}
diff --git a/tests/rustdoc/impl-everywhere.rs b/tests/rustdoc/impl-everywhere.rs
new file mode 100644
index 000000000..44885d430
--- /dev/null
+++ b/tests/rustdoc/impl-everywhere.rs
@@ -0,0 +1,30 @@
+#![crate_name = "foo"]
+
+pub trait Foo {}
+pub trait Foo2 {}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+impl Foo2 for Bar {}
+
+// @has foo/fn.foo.html '//section[@id="main-content"]//pre' "x: &'x impl Foo"
+// @has foo/fn.foo.html '//section[@id="main-content"]//pre' "-> &'x impl Foo"
+pub fn foo<'x>(x: &'x impl Foo) -> &'x impl Foo {
+ x
+}
+
+// @has foo/fn.foo2.html '//section[@id="main-content"]//pre' "x: &'x impl Foo"
+// @has foo/fn.foo2.html '//section[@id="main-content"]//pre' '-> impl Foo2'
+pub fn foo2<'x>(_x: &'x impl Foo) -> impl Foo2 {
+ Bar
+}
+
+// @has foo/fn.foo_foo.html '//section[@id="main-content"]//pre' '-> impl Foo + Foo2'
+pub fn foo_foo() -> impl Foo + Foo2 {
+ Bar
+}
+
+// @has foo/fn.foo_foo_foo.html '//section[@id="main-content"]//pre' "x: &'x impl Foo + Foo2"
+pub fn foo_foo_foo<'x>(_x: &'x (impl Foo + Foo2)) {
+}
diff --git a/tests/rustdoc/impl-parts-crosscrate.rs b/tests/rustdoc/impl-parts-crosscrate.rs
new file mode 100644
index 000000000..34733f1f8
--- /dev/null
+++ b/tests/rustdoc/impl-parts-crosscrate.rs
@@ -0,0 +1,20 @@
+// aux-build:rustdoc-impl-parts-crosscrate.rs
+// ignore-cross-compile
+
+#![feature(negative_impls)]
+
+extern crate rustdoc_impl_parts_crosscrate;
+
+pub struct Bar<T> { t: T }
+
+// The output file is html embedded in javascript, so the html tags
+// aren't stripped by the processing script and we can't check for the
+// full impl string. Instead, just make sure something from each part
+// is mentioned.
+
+// @hasraw implementors/rustdoc_impl_parts_crosscrate/trait.AnAutoTrait.js Bar
+// @hasraw - Send
+// @hasraw - !AnAutoTrait
+// @hasraw - Copy
+impl<T: Send> !rustdoc_impl_parts_crosscrate::AnAutoTrait for Bar<T>
+ where T: Copy {}
diff --git a/tests/rustdoc/impl-parts.rs b/tests/rustdoc/impl-parts.rs
new file mode 100644
index 000000000..90cbb77cb
--- /dev/null
+++ b/tests/rustdoc/impl-parts.rs
@@ -0,0 +1,12 @@
+#![feature(negative_impls)]
+#![feature(auto_traits)]
+
+pub auto trait AnAutoTrait {}
+
+pub struct Foo<T> { field: T }
+
+// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
+// @has impl_parts/trait.AnAutoTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
+impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}
diff --git a/tests/rustdoc/impl-trait-alias.rs b/tests/rustdoc/impl-trait-alias.rs
new file mode 100644
index 000000000..4f681c78e
--- /dev/null
+++ b/tests/rustdoc/impl-trait-alias.rs
@@ -0,0 +1,14 @@
+#![feature(type_alias_impl_trait)]
+
+trait MyTrait {}
+impl MyTrait for i32 {}
+
+// @hasraw impl_trait_alias/type.Foo.html 'Foo'
+/// debug type
+pub type Foo = impl MyTrait;
+
+// @hasraw impl_trait_alias/fn.foo.html 'foo'
+/// debug function
+pub fn foo() -> Foo {
+ 1
+}
diff --git a/tests/rustdoc/implementor-stable-version.rs b/tests/rustdoc/implementor-stable-version.rs
new file mode 100644
index 000000000..a1f3fd5a8
--- /dev/null
+++ b/tests/rustdoc/implementor-stable-version.rs
@@ -0,0 +1,21 @@
+#![stable(feature = "bar", since = "OLD 1.0")]
+#![crate_name = "foo"]
+
+#![feature(staged_api)]
+
+#[stable(feature = "bar", since = "OLD 1.0")]
+pub trait Bar {}
+
+#[stable(feature = "baz", since = "OLD 1.0")]
+pub trait Baz {}
+
+#[stable(feature = "baz", since = "OLD 1.0")]
+pub struct Foo;
+
+// @has foo/trait.Bar.html '//div[@id="implementors-list"]//span[@class="since"]' 'NEW 2.0'
+#[stable(feature = "foobar", since = "NEW 2.0")]
+impl Bar for Foo {}
+
+// @!has foo/trait.Baz.html '//div[@id="implementors-list"]//span[@class="since"]' 'OLD 1.0'
+#[stable(feature = "foobaz", since = "OLD 1.0")]
+impl Baz for Foo {}
diff --git a/tests/rustdoc/impossible-default.rs b/tests/rustdoc/impossible-default.rs
new file mode 100644
index 000000000..24d6e3bda
--- /dev/null
+++ b/tests/rustdoc/impossible-default.rs
@@ -0,0 +1,20 @@
+#![crate_name = "foo"]
+
+// Check that default trait items that are impossible to satisfy
+
+pub trait Foo {
+ fn needs_sized(&self)
+ where
+ Self: Sized,
+ {}
+
+ fn no_needs_sized(&self) {}
+}
+
+// @!has foo/struct.Bar.html '//*[@id="method.needs_sized"]//h4[@class="code-header"]' \
+// "fn needs_sized"
+// @has foo/struct.Bar.html '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' \
+// "fn no_needs_sized"
+pub struct Bar([u8]);
+
+impl Foo for Bar {}
diff --git a/tests/rustdoc/include_str_cut.rs b/tests/rustdoc/include_str_cut.rs
new file mode 100644
index 000000000..cbc1ba8db
--- /dev/null
+++ b/tests/rustdoc/include_str_cut.rs
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![no_std]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock"]' 'inc2 x'
+#[doc = include_str!("short-line.md")]
+pub fn foo() {}
diff --git a/tests/rustdoc/index-page.rs b/tests/rustdoc/index-page.rs
new file mode 100644
index 000000000..fc755afda
--- /dev/null
+++ b/tests/rustdoc/index-page.rs
@@ -0,0 +1,11 @@
+// aux-build:all-item-types.rs
+// build-aux-docs
+// compile-flags: -Z unstable-options --enable-index-page
+
+#![crate_name = "foo"]
+
+// @has foo/../index.html
+// @has - '//h1' 'List of all crates'
+// @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo'
+// @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types'
+pub struct Foo;
diff --git a/tests/rustdoc/infinite-redirection.rs b/tests/rustdoc/infinite-redirection.rs
new file mode 100644
index 000000000..f037a8e1a
--- /dev/null
+++ b/tests/rustdoc/infinite-redirection.rs
@@ -0,0 +1,29 @@
+#![crate_name = "foo"]
+
+// This test ensures that there is no "infinite redirection" file generated (a
+// file which redirects to itself).
+
+// We check it's not a redirection file.
+// @has 'foo/builders/struct.ActionRowBuilder.html'
+// @has - '//*[@id="synthetic-implementations"]' 'Auto Trait Implementations'
+
+// And that the link in the module is targeting it.
+// @has 'foo/builders/index.html'
+// @has - '//a[@href="struct.ActionRowBuilder.html"]' 'ActionRowBuilder'
+
+mod auto {
+ mod action_row {
+ pub struct ActionRowBuilder;
+ }
+
+ #[doc(hidden)]
+ pub mod builders {
+ pub use super::action_row::ActionRowBuilder;
+ }
+}
+
+pub use auto::*;
+
+pub mod builders {
+ pub use crate::auto::builders::*;
+}
diff --git a/tests/rustdoc/inline-default-methods.rs b/tests/rustdoc/inline-default-methods.rs
new file mode 100644
index 000000000..a4ca928f3
--- /dev/null
+++ b/tests/rustdoc/inline-default-methods.rs
@@ -0,0 +1,9 @@
+// aux-build:inline-default-methods.rs
+// ignore-cross-compile
+
+extern crate inline_default_methods;
+
+// @has inline_default_methods/trait.Foo.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(&mut self) { ... }'
+pub use inline_default_methods::Foo;
diff --git a/tests/rustdoc/inline_cross/add-docs.rs b/tests/rustdoc/inline_cross/add-docs.rs
new file mode 100644
index 000000000..a1124d209
--- /dev/null
+++ b/tests/rustdoc/inline_cross/add-docs.rs
@@ -0,0 +1,9 @@
+// aux-build:add-docs.rs
+
+extern crate inner;
+
+
+// @has add_docs/struct.MyStruct.html
+// @hasraw add_docs/struct.MyStruct.html "Doc comment from ‘pub use’, Doc comment from definition"
+/// Doc comment from 'pub use',
+pub use inner::MyStruct;
diff --git a/tests/rustdoc/inline_cross/assoc-items.rs b/tests/rustdoc/inline_cross/assoc-items.rs
new file mode 100644
index 000000000..811827a17
--- /dev/null
+++ b/tests/rustdoc/inline_cross/assoc-items.rs
@@ -0,0 +1,42 @@
+// aux-build:assoc-items.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate assoc_items;
+
+// @has foo/struct.MyStruct.html
+// @!hasraw - 'PrivateConst'
+// @has - '//*[@id="associatedconstant.PublicConst"]' 'pub const PublicConst: u8'
+// @has - '//*[@class="docblock"]' 'docs for PublicConst'
+// @!hasraw - 'private_method'
+// @has - '//*[@id="method.public_method"]' 'pub fn public_method()'
+// @has - '//*[@class="docblock"]' 'docs for public_method'
+// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16'
+// @has - '//*[@class="docblock"]' 'dox for ConstNoDefault'
+// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16'
+// @has - '//div[@class="docblock"]' 'docs for ConstWithDefault'
+// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault = i32'
+// @has - '//*[@class="docblock"]' 'dox for TypeNoDefault'
+// @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32'
+// @has - '//div[@class="docblock"]' 'docs for TypeWithDefault'
+// @has - '//*[@id="method.method_no_default"]' 'fn method_no_default()'
+// @has - '//*[@class="docblock"]' 'dox for method_no_default'
+// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()'
+// @has - '//div[@class="docblock"]' 'docs for method_with_default'
+pub use assoc_items::MyStruct;
+
+// @has foo/trait.MyTrait.html
+// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16'
+// @has - '//*[@class="docblock"]' 'docs for ConstNoDefault'
+// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16'
+// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault'
+// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault'
+// @has - '//*[@class="docblock"]' 'docs for TypeNoDefault'
+// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault'
+// @has - '//*[@id="tymethod.method_no_default"]' 'fn method_no_default()'
+// @has - '//*[@class="docblock"]' 'docs for method_no_default'
+// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()'
+// @has - '//*[@class="docblock"]' 'docs for method_with_default'
+pub use assoc_items::MyTrait;
diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
new file mode 100644
index 000000000..8934bc1ee
--- /dev/null
+++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4> \ No newline at end of file
diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
new file mode 100644
index 000000000..bf330670e
--- /dev/null
+++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out2" class="associatedtype">Out2</a>&lt;T&gt;: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = T&gt;</h4> \ No newline at end of file
diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
new file mode 100644
index 000000000..69d84e1b2
--- /dev/null
+++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out9" class="associatedtype">Out9</a>: <a class="trait" href="{{channel}}/core/ops/function/trait.FnMut.html" title="trait core::ops::function::FnMut">FnMut</a>(<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.bool.html">bool</a> + <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a></h4> \ No newline at end of file
diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs
new file mode 100644
index 000000000..db2491b87
--- /dev/null
+++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs
@@ -0,0 +1,44 @@
+// Regression test for issues #77763, #84579 and #102142.
+#![crate_name = "main"]
+
+// aux-build:assoc_item_trait_bounds.rs
+// build-aux-docs
+// ignore-cross-compile
+extern crate assoc_item_trait_bounds as aux;
+
+// @has main/trait.Main.html
+// @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support<Item = ()>'
+// @has - '//*[@id="associatedtype.Out1"]' 'type Out1: Support<Item = Self::Item>'
+// @has - '//*[@id="associatedtype.Out2"]' 'type Out2<T>: Support<Item = T>'
+// @has - '//*[@id="associatedtype.Out3"]' 'type Out3: Support<Produce<()> = bool>'
+// @has - '//*[@id="associatedtype.Out4"]' 'type Out4<T>: Support<Produce<T> = T>'
+// @has - '//*[@id="associatedtype.Out5"]' "type Out5: Support<Output<'static> = &'static ()>"
+// @has - '//*[@id="associatedtype.Out6"]' "type Out6: for<'a> Support<Output<'a> = &'a ()>"
+// @has - '//*[@id="associatedtype.Out7"]' "type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated"
+// @has - '//*[@id="associatedtype.Out8"]' "type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>"
+// @has - '//*[@id="associatedtype.Out9"]' "type Out9: FnMut(i32) -> bool + Clone"
+// @has - '//*[@id="associatedtype.Out10"]' "type Out10<'q>: Support<Output<'q> = ()>"
+// @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>"
+// @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>"
+// @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>"
+// @has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>"
+//
+// Snapshots:
+// Check that we don't render any where-clauses for the following associated types since
+// all corresponding projection equality predicates should have already been re-sugared
+// to associated type bindings:
+//
+// @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]'
+// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]'
+// @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]'
+//
+// @has - '//*[@id="tymethod.make"]' \
+// "fn make<F>(_: F, _: impl FnMut(&str) -> bool)\
+// where \
+// F: FnOnce(u32) -> String, \
+// Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>"
+pub use aux::Main;
+
+// @has main/trait.Aid.html
+// @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>"
+pub use aux::Aid;
diff --git a/tests/rustdoc/inline_cross/auxiliary/add-docs.rs b/tests/rustdoc/inline_cross/auxiliary/add-docs.rs
new file mode 100644
index 000000000..85efa508f
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/add-docs.rs
@@ -0,0 +1,4 @@
+#![crate_name = "inner"]
+
+/// Doc comment from definition
+pub struct MyStruct;
diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc-items.rs b/tests/rustdoc/inline_cross/auxiliary/assoc-items.rs
new file mode 100644
index 000000000..5fa299914
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/assoc-items.rs
@@ -0,0 +1,38 @@
+#![feature(associated_type_defaults)]
+
+pub struct MyStruct;
+
+impl MyStruct {
+ /// docs for PrivateConst
+ const PrivateConst: i8 = -123;
+ /// docs for PublicConst
+ pub const PublicConst: u8 = 123;
+ /// docs for private_method
+ fn private_method() {}
+ /// docs for public_method
+ pub fn public_method() {}
+}
+
+pub trait MyTrait {
+ /// docs for ConstNoDefault
+ const ConstNoDefault: i16;
+ /// docs for ConstWithDefault
+ const ConstWithDefault: u16 = 12345;
+ /// docs for TypeNoDefault
+ type TypeNoDefault;
+ /// docs for TypeWithDefault
+ type TypeWithDefault = u32;
+ /// docs for method_no_default
+ fn method_no_default();
+ /// docs for method_with_default
+ fn method_with_default() {}
+}
+
+impl MyTrait for MyStruct {
+ /// dox for ConstNoDefault
+ const ConstNoDefault: i16 = -12345;
+ /// dox for TypeNoDefault
+ type TypeNoDefault = i32;
+ /// dox for method_no_default
+ fn method_no_default() {}
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
new file mode 100644
index 000000000..6644c8e41
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -0,0 +1,46 @@
+pub trait Main {
+ type Item;
+
+ type Out0: Support<Item = ()>;
+ type Out1: Support<Item = Self::Item>;
+ type Out2<T>: Support<Item = T>;
+ type Out3: Support<Produce<()> = bool>;
+ type Out4<T>: Support<Produce<T> = T>;
+ type Out5: Support<Output<'static> = &'static ()>;
+ type Out6: for<'a> Support<Output<'a> = &'a ()>;
+ type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated;
+ type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>;
+ type Out9: FnMut(i32) -> bool + Clone;
+ type Out10<'q>: Support<Output<'q> = ()>;
+ type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>;
+ type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>;
+ type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>;
+ type Out14<P: Copy + Eq, Q: ?Sized>;
+
+ fn make<F>(_: F, _: impl FnMut(&str) -> bool)
+ where
+ F: FnOnce(u32) -> String,
+ Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>;
+}
+
+pub trait Support {
+ type Item;
+ type Output<'a>;
+ type Produce<T>;
+}
+
+pub trait Protocol<K> {
+ type Q0;
+ type Q1;
+}
+
+pub trait Unrelated {}
+
+pub trait Helper {
+ type A<'q>;
+ type B<'q>;
+}
+
+pub trait Aid<'src> {
+ type Result<'inter: 'src>;
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs b/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs
new file mode 100644
index 000000000..48672590a
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs
@@ -0,0 +1,7 @@
+#![crate_name = "inner"]
+
+pub struct SomeStruct;
+
+pub fn some_fn() {}
+
+pub enum Shadowed {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/default-trait-method.rs b/tests/rustdoc/inline_cross/auxiliary/default-trait-method.rs
new file mode 100644
index 000000000..ce60bbfb4
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/default-trait-method.rs
@@ -0,0 +1,16 @@
+#![feature(specialization)]
+
+#![crate_name = "foo"]
+
+pub trait Item {
+ fn foo();
+ fn bar();
+ fn baz() {}
+}
+
+pub struct Foo;
+
+impl Item for Foo {
+ default fn foo() {}
+ fn bar() {}
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs b/tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs
new file mode 100644
index 000000000..9ac2e3d96
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs
@@ -0,0 +1,17 @@
+pub type Ty0 = dyn for<'any> FnOnce(&'any str) -> bool;
+
+pub type Ty1<'obj> = dyn std::fmt::Display + 'obj;
+
+pub type Ty2 = dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>;
+
+pub type Ty3<'s> = &'s dyn ToString;
+
+pub fn func0(_: &(dyn Fn() + '_)) {}
+
+pub fn func1<'func>(_: &(dyn Fn() + 'func)) {}
+
+pub trait Container<'r> {
+ type Item<'a, 'ctx>;
+}
+
+pub trait Shape<'a> {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs b/tests/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs
new file mode 100644
index 000000000..401a6a44a
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs
@@ -0,0 +1,8 @@
+pub trait MyTrait {
+ /// docs for my_trait_method
+ fn my_trait_method() {}
+}
+
+pub struct MyStruct;
+
+impl MyTrait for MyStruct {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
new file mode 100644
index 000000000..19433c968
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
@@ -0,0 +1,41 @@
+// edition:2018
+
+use std::ops::Deref;
+
+pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
+
+pub fn func2<T>(
+ _x: impl Deref<Target = Option<T>> + Iterator<Item = T>,
+ _y: impl Iterator<Item = u8>,
+) {}
+
+pub fn func3(_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone) {}
+
+pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
+
+pub fn func5(
+ _f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,
+ _a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
+) {}
+
+pub trait Other {
+ type T<'dependency>;
+}
+
+pub trait Auxiliary<'arena> {
+ type Item<'input>;
+}
+
+pub async fn async_fn() {}
+
+pub struct Foo;
+
+impl Foo {
+ pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
+}
+
+pub struct Bar;
+
+impl Bar {
+ pub async fn async_foo(&self) {}
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/implementors_inline.rs b/tests/rustdoc/inline_cross/auxiliary/implementors_inline.rs
new file mode 100644
index 000000000..b003fb357
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/implementors_inline.rs
@@ -0,0 +1,18 @@
+pub mod my_trait {
+ pub trait MyTrait {
+ fn my_fn(&self) -> Self;
+ }
+}
+
+pub mod prelude {
+ #[doc(inline)]
+ pub use crate::my_trait::MyTrait;
+}
+
+pub struct SomeStruct;
+
+impl my_trait::MyTrait for SomeStruct {
+ fn my_fn(&self) -> SomeStruct {
+ SomeStruct
+ }
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/issue-24183.rs b/tests/rustdoc/inline_cross/auxiliary/issue-24183.rs
new file mode 100644
index 000000000..e7a13acc6
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-24183.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+
+pub trait U/*: ?Sized */ {
+ fn modified(self) -> Self
+ where
+ Self: Sized
+ {
+ self
+ }
+
+ fn touch(&self)/* where Self: ?Sized */{}
+}
+
+pub trait S: Sized {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/issue-33113.rs b/tests/rustdoc/inline_cross/auxiliary/issue-33113.rs
new file mode 100644
index 000000000..4e1f1918e
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-33113.rs
@@ -0,0 +1,7 @@
+#![crate_name="bar"]
+
+pub trait Bar {}
+pub struct Foo;
+
+impl<'a> Bar for &'a char {}
+impl Bar for Foo {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/macro-vis.rs b/tests/rustdoc/inline_cross/auxiliary/macro-vis.rs
new file mode 100644
index 000000000..5615a4fdd
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/macro-vis.rs
@@ -0,0 +1,25 @@
+#![crate_name = "qwop"]
+
+/// (written on a spider's web) Some Macro
+#[macro_export]
+macro_rules! some_macro {
+ () => {
+ println!("this is some macro, for sure");
+ };
+}
+
+/// Some other macro, to fill space.
+#[macro_export]
+macro_rules! other_macro {
+ () => {
+ println!("this is some other macro, whatev");
+ };
+}
+
+/// This macro is so cool, it's Super.
+#[macro_export]
+macro_rules! super_macro {
+ () => {
+ println!("is it a bird? a plane? no, it's Super Macro!");
+ };
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/macros.rs b/tests/rustdoc/inline_cross/auxiliary/macros.rs
new file mode 100644
index 000000000..651ae2f1a
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/macros.rs
@@ -0,0 +1,10 @@
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+/// docs for my_macro
+#[unstable(feature = "macro_test", issue = "none")]
+#[deprecated(since = "1.2.3", note = "text")]
+#[macro_export]
+macro_rules! my_macro {
+ () => {};
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/proc_macro.rs b/tests/rustdoc/inline_cross/auxiliary/proc_macro.rs
new file mode 100644
index 000000000..d8e5746f3
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/proc_macro.rs
@@ -0,0 +1,47 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+
+#![crate_type="proc-macro"]
+#![crate_name="some_macros"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+macro_rules! make_attr_macro {
+ ($name:ident) => {
+ /// Generated doc comment
+ #[proc_macro_attribute]
+ pub fn $name(args: TokenStream, input: TokenStream) -> TokenStream {
+ panic!()
+ }
+ }
+}
+
+make_attr_macro!(first_attr);
+make_attr_macro!(second_attr);
+
+/// a proc-macro that swallows its input and does nothing.
+#[proc_macro]
+pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+/// a proc-macro attribute that passes its item through verbatim.
+#[proc_macro_attribute]
+pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ item
+}
+
+/// a derive attribute that adds nothing to its input.
+#[proc_macro_derive(SomeDerive)]
+pub fn some_derive(_item: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+/// Doc comment from the original crate
+#[proc_macro]
+pub fn reexported_macro(_input: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/renamed-via-module.rs b/tests/rustdoc/inline_cross/auxiliary/renamed-via-module.rs
new file mode 100644
index 000000000..2e5290782
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/renamed-via-module.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+pub mod iter {
+ mod range {
+ pub struct StepBy;
+ }
+ pub use self::range::StepBy as DeprecatedStepBy;
+ pub struct StepBy;
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden-sig.rs b/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden-sig.rs
new file mode 100644
index 000000000..6357b76df
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden-sig.rs
@@ -0,0 +1,12 @@
+pub struct Bar;
+
+impl Bar {
+ pub fn bar(_: u8) -> hidden::Hidden {
+ hidden::Hidden
+ }
+}
+
+#[doc(hidden)]
+pub mod hidden {
+ pub struct Hidden;
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden.rs b/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden.rs
new file mode 100644
index 000000000..0c75b3127
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/rustdoc-hidden.rs
@@ -0,0 +1,4 @@
+#[doc(hidden)]
+pub struct Foo;
+
+pub struct Bar;
diff --git a/tests/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs b/tests/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs
new file mode 100644
index 000000000..4e461d3bc
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs
@@ -0,0 +1,34 @@
+pub struct Foo;
+
+pub trait Woof {}
+pub trait Bark {}
+
+mod private {
+ // should be shown
+ impl ::Woof for ::Foo {}
+
+ pub trait Bar {}
+ pub struct Wibble;
+
+ // these should not be shown
+ impl Bar for ::Foo {}
+ impl Bar for Wibble {}
+ impl ::Bark for Wibble {}
+ impl ::Woof for Wibble {}
+}
+
+#[doc(hidden)]
+pub mod hidden {
+ // should be shown
+ impl ::Bark for ::Foo {}
+
+ pub trait Qux {}
+ pub struct Wobble;
+
+
+ // these should only be shown if they're re-exported correctly
+ impl Qux for ::Foo {}
+ impl Qux for Wobble {}
+ impl ::Bark for Wobble {}
+ impl ::Woof for Wobble {}
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/rustdoc-trait-object-impl.rs b/tests/rustdoc/inline_cross/auxiliary/rustdoc-trait-object-impl.rs
new file mode 100644
index 000000000..11d8733c4
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/rustdoc-trait-object-impl.rs
@@ -0,0 +1,13 @@
+use std::fmt;
+
+pub trait Bar {}
+
+impl<'a> Bar + 'a {
+ pub fn bar(&self) -> usize { 42 }
+}
+
+impl<'a> fmt::Debug for Bar + 'a {
+ fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+ Ok(())
+ }
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/trait-vis.rs b/tests/rustdoc/inline_cross/auxiliary/trait-vis.rs
new file mode 100644
index 000000000..e5bc7969b
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/trait-vis.rs
@@ -0,0 +1,13 @@
+#![crate_name = "inner"]
+
+pub struct SomeStruct;
+
+fn asdf() {
+ const _FOO: () = {
+ impl Clone for SomeStruct {
+ fn clone(&self) -> Self {
+ SomeStruct
+ }
+ }
+ };
+}
diff --git a/tests/rustdoc/inline_cross/auxiliary/use_crate.rs b/tests/rustdoc/inline_cross/auxiliary/use_crate.rs
new file mode 100644
index 000000000..75efbe0db
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/use_crate.rs
@@ -0,0 +1,5 @@
+pub mod asdf {
+ pub struct SomeStruct;
+}
+
+pub trait SomeTrait {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/use_crate_2.rs b/tests/rustdoc/inline_cross/auxiliary/use_crate_2.rs
new file mode 100644
index 000000000..25b4c202e
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/use_crate_2.rs
@@ -0,0 +1 @@
+pub struct SomethingElse;
diff --git a/tests/rustdoc/inline_cross/cross-glob.rs b/tests/rustdoc/inline_cross/cross-glob.rs
new file mode 100644
index 000000000..7a519d2d2
--- /dev/null
+++ b/tests/rustdoc/inline_cross/cross-glob.rs
@@ -0,0 +1,16 @@
+// aux-build:cross-glob.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate inner;
+
+// @has cross_glob/struct.SomeStruct.html
+// @has cross_glob/fn.some_fn.html
+// @!has cross_glob/enum.Shadowed.html
+// @!has cross_glob/index.html '//code' 'pub use inner::*;'
+#[doc(inline)]
+pub use inner::*;
+
+// This type shadows the glob-imported enum `Shadowed`.
+// @has cross_glob/type.Shadowed.html
+pub type Shadowed = u8;
diff --git a/tests/rustdoc/inline_cross/default-trait-method.rs b/tests/rustdoc/inline_cross/default-trait-method.rs
new file mode 100644
index 000000000..a4ec73a12
--- /dev/null
+++ b/tests/rustdoc/inline_cross/default-trait-method.rs
@@ -0,0 +1,20 @@
+// aux-build:default-trait-method.rs
+
+extern crate foo;
+
+// @has default_trait_method/trait.Item.html
+// @has - '//*[@id="tymethod.foo"]' 'fn foo()'
+// @!has - '//*[@id="tymethod.foo"]' 'default fn foo()'
+// @has - '//*[@id="tymethod.bar"]' 'fn bar()'
+// @!has - '//*[@id="tymethod.bar"]' 'default fn bar()'
+// @has - '//*[@id="method.baz"]' 'fn baz()'
+// @!has - '//*[@id="method.baz"]' 'default fn baz()'
+pub use foo::Item;
+
+// @has default_trait_method/struct.Foo.html
+// @has - '//*[@id="method.foo"]' 'default fn foo()'
+// @has - '//*[@id="method.bar"]' 'fn bar()'
+// @!has - '//*[@id="method.bar"]' 'default fn bar()'
+// @has - '//*[@id="method.baz"]' 'fn baz()'
+// @!has - '//*[@id="method.baz"]' 'default fn baz()'
+pub use foo::Foo;
diff --git a/tests/rustdoc/inline_cross/dyn_trait.rs b/tests/rustdoc/inline_cross/dyn_trait.rs
new file mode 100644
index 000000000..0da8bfc3a
--- /dev/null
+++ b/tests/rustdoc/inline_cross/dyn_trait.rs
@@ -0,0 +1,31 @@
+#![crate_name = "user"]
+
+// aux-crate:dyn_trait=dyn_trait.rs
+// edition:2021
+
+// @has user/type.Ty0.html
+// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// FIXME(fmease): Hide default lifetime bound `'static`
+pub use dyn_trait::Ty0;
+
+// @has user/type.Ty1.html
+// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+pub use dyn_trait::Ty1;
+
+// @has user/type.Ty2.html
+// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+pub use dyn_trait::Ty2;
+
+// @has user/type.Ty3.html
+// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
+pub use dyn_trait::Ty3;
+
+// @has user/fn.func0.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
+// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
+pub use dyn_trait::func0;
+
+// @has user/fn.func1.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+pub use dyn_trait::func1;
diff --git a/tests/rustdoc/inline_cross/hidden-use.rs b/tests/rustdoc/inline_cross/hidden-use.rs
new file mode 100644
index 000000000..28a4f4bac
--- /dev/null
+++ b/tests/rustdoc/inline_cross/hidden-use.rs
@@ -0,0 +1,12 @@
+// aux-build:rustdoc-hidden.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_hidden;
+
+// @has hidden_use/index.html
+// @!hasraw - 'rustdoc_hidden'
+// @!hasraw - 'Bar'
+// @!has hidden_use/struct.Bar.html
+#[doc(hidden)]
+pub use rustdoc_hidden::Bar;
diff --git a/tests/rustdoc/inline_cross/impl-inline-without-trait.rs b/tests/rustdoc/inline_cross/impl-inline-without-trait.rs
new file mode 100644
index 000000000..9b67022fd
--- /dev/null
+++ b/tests/rustdoc/inline_cross/impl-inline-without-trait.rs
@@ -0,0 +1,12 @@
+// aux-build:impl-inline-without-trait.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate impl_inline_without_trait;
+
+// @has 'foo/struct.MyStruct.html'
+// @has - '//*[@id="method.my_trait_method"]' 'fn my_trait_method()'
+// @has - '//div[@class="docblock"]' 'docs for my_trait_method'
+pub use impl_inline_without_trait::MyStruct;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
new file mode 100644
index 000000000..e8587209b
--- /dev/null
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -0,0 +1,47 @@
+// aux-build:impl_trait_aux.rs
+// edition:2018
+
+extern crate impl_trait_aux;
+
+// @has impl_trait/fn.func.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+pub use impl_trait_aux::func;
+
+// @has impl_trait/fn.func2.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func2<T>("
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_y: impl Iterator<Item = u8>)"
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+pub use impl_trait_aux::func2;
+
+// @has impl_trait/fn.func3.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func3("
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+pub use impl_trait_aux::func3;
+
+// @has impl_trait/fn.func4.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4<T>("
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator<Item = impl Clone>,"
+pub use impl_trait_aux::func4;
+
+// @has impl_trait/fn.func5.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func5("
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+pub use impl_trait_aux::func5;
+
+// @has impl_trait/fn.async_fn.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
+pub use impl_trait_aux::async_fn;
+
+// @has impl_trait/struct.Foo.html
+// @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
+pub use impl_trait_aux::Foo;
+
+// @has impl_trait/struct.Bar.html
+// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo("
+pub use impl_trait_aux::Bar;
diff --git a/tests/rustdoc/inline_cross/implementors-js.rs b/tests/rustdoc/inline_cross/implementors-js.rs
new file mode 100644
index 000000000..c79f05d8d
--- /dev/null
+++ b/tests/rustdoc/inline_cross/implementors-js.rs
@@ -0,0 +1,25 @@
+// aux-build:implementors_inline.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate implementors_inline;
+
+// @!has implementors/implementors_js/trait.MyTrait.js
+// @has implementors/implementors_inline/my_trait/trait.MyTrait.js
+// @!has implementors/implementors_inline/prelude/trait.MyTrait.js
+// @has implementors_inline/my_trait/trait.MyTrait.html
+// @has - '//script/@src' '../../implementors/implementors_inline/my_trait/trait.MyTrait.js'
+// @has implementors_js/trait.MyTrait.html
+// @has - '//script/@src' '../implementors/implementors_inline/my_trait/trait.MyTrait.js'
+/// When re-exporting this trait, the HTML will be inlined,
+/// but, vitally, the JavaScript will be located only at the
+/// one canonical path.
+pub use implementors_inline::prelude::MyTrait;
+
+pub struct OtherStruct;
+
+impl MyTrait for OtherStruct {
+ fn my_fn(&self) -> OtherStruct {
+ OtherStruct
+ }
+}
diff --git a/tests/rustdoc/inline_cross/inline_hidden.rs b/tests/rustdoc/inline_cross/inline_hidden.rs
new file mode 100644
index 000000000..dcceaadb9
--- /dev/null
+++ b/tests/rustdoc/inline_cross/inline_hidden.rs
@@ -0,0 +1,12 @@
+// aux-build:rustdoc-hidden.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_hidden;
+
+#[doc(no_inline)]
+pub use rustdoc_hidden::Foo;
+
+// @has inline_hidden/fn.foo.html
+// @!has - '//a/@title' 'Foo'
+pub fn foo(_: Foo) {}
diff --git a/tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html b/tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
new file mode 100644
index 000000000..f3c1c0452
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
@@ -0,0 +1 @@
+<h4 class="code-header">fn <a href="#method.touch" class="fn">touch</a>(&amp;self)</h4> \ No newline at end of file
diff --git a/tests/rustdoc/inline_cross/issue-24183.rs b/tests/rustdoc/inline_cross/issue-24183.rs
new file mode 100644
index 000000000..d11b6955f
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-24183.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![crate_name = "usr"]
+
+// aux-crate:issue_24183=issue-24183.rs
+// edition: 2021
+
+// @has usr/trait.U.html
+// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@id="method.modified"]' \
+// "fn modified(self) -> Self\
+// where \
+// Self: Sized"
+// @snapshot method_no_where_self_sized - '//*[@id="method.touch"]/*[@class="code-header"]'
+pub use issue_24183::U;
+
+// @has usr/trait.S.html
+// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+pub use issue_24183::S;
diff --git a/tests/rustdoc/inline_cross/issue-28480.rs b/tests/rustdoc/inline_cross/issue-28480.rs
new file mode 100644
index 000000000..99f5b9007
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-28480.rs
@@ -0,0 +1,13 @@
+// aux-build:rustdoc-hidden-sig.rs
+// build-aux-docs
+// ignore-cross-compile
+
+// @has rustdoc_hidden_sig/struct.Bar.html
+// @!has - '//a/@title' 'Hidden'
+// @has - '//a' 'u8'
+extern crate rustdoc_hidden_sig;
+
+// @has issue_28480/struct.Bar.html
+// @!has - '//a/@title' 'Hidden'
+// @has - '//a' 'u8'
+pub use rustdoc_hidden_sig::Bar;
diff --git a/tests/rustdoc/inline_cross/issue-31948-1.rs b/tests/rustdoc/inline_cross/issue-31948-1.rs
new file mode 100644
index 000000000..6e89167b3
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-31948-1.rs
@@ -0,0 +1,27 @@
+// aux-build:rustdoc-nonreachable-impls.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_nonreachable_impls;
+
+// @has issue_31948_1/struct.Wobble.html
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
+pub use rustdoc_nonreachable_impls::hidden::Wobble;
+
+// @has issue_31948_1/trait.Bark.html
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+pub use rustdoc_nonreachable_impls::Bark;
+
+// @has issue_31948_1/trait.Woof.html
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+pub use rustdoc_nonreachable_impls::Woof;
+
+// @!has issue_31948_1/trait.Bar.html
+// @!has issue_31948_1/trait.Qux.html
diff --git a/tests/rustdoc/inline_cross/issue-31948-2.rs b/tests/rustdoc/inline_cross/issue-31948-2.rs
new file mode 100644
index 000000000..141e07656
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-31948-2.rs
@@ -0,0 +1,21 @@
+// aux-build:rustdoc-nonreachable-impls.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_nonreachable_impls;
+
+// @has issue_31948_2/struct.Wobble.html
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Qux for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
+pub use rustdoc_nonreachable_impls::hidden::Wobble;
+
+// @has issue_31948_2/trait.Qux.html
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
+pub use rustdoc_nonreachable_impls::hidden::Qux;
+
+// @!has issue_31948_2/trait.Bar.html
+// @!has issue_31948_2/trait.Woof.html
+// @!has issue_31948_2/trait.Bark.html
diff --git a/tests/rustdoc/inline_cross/issue-31948.rs b/tests/rustdoc/inline_cross/issue-31948.rs
new file mode 100644
index 000000000..96fc6ca47
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-31948.rs
@@ -0,0 +1,29 @@
+// aux-build:rustdoc-nonreachable-impls.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_nonreachable_impls;
+
+// @has issue_31948/struct.Foo.html
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
+// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
+pub use rustdoc_nonreachable_impls::Foo;
+
+// @has issue_31948/trait.Bark.html
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+// @!has - '//h3[@class="code-header"]' 'for Wobble'
+pub use rustdoc_nonreachable_impls::Bark;
+
+// @has issue_31948/trait.Woof.html
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+// @!has - '//h3[@class="code-header"]' 'for Wobble'
+pub use rustdoc_nonreachable_impls::Woof;
+
+// @!has issue_31948/trait.Bar.html
+// @!has issue_31948/trait.Qux.html
+// @!has issue_31948/struct.Wibble.html
+// @!has issue_31948/struct.Wobble.html
diff --git a/tests/rustdoc/inline_cross/issue-32881.rs b/tests/rustdoc/inline_cross/issue-32881.rs
new file mode 100644
index 000000000..183fd15ab
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-32881.rs
@@ -0,0 +1,11 @@
+// aux-build:rustdoc-trait-object-impl.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate rustdoc_trait_object_impl;
+
+// @has issue_32881/trait.Bar.html
+// @has - '//h3[@class="code-header"]' "impl<'a> dyn Bar"
+// @has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar"
+
+pub use rustdoc_trait_object_impl::Bar;
diff --git a/tests/rustdoc/inline_cross/issue-33113.rs b/tests/rustdoc/inline_cross/issue-33113.rs
new file mode 100644
index 000000000..d954707fa
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-33113.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-33113.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate bar;
+
+// @has issue_33113/trait.Bar.html
+// @has - '//h3[@class="code-header"]' "for &'a char"
+// @has - '//h3[@class="code-header"]' "for Foo"
+pub use bar::Bar;
diff --git a/tests/rustdoc/inline_cross/macro-vis.rs b/tests/rustdoc/inline_cross/macro-vis.rs
new file mode 100644
index 000000000..9fefd38ad
--- /dev/null
+++ b/tests/rustdoc/inline_cross/macro-vis.rs
@@ -0,0 +1,36 @@
+// aux-build:macro-vis.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#[macro_use] extern crate qwop;
+
+// @has macro_vis/macro.some_macro.html
+// @has macro_vis/index.html '//a/@href' 'macro.some_macro.html'
+pub use qwop::some_macro;
+
+// @has macro_vis/macro.renamed_macro.html
+// @!has - '//pre' 'some_macro'
+// @has macro_vis/index.html '//a/@href' 'macro.renamed_macro.html'
+#[doc(inline)]
+pub use qwop::some_macro as renamed_macro;
+
+// @!has macro_vis/macro.other_macro.html
+// @!has macro_vis/index.html '//a/@href' 'macro.other_macro.html'
+// @!has - '//code' 'pub use qwop::other_macro;'
+#[doc(hidden)]
+pub use qwop::other_macro;
+
+// @has macro_vis/index.html '//code' 'pub use qwop::super_macro;'
+// @!has macro_vis/macro.super_macro.html
+#[doc(no_inline)]
+pub use qwop::super_macro;
+
+// @has macro_vis/macro.this_is_dope.html
+// @has macro_vis/index.html '//a/@href' 'macro.this_is_dope.html'
+/// What it says on the tin.
+#[macro_export]
+macro_rules! this_is_dope {
+ () => {
+ println!("yo check this out");
+ };
+}
diff --git a/tests/rustdoc/inline_cross/macros.rs b/tests/rustdoc/inline_cross/macros.rs
new file mode 100644
index 000000000..5daa0d4ba
--- /dev/null
+++ b/tests/rustdoc/inline_cross/macros.rs
@@ -0,0 +1,19 @@
+// aux-build:macros.rs
+// build-aux-docs
+
+#![feature(macro_test)]
+#![crate_name = "foo"]
+
+extern crate macros;
+
+// @has foo/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
+// Deprecated
+// @has - '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
+// Experimental
+
+// @has foo/macro.my_macro.html
+// @has - '//*[@class="docblock"]' 'docs for my_macro'
+// @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.2.3: text'
+// @has - '//*[@class="stab unstable"]' 'macro_test'
+// @has - '//a/@href' '../src/macros/macros.rs.html#8'
+pub use macros::my_macro;
diff --git a/tests/rustdoc/inline_cross/proc_macro.rs b/tests/rustdoc/inline_cross/proc_macro.rs
new file mode 100644
index 000000000..a46550865
--- /dev/null
+++ b/tests/rustdoc/inline_cross/proc_macro.rs
@@ -0,0 +1,36 @@
+// aux-build:proc_macro.rs
+// build-aux-docs
+
+extern crate some_macros;
+
+// @has proc_macro/index.html
+// @has - '//a/@href' 'macro.some_proc_macro.html'
+// @has - '//a/@href' 'attr.some_proc_attr.html'
+// @has - '//a/@href' 'derive.SomeDerive.html'
+// @has proc_macro/macro.some_proc_macro.html
+// @has proc_macro/attr.some_proc_attr.html
+// @has proc_macro/derive.SomeDerive.html
+
+// @has proc_macro/macro.some_proc_macro.html
+// @hasraw - 'a proc-macro that swallows its input and does nothing.'
+pub use some_macros::some_proc_macro;
+
+// @has proc_macro/macro.reexported_macro.html
+// @hasraw - 'Doc comment from the original crate'
+pub use some_macros::reexported_macro;
+
+// @has proc_macro/attr.some_proc_attr.html
+// @hasraw - 'a proc-macro attribute that passes its item through verbatim.'
+pub use some_macros::some_proc_attr;
+
+// @has proc_macro/derive.SomeDerive.html
+// @hasraw - 'a derive attribute that adds nothing to its input.'
+pub use some_macros::SomeDerive;
+
+// @has proc_macro/attr.first_attr.html
+// @hasraw - 'Generated doc comment'
+pub use some_macros::first_attr;
+
+// @has proc_macro/attr.second_attr.html
+// @hasraw - 'Generated doc comment'
+pub use some_macros::second_attr;
diff --git a/tests/rustdoc/inline_cross/renamed-via-module.rs b/tests/rustdoc/inline_cross/renamed-via-module.rs
new file mode 100644
index 000000000..cdedbf070
--- /dev/null
+++ b/tests/rustdoc/inline_cross/renamed-via-module.rs
@@ -0,0 +1,24 @@
+// aux-build:renamed-via-module.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "bar"]
+
+extern crate foo;
+
+// @has foo/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has foo/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct foo::iter::DeprecatedStepBy"
+// @has foo/iter/struct.StepBy.html
+// @has - '//h1' "Struct foo::iter::StepBy"
+
+// @has bar/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has bar/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct bar::iter::DeprecatedStepBy"
+// @has bar/iter/struct.StepBy.html
+// @has - '//h1' "Struct bar::iter::StepBy"
+pub use foo::iter;
diff --git a/tests/rustdoc/inline_cross/trait-vis.rs b/tests/rustdoc/inline_cross/trait-vis.rs
new file mode 100644
index 000000000..b646babac
--- /dev/null
+++ b/tests/rustdoc/inline_cross/trait-vis.rs
@@ -0,0 +1,7 @@
+// aux-build:trait-vis.rs
+
+extern crate inner;
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct'
+pub use inner::SomeStruct;
diff --git a/tests/rustdoc/inline_cross/use_crate.rs b/tests/rustdoc/inline_cross/use_crate.rs
new file mode 100644
index 000000000..00e0f041c
--- /dev/null
+++ b/tests/rustdoc/inline_cross/use_crate.rs
@@ -0,0 +1,27 @@
+// aux-build:use_crate.rs
+// aux-build:use_crate_2.rs
+// build-aux-docs
+// edition:2018
+// compile-flags:--extern use_crate --extern use_crate_2
+
+// During the buildup to Rust 2018, rustdoc would eagerly inline `pub use some_crate;` as if it
+// were a module, so we changed it to make `pub use`ing crate roots remain as a `pub use` statement
+// in docs... unless you added `#[doc(inline)]`.
+
+#![crate_name = "local"]
+
+// @!has-dir local/use_crate
+// @has local/index.html
+// @has - '//code' 'pub use use_crate'
+pub use use_crate;
+
+// @has-dir local/asdf
+// @has local/asdf/index.html
+// @has local/index.html '//a/@href' 'asdf/index.html'
+pub use use_crate::asdf;
+
+// @has-dir local/use_crate_2
+// @has local/use_crate_2/index.html
+// @has local/index.html '//a/@href' 'use_crate_2/index.html'
+#[doc(inline)]
+pub use use_crate_2;
diff --git a/tests/rustdoc/inline_local/glob-extern-document-private-items.rs b/tests/rustdoc/inline_local/glob-extern-document-private-items.rs
new file mode 100644
index 000000000..8e1089d60
--- /dev/null
+++ b/tests/rustdoc/inline_local/glob-extern-document-private-items.rs
@@ -0,0 +1,25 @@
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+mod mod1 {
+ extern "C" {
+ pub fn public_fn();
+ fn private_fn();
+ }
+}
+
+pub use mod1::*;
+
+// @has foo/index.html
+// @hasraw - "mod1"
+// @hasraw - "public_fn"
+// @!hasraw - "private_fn"
+// @has foo/fn.public_fn.html
+// @!has foo/fn.private_fn.html
+
+// @has foo/mod1/index.html
+// @hasraw - "public_fn"
+// @hasraw - "private_fn"
+// @has foo/mod1/fn.public_fn.html
+// @has foo/mod1/fn.private_fn.html
diff --git a/tests/rustdoc/inline_local/glob-extern.rs b/tests/rustdoc/inline_local/glob-extern.rs
new file mode 100644
index 000000000..c592a4db1
--- /dev/null
+++ b/tests/rustdoc/inline_local/glob-extern.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+mod mod1 {
+ extern "C" {
+ pub fn public_fn();
+ fn private_fn();
+ }
+}
+
+pub use mod1::*;
+
+// @has foo/index.html
+// @!hasraw - "mod1"
+// @hasraw - "public_fn"
+// @!hasraw - "private_fn"
+// @has foo/fn.public_fn.html
+// @!has foo/fn.private_fn.html
+
+// @!has foo/mod1/index.html
+// @has foo/mod1/fn.public_fn.html
+// @!has foo/mod1/fn.private_fn.html
diff --git a/tests/rustdoc/inline_local/glob-private-document-private-items.rs b/tests/rustdoc/inline_local/glob-private-document-private-items.rs
new file mode 100644
index 000000000..d8cbd4234
--- /dev/null
+++ b/tests/rustdoc/inline_local/glob-private-document-private-items.rs
@@ -0,0 +1,48 @@
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+mod mod1 {
+ mod mod2 {
+ pub struct Mod2Public;
+ struct Mod2Private;
+ }
+ pub use self::mod2::*;
+
+ pub struct Mod1Public;
+ struct Mod1Private;
+}
+pub use mod1::*;
+
+// @has foo/index.html
+// @hasraw - "mod1"
+// @hasraw - "Mod1Public"
+// @!hasraw - "Mod1Private"
+// @!hasraw - "mod2"
+// @hasraw - "Mod2Public"
+// @!hasraw - "Mod2Private"
+// @has foo/struct.Mod1Public.html
+// @!has foo/struct.Mod1Private.html
+// @has foo/struct.Mod2Public.html
+// @!has foo/struct.Mod2Private.html
+
+// @has foo/mod1/index.html
+// @hasraw - "mod2"
+// @hasraw - "Mod1Public"
+// @hasraw - "Mod1Private"
+// @!hasraw - "Mod2Public"
+// @!hasraw - "Mod2Private"
+// @has foo/mod1/struct.Mod1Public.html
+// @has foo/mod1/struct.Mod1Private.html
+// @!has foo/mod1/struct.Mod2Public.html
+// @!has foo/mod1/struct.Mod2Private.html
+
+// @has foo/mod1/mod2/index.html
+// @hasraw - "Mod2Public"
+// @hasraw - "Mod2Private"
+// @has foo/mod1/mod2/struct.Mod2Public.html
+// @has foo/mod1/mod2/struct.Mod2Private.html
+
+// @!has foo/mod2/index.html
+// @!has foo/mod2/struct.Mod2Public.html
+// @!has foo/mod2/struct.Mod2Private.html
diff --git a/tests/rustdoc/inline_local/glob-private.rs b/tests/rustdoc/inline_local/glob-private.rs
new file mode 100644
index 000000000..303f1d610
--- /dev/null
+++ b/tests/rustdoc/inline_local/glob-private.rs
@@ -0,0 +1,42 @@
+#![crate_name = "foo"]
+
+mod mod1 {
+ mod mod2 {
+ pub struct Mod2Public;
+ struct Mod2Private;
+ }
+ pub use self::mod2::*;
+
+ pub struct Mod1Public;
+ struct Mod1Private;
+}
+pub use mod1::*;
+
+// @has foo/index.html
+// @!hasraw - "mod1"
+// @hasraw - "Mod1Public"
+// @!hasraw - "Mod1Private"
+// @!hasraw - "mod2"
+// @hasraw - "Mod2Public"
+// @!hasraw - "Mod2Private"
+// @has foo/struct.Mod1Public.html
+// @!has foo/struct.Mod1Private.html
+// @has foo/struct.Mod2Public.html
+// @!has foo/struct.Mod2Private.html
+
+// @has-dir foo/mod1
+// @!has foo/mod1/index.html
+// @has foo/mod1/struct.Mod1Public.html
+// @!has foo/mod1/struct.Mod1Private.html
+// @!has foo/mod1/struct.Mod2Public.html
+// @!has foo/mod1/struct.Mod2Private.html
+
+// @has-dir foo/mod1/mod2
+// @!has foo/mod1/mod2/index.html
+// @has foo/mod1/mod2/struct.Mod2Public.html
+// @!has foo/mod1/mod2/struct.Mod2Private.html
+
+// @!has-dir foo/mod2
+// @!has foo/mod2/index.html
+// @!has foo/mod2/struct.Mod2Public.html
+// @!has foo/mod2/struct.Mod2Private.html
diff --git a/tests/rustdoc/inline_local/hidden-use.rs b/tests/rustdoc/inline_local/hidden-use.rs
new file mode 100644
index 000000000..de512fb26
--- /dev/null
+++ b/tests/rustdoc/inline_local/hidden-use.rs
@@ -0,0 +1,10 @@
+mod private {
+ pub struct Foo {}
+}
+
+// @has hidden_use/index.html
+// @!hasraw - 'private'
+// @!hasraw - 'Foo'
+// @!has hidden_use/struct.Foo.html
+#[doc(hidden)]
+pub use private::Foo;
diff --git a/tests/rustdoc/inline_local/issue-28537.rs b/tests/rustdoc/inline_local/issue-28537.rs
new file mode 100644
index 000000000..da9cc4c94
--- /dev/null
+++ b/tests/rustdoc/inline_local/issue-28537.rs
@@ -0,0 +1,17 @@
+#[doc(hidden)]
+pub mod foo {
+ pub struct Foo;
+}
+
+mod bar {
+ pub use self::bar::Bar;
+ mod bar {
+ pub struct Bar;
+ }
+}
+
+// @has issue_28537/struct.Foo.html
+pub use foo::Foo;
+
+// @has issue_28537/struct.Bar.html
+pub use self::bar::Bar;
diff --git a/tests/rustdoc/inline_local/issue-32343.rs b/tests/rustdoc/inline_local/issue-32343.rs
new file mode 100644
index 000000000..5620ae0dc
--- /dev/null
+++ b/tests/rustdoc/inline_local/issue-32343.rs
@@ -0,0 +1,23 @@
+// @!has issue_32343/struct.Foo.html
+// @has issue_32343/index.html
+// @has - '//code' 'pub use foo::Foo'
+// @!has - '//code/a' 'Foo'
+#[doc(no_inline)]
+pub use foo::Foo;
+
+// @!has issue_32343/struct.Bar.html
+// @has issue_32343/index.html
+// @has - '//code' 'pub use foo::Bar'
+// @has - '//code/a' 'Bar'
+#[doc(no_inline)]
+pub use foo::Bar;
+
+mod foo {
+ pub struct Foo;
+ pub struct Bar;
+}
+
+pub mod bar {
+ // @has issue_32343/bar/struct.Bar.html
+ pub use ::foo::Bar;
+}
diff --git a/tests/rustdoc/inline_local/macro_by_example.rs b/tests/rustdoc/inline_local/macro_by_example.rs
new file mode 100644
index 000000000..5c33c0037
--- /dev/null
+++ b/tests/rustdoc/inline_local/macro_by_example.rs
@@ -0,0 +1,17 @@
+/// docs for foo
+#[deprecated(since = "1.2.3", note = "text")]
+#[macro_export]
+macro_rules! foo {
+ ($($tt:tt)*) => {}
+}
+
+// @has macro_by_example/macros/index.html
+pub mod macros {
+ // @!hasraw - 'pub use foo as bar;'
+ // @has macro_by_example/macros/macro.bar.html
+ // @has - '//*[@class="docblock"]' 'docs for foo'
+ // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.2.3: text'
+ // @has - '//a/@href' 'macro_by_example.rs.html#4-6'
+ #[doc(inline)]
+ pub use foo as bar;
+}
diff --git a/tests/rustdoc/inline_local/please_inline.rs b/tests/rustdoc/inline_local/please_inline.rs
new file mode 100644
index 000000000..e4429ef33
--- /dev/null
+++ b/tests/rustdoc/inline_local/please_inline.rs
@@ -0,0 +1,19 @@
+pub mod foo {
+ pub struct Foo;
+}
+
+// @has please_inline/a/index.html
+pub mod a {
+ // @!hasraw - 'pub use foo::'
+ // @has please_inline/a/struct.Foo.html
+ #[doc(inline)]
+ pub use foo::Foo;
+}
+
+// @has please_inline/b/index.html
+pub mod b {
+ // @hasraw - 'pub use foo::'
+ // @!has please_inline/b/struct.Foo.html
+ #[feature(inline)]
+ pub use foo::Foo;
+}
diff --git a/tests/rustdoc/inline_local/trait-vis.rs b/tests/rustdoc/inline_local/trait-vis.rs
new file mode 100644
index 000000000..19b69da15
--- /dev/null
+++ b/tests/rustdoc/inline_local/trait-vis.rs
@@ -0,0 +1,18 @@
+pub trait ThisTrait {}
+
+mod asdf {
+ use ThisTrait;
+
+ pub struct SomeStruct;
+
+ impl ThisTrait for SomeStruct {}
+
+ trait PrivateTrait {}
+
+ impl PrivateTrait for SomeStruct {}
+}
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//h3[@class="code-header"]' 'impl ThisTrait for SomeStruct'
+// @!has - '//h3[@class="code-header"]' 'impl PrivateTrait for SomeStruct'
+pub use asdf::SomeStruct;
diff --git a/tests/rustdoc/internal.rs b/tests/rustdoc/internal.rs
new file mode 100644
index 000000000..caad43a08
--- /dev/null
+++ b/tests/rustdoc/internal.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z force-unstable-if-unmarked
+
+// Check that the unstable marker is not added for "rustc_private".
+
+// @!matches internal/index.html \
+// '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]' \
+// ''
+// @!matches internal/index.html \
+// '//*[@class="item-right docblock-short"]/span[@class="stab internal"]' \
+// ''
+// @matches - '//*[@class="item-right docblock-short"]' 'Docs'
+
+// @!has internal/struct.S.html '//*[@class="stab unstable"]' ''
+// @!has internal/struct.S.html '//*[@class="stab internal"]' ''
+/// Docs
+pub struct S;
+
+fn main() {}
diff --git a/tests/rustdoc/intra-doc-crate/auxiliary/self.rs b/tests/rustdoc/intra-doc-crate/auxiliary/self.rs
new file mode 100644
index 000000000..54902f12e
--- /dev/null
+++ b/tests/rustdoc/intra-doc-crate/auxiliary/self.rs
@@ -0,0 +1,10 @@
+#![crate_name = "cross_crate_self"]
+
+/// Link to [Self]
+/// Link to [crate]
+pub struct S;
+
+impl S {
+ /// Link to [Self::f]
+ pub fn f() {}
+}
diff --git a/tests/rustdoc/intra-doc-crate/self.rs b/tests/rustdoc/intra-doc-crate/self.rs
new file mode 100644
index 000000000..8c36a7fa0
--- /dev/null
+++ b/tests/rustdoc/intra-doc-crate/self.rs
@@ -0,0 +1,9 @@
+// aux-build:self.rs
+// build-aux-docs
+
+extern crate cross_crate_self;
+
+// @has self/struct.S.html '//a[@href="struct.S.html#method.f"]' "Self::f"
+// @has self/struct.S.html '//a[@href="struct.S.html"]' "Self"
+// @has self/struct.S.html '//a[@href="../cross_crate_self/index.html"]' "crate"
+pub use cross_crate_self::S;
diff --git a/tests/rustdoc/intra-doc/anchors.rs b/tests/rustdoc/intra-doc/anchors.rs
new file mode 100644
index 000000000..3d4c46496
--- /dev/null
+++ b/tests/rustdoc/intra-doc/anchors.rs
@@ -0,0 +1,24 @@
+/// I want...
+///
+/// # Anchor!
+pub struct Something;
+
+// @has anchors/struct.SomeOtherType.html
+// @has - '//a/@href' 'struct.Something.html#Anchor!'
+
+/// I want...
+///
+/// To link to [Something#Anchor!]
+pub struct SomeOtherType;
+
+/// Primitives?
+///
+/// [u32#hello]
+// @has anchors/fn.x.html
+// @has - '//a/@href' '{{channel}}/std/primitive.u32.html#hello'
+pub fn x() {}
+
+/// [prim@usize#x]
+// @has anchors/usize/index.html
+// @has - '//a/@href' '{{channel}}/std/primitive.usize.html#x'
+pub mod usize {}
diff --git a/tests/rustdoc/intra-doc/assoc-reexport-super.rs b/tests/rustdoc/intra-doc/assoc-reexport-super.rs
new file mode 100644
index 000000000..a7bc1c6a2
--- /dev/null
+++ b/tests/rustdoc/intra-doc/assoc-reexport-super.rs
@@ -0,0 +1,20 @@
+// Regression test for #93205
+
+#![crate_name = "foo"]
+
+mod generated {
+ pub struct MyNewType;
+ impl MyNewType {
+ pub const FOO: Self = Self;
+ }
+}
+
+pub use generated::MyNewType;
+
+mod prelude {
+ impl super::MyNewType {
+ /// An alias for [`Self::FOO`].
+ // @has 'foo/struct.MyNewType.html' '//a[@href="struct.MyNewType.html#associatedconstant.FOO"]' 'Self::FOO'
+ pub const FOO2: Self = Self::FOO;
+ }
+}
diff --git a/tests/rustdoc/intra-doc/associated-defaults.rs b/tests/rustdoc/intra-doc/associated-defaults.rs
new file mode 100644
index 000000000..c7e66c826
--- /dev/null
+++ b/tests/rustdoc/intra-doc/associated-defaults.rs
@@ -0,0 +1,26 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(associated_type_defaults)]
+
+pub trait TraitWithDefault {
+ type T = usize;
+ fn f() -> Self::T {
+ 0
+ }
+}
+
+/// Link to [UsesDefaults::T] and [UsesDefaults::f]
+// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T'
+// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f'
+pub struct UsesDefaults;
+impl TraitWithDefault for UsesDefaults {}
+
+/// Link to [OverridesDefaults::T] and [OverridesDefaults::f]
+// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T'
+// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f'
+pub struct OverridesDefaults;
+impl TraitWithDefault for OverridesDefaults {
+ type T = bool;
+ fn f() -> bool {
+ true
+ }
+}
diff --git a/tests/rustdoc/intra-doc/associated-items.rs b/tests/rustdoc/intra-doc/associated-items.rs
new file mode 100644
index 000000000..0b958eb8e
--- /dev/null
+++ b/tests/rustdoc/intra-doc/associated-items.rs
@@ -0,0 +1,68 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// [`std::collections::BTreeMap::into_iter`]
+/// [`String::from`] is ambiguous as to which `From` impl
+/// [Vec::into_iter()] uses a disambiguator
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/struct.String.html#method.from"]' 'String::from'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
+pub fn foo() {}
+
+/// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
+// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html"]' 'MyStruct'
+// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.method"]' 'link from struct'
+// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.clone"]' 'MyStruct::clone'
+// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input'
+pub struct MyStruct { foo: () }
+
+impl Clone for MyStruct {
+ fn clone(&self) -> Self {
+ MyStruct
+ }
+}
+
+pub trait T {
+ type Input;
+ fn method(i: Self::Input);
+}
+
+impl T for MyStruct {
+ type Input = usize;
+
+ /// [link from method][MyStruct::method] on method
+ // @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.method"]' 'link from method'
+ fn method(i: usize) {
+ }
+}
+
+/// Ambiguity between which trait to use
+pub trait T1 {
+ fn ambiguous_method();
+}
+
+pub trait T2 {
+ fn ambiguous_method();
+}
+
+/// Link to [S::ambiguous_method]
+// FIXME: there is no way to disambiguate these.
+// Since we have `#[deny(intra_doc_failure)]`, we still know it was one or the other.
+pub struct S;
+
+impl T1 for S {
+ fn ambiguous_method() {}
+}
+
+impl T2 for S {
+ fn ambiguous_method() {}
+}
+
+// @has associated_items/enum.MyEnum.html '//a/@href' 'enum.MyEnum.html#variant.MyVariant'
+/// Link to [MyEnumAlias::MyVariant]
+pub enum MyEnum {
+ MyVariant,
+}
+
+pub type MyEnumAlias = MyEnum;
+
+fn main() {}
diff --git a/tests/rustdoc/intra-doc/auxiliary/empty.rs b/tests/rustdoc/intra-doc/auxiliary/empty.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/empty.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/rustdoc/intra-doc/auxiliary/empty2.rs b/tests/rustdoc/intra-doc/auxiliary/empty2.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/empty2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs b/tests/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs
new file mode 100644
index 000000000..d9a08cb41
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs
@@ -0,0 +1,28 @@
+// no-prefer-dynamic
+
+#![feature(lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_std]
+
+pub struct DerefsToF64(f64);
+
+impl core::ops::Deref for DerefsToF64 {
+ type Target = f64;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+mod inner {
+ impl f64 {
+ /// [f64::clone]
+ #[rustc_allow_incoherent_impl]
+ pub fn method() {}
+ }
+}
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/tests/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs b/tests/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs
new file mode 100644
index 000000000..ee4138b68
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs
@@ -0,0 +1,11 @@
+#[derive(Clone)]
+pub struct PublicStruct;
+
+mod inner {
+ use super::PublicStruct;
+
+ impl PublicStruct {
+ /// [PublicStruct::clone]
+ pub fn method() {}
+ }
+}
diff --git a/tests/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs b/tests/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs
new file mode 100644
index 000000000..db3bb38ad
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs
@@ -0,0 +1,3 @@
+#![crate_name="inner"]
+
+//! ooh, i'm a rebel just for [kicks]
diff --git a/tests/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs b/tests/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs
new file mode 100644
index 000000000..a4db2ffc4
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs
@@ -0,0 +1,4 @@
+#![crate_name = "inner"]
+
+/// Documentation, including a link to [std::ptr]
+pub fn f() {}
diff --git a/tests/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs b/tests/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs
new file mode 100644
index 000000000..fc51995a9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs
@@ -0,0 +1,6 @@
+#![crate_name = "inner"]
+
+/// Links to [f()]
+pub struct Inner;
+
+pub fn f() {}
diff --git a/tests/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs b/tests/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs
new file mode 100644
index 000000000..6142dcda9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs
@@ -0,0 +1,6 @@
+pub trait ThisTrait {
+ fn asdf(&self);
+
+ /// let's link to [`asdf`](ThisTrait::asdf)
+ fn qwop(&self);
+}
diff --git a/tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs b/tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs
new file mode 100644
index 000000000..2b8fdec1f
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs
@@ -0,0 +1,4 @@
+pub trait Trait {
+ /// [`u8::clone`]
+ fn method();
+}
diff --git a/tests/rustdoc/intra-doc/auxiliary/issue-66159-1.rs b/tests/rustdoc/intra-doc/auxiliary/issue-66159-1.rs
new file mode 100644
index 000000000..2f3d069bd
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/issue-66159-1.rs
@@ -0,0 +1,2 @@
+/// This will be referred to by the test docstring
+pub struct Something;
diff --git a/tests/rustdoc/intra-doc/auxiliary/my-core.rs b/tests/rustdoc/intra-doc/auxiliary/my-core.rs
new file mode 100644
index 000000000..e22feb03a
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/my-core.rs
@@ -0,0 +1,23 @@
+#![feature(no_core, lang_items, rustdoc_internals, rustc_attrs)]
+#![no_core]
+#![rustc_coherence_is_core]
+#![crate_type="rlib"]
+
+#[doc(primitive = "char")]
+/// Some char docs
+mod char {}
+
+impl char {
+ pub fn len_utf8(self) -> usize {
+ 42
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {}
+
+#[lang = "copy"]
+pub trait Copy: Clone {}
diff --git a/tests/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs b/tests/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs
new file mode 100644
index 000000000..5ba132f25
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs
@@ -0,0 +1,34 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+
+#![crate_type="proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(DeriveA)]
+pub fn a_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(DeriveB)]
+pub fn b_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(DeriveTrait)]
+pub fn trait_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_attribute]
+pub fn attr_a(input: TokenStream, _args: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_attribute]
+pub fn attr_b(input: TokenStream, _args: TokenStream) -> TokenStream {
+ input
+}
diff --git a/tests/rustdoc/intra-doc/auxiliary/pub-struct.rs b/tests/rustdoc/intra-doc/auxiliary/pub-struct.rs
new file mode 100644
index 000000000..75d428932
--- /dev/null
+++ b/tests/rustdoc/intra-doc/auxiliary/pub-struct.rs
@@ -0,0 +1 @@
+pub struct SomeStruct;
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
new file mode 100644
index 000000000..39f5c298b
--- /dev/null
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -0,0 +1,84 @@
+// @has basic/index.html
+// @has - '//a/@href' 'struct.ThisType.html'
+// @has - '//a/@href' 'struct.ThisType.html#method.this_method'
+// @has - '//a/@href' 'enum.ThisEnum.html'
+// @has - '//a/@href' 'enum.ThisEnum.html#variant.ThisVariant'
+// @has - '//a/@href' 'trait.ThisTrait.html'
+// @has - '//a/@href' 'trait.ThisTrait.html#tymethod.this_associated_method'
+// @has - '//a/@href' 'trait.ThisTrait.html#associatedtype.ThisAssociatedType'
+// @has - '//a/@href' 'trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST'
+// @has - '//a/@href' 'trait.ThisTrait.html'
+// @has - '//a/@href' 'type.ThisAlias.html'
+// @has - '//a/@href' 'union.ThisUnion.html'
+// @has - '//a/@href' 'fn.this_function.html'
+// @has - '//a/@href' 'constant.THIS_CONST.html'
+// @has - '//a/@href' 'static.THIS_STATIC.html'
+// @has - '//a/@href' 'macro.this_macro.html'
+// @has - '//a/@href' 'trait.SoAmbiguous.html'
+// @has - '//a/@href' 'fn.SoAmbiguous.html'
+//! In this crate we would like to link to:
+//!
+//! * [`ThisType`](ThisType)
+//! * [`ThisType::this_method`](ThisType::this_method)
+//! * [`ThisEnum`](ThisEnum)
+//! * [`ThisEnum::ThisVariant`](ThisEnum::ThisVariant)
+//! * [`ThisEnum::ThisVariantCtor`](ThisEnum::ThisVariantCtor)
+//! * [`ThisTrait`](ThisTrait)
+//! * [`ThisTrait::this_associated_method`](ThisTrait::this_associated_method)
+//! * [`ThisTrait::ThisAssociatedType`](ThisTrait::ThisAssociatedType)
+//! * [`ThisTrait::THIS_ASSOCIATED_CONST`](ThisTrait::THIS_ASSOCIATED_CONST)
+//! * [`ThisAlias`](ThisAlias)
+//! * [`ThisUnion`](ThisUnion)
+//! * [`this_function`](this_function())
+//! * [`THIS_CONST`](const@THIS_CONST)
+//! * [`THIS_STATIC`](static@THIS_STATIC)
+//! * [`this_macro`](this_macro!)
+//!
+//! In addition, there's some specifics we want to look at. There's [a trait called
+//! SoAmbiguous][ambig-trait], but there's also [a function called SoAmbiguous][ambig-fn] too!
+//! Whatever shall we do?
+//!
+//! [ambig-trait]: trait@SoAmbiguous
+//! [ambig-fn]: SoAmbiguous()
+
+#[macro_export]
+macro_rules! this_macro {
+ () => {};
+}
+
+// @has basic/struct.ThisType.html '//a/@href' 'macro.this_macro.html'
+/// another link to [`this_macro!()`]
+pub struct ThisType;
+
+impl ThisType {
+ pub fn this_method() {}
+}
+pub enum ThisEnum { ThisVariant, ThisVariantCtor(u32), }
+pub trait ThisTrait {
+ type ThisAssociatedType;
+ const THIS_ASSOCIATED_CONST: u8;
+ fn this_associated_method();
+}
+pub type ThisAlias = Result<(), ()>;
+pub union ThisUnion { this_field: usize, }
+
+pub fn this_function() {}
+pub const THIS_CONST: usize = 5usize;
+pub static THIS_STATIC: usize = 5usize;
+
+pub trait SoAmbiguous {}
+
+#[allow(nonstandard_style)]
+pub fn SoAmbiguous() {}
+
+
+// @has basic/struct.SomeOtherType.html '//a/@href' 'struct.ThisType.html'
+// @has - '//a/@href' 'struct.ThisType.html#method.this_method'
+// @has - '//a/@href' 'enum.ThisEnum.html'
+// @has - '//a/@href' 'enum.ThisEnum.html#variant.ThisVariant'
+/// Shortcut links for:
+/// * [`ThisType`]
+/// * [`ThisType::this_method`]
+/// * [ThisEnum]
+/// * [ThisEnum::ThisVariant]
+pub struct SomeOtherType;
diff --git a/tests/rustdoc/intra-doc/builtin-macros.rs b/tests/rustdoc/intra-doc/builtin-macros.rs
new file mode 100644
index 000000000..bbdbe246b
--- /dev/null
+++ b/tests/rustdoc/intra-doc/builtin-macros.rs
@@ -0,0 +1,3 @@
+// @has builtin_macros/index.html
+// @has - '//a/@href' '{{channel}}/core/macro.cfg.html'
+//! [cfg]
diff --git a/tests/rustdoc/intra-doc/crate-relative-assoc.rs b/tests/rustdoc/intra-doc/crate-relative-assoc.rs
new file mode 100644
index 000000000..d4a0ecc35
--- /dev/null
+++ b/tests/rustdoc/intra-doc/crate-relative-assoc.rs
@@ -0,0 +1,17 @@
+pub mod io {
+ pub trait Read {
+ fn read(&mut self);
+ }
+}
+
+pub mod bufreader {
+ // @has crate_relative_assoc/bufreader/index.html '//a/@href' 'struct.TcpStream.html#method.read'
+ //! [`crate::TcpStream::read`]
+ use crate::io::Read;
+}
+
+pub struct TcpStream;
+
+impl crate::io::Read for TcpStream {
+ fn read(&mut self) {}
+}
diff --git a/tests/rustdoc/intra-doc/crate-relative.rs b/tests/rustdoc/intra-doc/crate-relative.rs
new file mode 100644
index 000000000..bacbcabfc
--- /dev/null
+++ b/tests/rustdoc/intra-doc/crate-relative.rs
@@ -0,0 +1,13 @@
+pub struct Test<'a> {
+ data: &'a (),
+}
+
+impl<'a> Test<'a> {
+ pub fn do_test(&self) {}
+}
+
+// @has crate_relative/demo/index.html
+// @has - '//a/@href' '../struct.Test.html#method.do_test'
+pub mod demo {
+ //! [`crate::Test::do_test`]
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/additional_doc.rs b/tests/rustdoc/intra-doc/cross-crate/additional_doc.rs
new file mode 100644
index 000000000..e52fb9b1c
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/additional_doc.rs
@@ -0,0 +1,10 @@
+// aux-build:additional_doc.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate my_rand;
+
+// @has 'additional_doc/trait.Rng.html' '//a[@href="trait.Rng.html"]' 'Rng'
+// @has 'additional_doc/trait.Rng.html' '//a[@href="../my_rand/trait.RngCore.html"]' 'RngCore'
+/// This is an [`Rng`].
+pub use my_rand::Rng;
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs
new file mode 100644
index 000000000..684fdd449
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs
@@ -0,0 +1,6 @@
+#![crate_name = "my_rand"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub trait RngCore {}
+/// Rng extends [`RngCore`].
+pub trait Rng: RngCore {}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs
new file mode 100644
index 000000000..34f4e9f63
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs
@@ -0,0 +1,19 @@
+#![crate_name = "hidden_dep"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+#[doc(hidden)]
+pub mod __reexport {
+ pub use crate::*;
+}
+
+pub mod future {
+ mod ready {
+
+ /// Link to [`ready`](function@ready)
+ pub struct Ready;
+ pub fn ready() {}
+
+ }
+ pub use self::ready::{ready, Ready};
+
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs
new file mode 100644
index 000000000..d6a829966
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs
@@ -0,0 +1,7 @@
+#![crate_name = "a"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub struct Foo;
+
+/// Link to [Foo]
+pub struct Bar;
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs
new file mode 100644
index 000000000..a37848e23
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs
@@ -0,0 +1,5 @@
+#![crate_name = "inner"]
+
+/// Links to [crate::g]
+pub fn f() {}
+pub fn g() {}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs
new file mode 100644
index 000000000..cb7a8afb6
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs
@@ -0,0 +1,10 @@
+#![crate_name = "macro_inner"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub struct Foo;
+
+/// See also [`Foo`]
+#[macro_export]
+macro_rules! my_macro {
+ () => {}
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/module.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/module.rs
new file mode 100644
index 000000000..018fdedd9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/module.rs
@@ -0,0 +1,7 @@
+#![crate_name = "module_inner"]
+#![deny(rustdoc::broken_intra_doc_links)]
+/// [SomeType] links to [bar]
+pub struct SomeType;
+pub trait SomeTrait {}
+/// [bar] links to [SomeTrait] and also [SomeType]
+pub mod bar {}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs
new file mode 100644
index 000000000..0d5a95407
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+#![crate_type="proc-macro"]
+#![crate_name="proc_macro_inner"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+/// Links to [`OtherDerive`]
+#[proc_macro_derive(DeriveA)]
+pub fn a_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(OtherDerive)]
+pub fn other_derive(input: TokenStream) -> TokenStream {
+ input
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs
new file mode 100644
index 000000000..0612f53d6
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs
@@ -0,0 +1,12 @@
+#![crate_name = "a"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub mod bar {
+ pub struct Bar;
+}
+
+pub mod foo {
+ use crate::bar;
+ /// link to [bar::Bar]
+ pub struct Foo;
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs
new file mode 100644
index 000000000..105eb8e11
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs
@@ -0,0 +1,13 @@
+#![crate_name = "bar"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub trait Foo {
+ /// [`Bar`] [`Baz`]
+ fn foo();
+}
+
+pub trait Bar {
+}
+
+pub trait Baz {
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs b/tests/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs
new file mode 100644
index 000000000..c16e39d56
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs
@@ -0,0 +1,16 @@
+#![crate_name = "inner"]
+/// this is a trait
+pub trait SomeTrait {
+ /// this is a method for [a trait][SomeTrait]
+ fn foo();
+}
+
+pub mod bar {
+ use super::SomeTrait;
+
+ pub struct BarStruct;
+
+ impl SomeTrait for BarStruct {
+ fn foo() {}
+ }
+}
diff --git a/tests/rustdoc/intra-doc/cross-crate/basic.rs b/tests/rustdoc/intra-doc/cross-crate/basic.rs
new file mode 100644
index 000000000..ad7454918
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/basic.rs
@@ -0,0 +1,9 @@
+// aux-build:intra-doc-basic.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// from https://github.com/rust-lang/rust/issues/65983
+extern crate a;
+
+// @has 'basic/struct.Bar.html' '//a[@href="../a/struct.Foo.html"]' 'Foo'
+pub use a::Bar;
diff --git a/tests/rustdoc/intra-doc/cross-crate/crate.rs b/tests/rustdoc/intra-doc/cross-crate/crate.rs
new file mode 100644
index 000000000..edf544708
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/crate.rs
@@ -0,0 +1,6 @@
+// aux-build:intra-link-cross-crate-crate.rs
+// build-aux-docs
+#![crate_name = "outer"]
+extern crate inner;
+// @has outer/fn.f.html '//a[@href="../inner/fn.g.html"]' "crate::g"
+pub use inner::f;
diff --git a/tests/rustdoc/intra-doc/cross-crate/hidden.rs b/tests/rustdoc/intra-doc/cross-crate/hidden.rs
new file mode 100644
index 000000000..4f7d075ba
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/hidden.rs
@@ -0,0 +1,10 @@
+// aux-build:hidden.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// tests https://github.com/rust-lang/rust/issues/73363
+
+extern crate hidden_dep;
+
+// @has 'hidden/struct.Ready.html' '//a/@href' 'fn.ready.html'
+pub use hidden_dep::future::{ready, Ready};
diff --git a/tests/rustdoc/intra-doc/cross-crate/macro.rs b/tests/rustdoc/intra-doc/cross-crate/macro.rs
new file mode 100644
index 000000000..32f0a55d3
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/macro.rs
@@ -0,0 +1,11 @@
+// aux-build:macro_inner.rs
+// aux-build:proc_macro.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+extern crate macro_inner;
+extern crate proc_macro_inner;
+
+// @has 'macro/macro.my_macro.html' '//a[@href="../macro_inner/struct.Foo.html"]' 'Foo'
+pub use macro_inner::my_macro;
+// @has 'macro/derive.DeriveA.html' '//a[@href="../proc_macro_inner/derive.OtherDerive.html"]' 'OtherDerive'
+pub use proc_macro_inner::DeriveA;
diff --git a/tests/rustdoc/intra-doc/cross-crate/module.rs b/tests/rustdoc/intra-doc/cross-crate/module.rs
new file mode 100644
index 000000000..fde932265
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/module.rs
@@ -0,0 +1,8 @@
+// outer.rs
+// aux-build: module.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+extern crate module_inner;
+// @has 'module/bar/index.html' '//a[@href="../../module_inner/trait.SomeTrait.html"]' 'SomeTrait'
+// @has 'module/bar/index.html' '//a[@href="../../module_inner/struct.SomeType.html"]' 'SomeType'
+pub use module_inner::bar;
diff --git a/tests/rustdoc/intra-doc/cross-crate/submodule-inner.rs b/tests/rustdoc/intra-doc/cross-crate/submodule-inner.rs
new file mode 100644
index 000000000..577fe78a5
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/submodule-inner.rs
@@ -0,0 +1,8 @@
+// aux-build:submodule-inner.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate a;
+
+// @has 'submodule_inner/struct.Foo.html' '//a[@href="../a/bar/struct.Bar.html"]' 'Bar'
+pub use a::foo::Foo;
diff --git a/tests/rustdoc/intra-doc/cross-crate/submodule-outer.rs b/tests/rustdoc/intra-doc/cross-crate/submodule-outer.rs
new file mode 100644
index 000000000..d0c0b7e85
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/submodule-outer.rs
@@ -0,0 +1,16 @@
+// aux-build:submodule-outer.rs
+// edition:2018
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate bar as bar_;
+
+// from https://github.com/rust-lang/rust/issues/60883
+pub mod bar {
+ pub use ::bar_::Bar;
+}
+
+// NOTE: we re-exported both `Foo` and `Bar` here,
+// NOTE: so they are inlined and therefore we link to the current module.
+// @has 'submodule_outer/trait.Foo.html' '//a[@href="bar/trait.Bar.html"]' 'Bar'
+// @has 'submodule_outer/trait.Foo.html' '//a[@href="trait.Baz.html"]' 'Baz'
+pub use ::bar_::{Foo, Baz};
diff --git a/tests/rustdoc/intra-doc/cross-crate/traits.rs b/tests/rustdoc/intra-doc/cross-crate/traits.rs
new file mode 100644
index 000000000..7b9554bfd
--- /dev/null
+++ b/tests/rustdoc/intra-doc/cross-crate/traits.rs
@@ -0,0 +1,14 @@
+// aux-build:traits.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate inner;
+use inner::SomeTrait;
+
+pub struct SomeStruct;
+
+ // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'SomeTrait'
+impl SomeTrait for SomeStruct {
+ // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'a trait'
+ fn foo() {}
+}
diff --git a/tests/rustdoc/intra-doc/disambiguators-removed.rs b/tests/rustdoc/intra-doc/disambiguators-removed.rs
new file mode 100644
index 000000000..331a31413
--- /dev/null
+++ b/tests/rustdoc/intra-doc/disambiguators-removed.rs
@@ -0,0 +1,50 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+// first try backticks
+/// Trait: [`trait@Name`], fn: [`fn@Name`], [`Name`][`macro@Name`]
+// @has disambiguators_removed/struct.AtDisambiguator.html
+// @has - '//a[@href="trait.Name.html"][code]' "Name"
+// @has - '//a[@href="fn.Name.html"][code]' "Name"
+// @has - '//a[@href="macro.Name.html"][code]' "Name"
+pub struct AtDisambiguator;
+
+/// fn: [`Name()`], macro: [`Name!`]
+// @has disambiguators_removed/struct.SymbolDisambiguator.html
+// @has - '//a[@href="fn.Name.html"][code]' "Name()"
+// @has - '//a[@href="macro.Name.html"][code]' "Name!"
+pub struct SymbolDisambiguator;
+
+// Now make sure that backticks aren't added if they weren't already there
+/// [fn@Name]
+// @has disambiguators_removed/trait.Name.html
+// @has - '//a[@href="fn.Name.html"]' "Name"
+// @!has - '//a[@href="fn.Name.html"][code]' "Name"
+
+// FIXME: this will turn !() into ! alone
+/// [Name!()]
+// @has - '//a[@href="macro.Name.html"]' "Name!"
+pub trait Name {}
+
+#[allow(non_snake_case)]
+
+// Try collapsed reference links
+/// [macro@Name][]
+// @has disambiguators_removed/fn.Name.html
+// @has - '//a[@href="macro.Name.html"]' "Name"
+
+// Try links that have the same text as a generated URL
+/// Weird URL aligned [macro.Name.html][trait@Name]
+// @has - '//a[@href="trait.Name.html"]' "macro.Name.html"
+pub fn Name() {}
+
+#[macro_export]
+// Rustdoc doesn't currently handle links that have weird interspersing of inline code blocks.
+/// [fn@Na`m`e]
+// @has disambiguators_removed/macro.Name.html
+// @has - '//a[@href="fn.Name.html"]' "fn@Name"
+
+// It also doesn't handle any case where the code block isn't the whole link text:
+/// [trait@`Name`]
+// @has - '//a[@href="trait.Name.html"]' "trait@Name"
+macro_rules! Name {
+ () => ()
+}
diff --git a/tests/rustdoc/intra-doc/email-address.rs b/tests/rustdoc/intra-doc/email-address.rs
new file mode 100644
index 000000000..24161c3bb
--- /dev/null
+++ b/tests/rustdoc/intra-doc/email-address.rs
@@ -0,0 +1,10 @@
+#![forbid(rustdoc::broken_intra_doc_links)]
+
+//! Email me at <hello@example.com>.
+//! Email me at <hello-world@example.com>.
+//! Email me at <hello@localhost>.
+//! Email me at <prim@i32>.
+// @has email_address/index.html '//a[@href="mailto:hello@example.com"]' 'hello@example.com'
+// @has email_address/index.html '//a[@href="mailto:hello-world@example.com"]' 'hello-world@example.com'
+// @has email_address/index.html '//a[@href="mailto:hello@localhost"]' 'hello@localhost'
+// @has email_address/index.html '//a[@href="mailto:prim@i32"]' 'prim@i32'
diff --git a/tests/rustdoc/intra-doc/enum-struct-field.rs b/tests/rustdoc/intra-doc/enum-struct-field.rs
new file mode 100644
index 000000000..2270a1faf
--- /dev/null
+++ b/tests/rustdoc/intra-doc/enum-struct-field.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+pub enum Foo {
+ X {
+ y: u8,
+ }
+}
+
+/// Hello
+///
+/// I want [Foo::X::y].
+pub fn foo() {}
+
+// @has foo/fn.foo.html '//a/@href' 'enum.Foo.html#variant.X.field.y'
diff --git a/tests/rustdoc/intra-doc/extern-builtin-type-impl.rs b/tests/rustdoc/intra-doc/extern-builtin-type-impl.rs
new file mode 100644
index 000000000..7bb1ded3f
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-builtin-type-impl.rs
@@ -0,0 +1,11 @@
+// Reexport of a structure that derefs to a type with lang item impls having doc links in their
+// comments. The doc link points to an associated item, so we check that traits in scope for that
+// link are populated.
+
+// aux-build:extern-builtin-type-impl-dep.rs
+
+#![no_std]
+
+extern crate extern_builtin_type_impl_dep;
+
+pub use extern_builtin_type_impl_dep::DerefsToF64;
diff --git a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
new file mode 100644
index 000000000..ad50887e9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
@@ -0,0 +1,19 @@
+// This test is just a little cursed.
+// aux-build:issue-66159-1.rs
+// aux-crate:priv:issue_66159_1=issue-66159-1.rs
+// aux-build:empty.rs
+// aux-crate:priv:empty=empty.rs
+// aux-build:empty2.rs
+// aux-crate:priv:empty2=empty2.rs
+// build-aux-docs
+// compile-flags:-Z unstable-options --edition 2018
+
+// @has extern_crate_only_used_in_link/index.html
+// @has - '//a[@href="../issue_66159_1/struct.Something.html"]' 'issue_66159_1::Something'
+//! [issue_66159_1::Something]
+
+// @has - '//a[@href="../empty/index.html"]' 'empty'
+//! [`empty`]
+
+// @has - '//a[@href="../empty2/index.html"]' 'empty2'
+//! [`empty2<x>`]
diff --git a/tests/rustdoc/intra-doc/extern-crate.rs b/tests/rustdoc/intra-doc/extern-crate.rs
new file mode 100644
index 000000000..4e4438dea
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-crate.rs
@@ -0,0 +1,9 @@
+// aux-build:intra-link-extern-crate.rs
+
+// When loading `extern crate` statements, we would pull in their docs at the same time, even
+// though they would never actually get displayed. This tripped intra-doc-link resolution failures,
+// for items that aren't under our control, and not actually getting documented!
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate inner;
diff --git a/tests/rustdoc/intra-doc/extern-inherent-impl.rs b/tests/rustdoc/intra-doc/extern-inherent-impl.rs
new file mode 100644
index 000000000..2e41c2214
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-inherent-impl.rs
@@ -0,0 +1,8 @@
+// Reexport of a structure with public inherent impls having doc links in their comments. The doc
+// link points to an associated item, so we check that traits in scope for that link are populated.
+
+// aux-build:extern-inherent-impl-dep.rs
+
+extern crate extern_inherent_impl_dep;
+
+pub use extern_inherent_impl_dep::PublicStruct;
diff --git a/tests/rustdoc/intra-doc/extern-reference-link.rs b/tests/rustdoc/intra-doc/extern-reference-link.rs
new file mode 100644
index 000000000..bad6ec755
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-reference-link.rs
@@ -0,0 +1,7 @@
+// compile-flags: --extern pub_struct
+// aux-build:pub-struct.rs
+
+/// [SomeStruct]
+///
+/// [SomeStruct]: pub_struct::SomeStruct
+pub fn foo() {}
diff --git a/tests/rustdoc/intra-doc/extern-type.rs b/tests/rustdoc/intra-doc/extern-type.rs
new file mode 100644
index 000000000..5440f582d
--- /dev/null
+++ b/tests/rustdoc/intra-doc/extern-type.rs
@@ -0,0 +1,37 @@
+#![feature(extern_types)]
+
+extern {
+ pub type ExternType;
+}
+
+pub trait T {
+ fn test(&self) {}
+}
+
+pub trait G<N> {
+ fn g(&self, n: N) {}
+}
+
+impl ExternType {
+ pub fn f(&self) {}
+}
+
+impl T for ExternType {
+ fn test(&self) {}
+}
+
+impl G<usize> for ExternType {
+ fn g(&self, n: usize) {}
+}
+
+// @has 'extern_type/foreigntype.ExternType.html'
+// @hasraw 'extern_type/fn.links_to_extern_type.html' \
+// 'href="foreigntype.ExternType.html#method.f"'
+// @hasraw 'extern_type/fn.links_to_extern_type.html' \
+// 'href="foreigntype.ExternType.html#method.test"'
+// @hasraw 'extern_type/fn.links_to_extern_type.html' \
+// 'href="foreigntype.ExternType.html#method.g"'
+/// See also [ExternType::f]
+/// See also [ExternType::test]
+/// See also [ExternType::g]
+pub fn links_to_extern_type() {}
diff --git a/tests/rustdoc/intra-doc/external-traits.rs b/tests/rustdoc/intra-doc/external-traits.rs
new file mode 100644
index 000000000..a0a66f242
--- /dev/null
+++ b/tests/rustdoc/intra-doc/external-traits.rs
@@ -0,0 +1,12 @@
+// aux-build:intra-links-external-traits.rs
+// ignore-cross-compile
+
+#![crate_name = "outer"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// using a trait that has intra-doc links on it from another crate (whether re-exporting or just
+// implementing it) used to give spurious resolution failure warnings
+
+extern crate intra_links_external_traits;
+
+pub use intra_links_external_traits::ThisTrait;
diff --git a/tests/rustdoc/intra-doc/field.rs b/tests/rustdoc/intra-doc/field.rs
new file mode 100644
index 000000000..001143489
--- /dev/null
+++ b/tests/rustdoc/intra-doc/field.rs
@@ -0,0 +1,4 @@
+// @has field/index.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start'
+// @has field/index.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
+//! [start][std::ops::Range::start]
+//! [not_found][std::io::ErrorKind::NotFound]
diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs
new file mode 100644
index 000000000..fbc9fc6a9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/generic-params.rs
@@ -0,0 +1,62 @@
+// ignore-tidy-linelength
+
+#![crate_name = "foo"]
+
+//! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
+//! Here's a link to [`Iterator<Box<T>>::Item`].
+//!
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html"]' 'Vec<T>'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
+// @has foo/index.html '//a[@href="{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
+
+//! And what about a link to [just `Option`](Option) and, [with the generic, `Option<T>`](Option<T>)?
+//!
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'just Option'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'with the generic, Option<T>'
+
+//! We should also try linking to [`Result<T, E>`]; it has *two* generics!
+//! And [`Result<T, !>`] and [`Result<!, E>`].
+//!
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, !>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<!, E>'
+
+//! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
+//! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
+//! And what about something even harder? That would be [`Vec::<Box<T>>::new()`].
+//!
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
+
+//! This is also pretty tricky: [`TypeId::of::<String>()`].
+//! And this too: [`Vec::<std::error::Error>::len`].
+//!
+// @has foo/index.html '//a[@href="{{channel}}/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
+
+//! We unofficially and implicitly support things that aren't valid in the actual Rust syntax, like
+//! [`Box::<T>new()`]. We may not support them in the future!
+//!
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
+
+//! These will be resolved as regular links:
+//! - [`this is <invalid syntax> first`](https://www.rust-lang.org)
+//! - [`this is <invalid syntax> twice`]
+//! - [`<invalid syntax> thrice`](https://www.rust-lang.org)
+//! - [`<invalid syntax> four times`][rlo]
+//! - [a < b][rlo]
+//! - [c > d]
+//!
+//! [`this is <invalid syntax> twice`]: https://www.rust-lang.org
+//! [rlo]: https://www.rust-lang.org
+//! [c > d]: https://www.rust-lang.org
+//!
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'this is <invalid syntax> first'
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'this is <invalid syntax> twice'
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' '<invalid syntax> thrice'
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' '<invalid syntax> four times'
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'a < b'
+// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'c > d'
+
+use std::any::TypeId;
diff --git a/tests/rustdoc/intra-doc/generic-trait-impl.rs b/tests/rustdoc/intra-doc/generic-trait-impl.rs
new file mode 100644
index 000000000..ba8595abf
--- /dev/null
+++ b/tests/rustdoc/intra-doc/generic-trait-impl.rs
@@ -0,0 +1,20 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// Test intra-doc links on trait implementations with generics
+// regression test for issue #92662
+
+use std::marker::PhantomData;
+
+pub trait Bar<T> {
+ fn bar(&self);
+}
+
+pub struct Foo<U>(PhantomData<U>);
+
+impl<T, U> Bar<T> for Foo<U> {
+ fn bar(&self) {}
+}
+
+// @has generic_trait_impl/fn.main.html '//a[@href="struct.Foo.html#method.bar"]' 'Foo::bar'
+/// link to [`Foo::bar`]
+pub fn main() {}
diff --git a/tests/rustdoc/intra-doc/in-bodies.rs b/tests/rustdoc/intra-doc/in-bodies.rs
new file mode 100644
index 000000000..55169e5d3
--- /dev/null
+++ b/tests/rustdoc/intra-doc/in-bodies.rs
@@ -0,0 +1,30 @@
+// we need to make sure that intra-doc links on trait impls get resolved in the right scope
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub mod inner {
+ pub struct SomethingOutOfScope;
+}
+
+pub mod other {
+ use inner::SomethingOutOfScope;
+ use SomeTrait;
+
+ pub struct OtherStruct;
+
+ /// Let's link to [SomethingOutOfScope] while we're at it.
+ impl SomeTrait for OtherStruct {}
+}
+
+pub trait SomeTrait {}
+
+pub struct SomeStruct;
+
+fn __implementation_details() {
+ use inner::SomethingOutOfScope;
+
+ // FIXME: intra-links resolve in their nearest module scope, not their actual scope in cases
+ // like this
+ // Let's link to [SomethingOutOfScope] while we're at it.
+ impl SomeTrait for SomeStruct {}
+}
diff --git a/tests/rustdoc/intra-doc/issue-103463.rs b/tests/rustdoc/intra-doc/issue-103463.rs
new file mode 100644
index 000000000..4adf8a9a8
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-103463.rs
@@ -0,0 +1,8 @@
+// The `Trait` is not pulled into the crate resulting in doc links in its methods being resolved.
+
+// aux-build:issue-103463-aux.rs
+
+extern crate issue_103463_aux;
+use issue_103463_aux::Trait;
+
+fn main() {}
diff --git a/tests/rustdoc/intra-doc/issue-104145.rs b/tests/rustdoc/intra-doc/issue-104145.rs
new file mode 100644
index 000000000..9ce36740d
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-104145.rs
@@ -0,0 +1,14 @@
+// Doc links in `Trait`'s methods are resolved because it has a local impl.
+
+// aux-build:issue-103463-aux.rs
+
+extern crate issue_103463_aux;
+use issue_103463_aux::Trait;
+
+pub struct LocalType;
+
+impl Trait for LocalType {
+ fn method() {}
+}
+
+fn main() {}
diff --git a/tests/rustdoc/intra-doc/issue-66159.rs b/tests/rustdoc/intra-doc/issue-66159.rs
new file mode 100644
index 000000000..56742b397
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-66159.rs
@@ -0,0 +1,10 @@
+// aux-crate:priv:pub_struct=pub-struct.rs
+// compile-flags:-Z unstable-options
+
+// The issue was an ICE which meant that we never actually generated the docs
+// so if we have generated the docs, we're okay.
+// Since we don't generate the docs for the auxiliary files, we can't actually
+// verify that the struct is linked correctly.
+
+// @has issue_66159/index.html
+//! [pub_struct::SomeStruct]
diff --git a/tests/rustdoc/intra-doc/issue-82209.rs b/tests/rustdoc/intra-doc/issue-82209.rs
new file mode 100644
index 000000000..a5fe855cb
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-82209.rs
@@ -0,0 +1,11 @@
+#![crate_name = "foo"]
+#![deny(rustdoc::broken_intra_doc_links)]
+pub enum Foo {
+ Bar {
+ abc: i32,
+ /// [Self::Bar::abc]
+ xyz: i32,
+ },
+}
+
+// @has foo/enum.Foo.html '//a/@href' 'enum.Foo.html#variant.Bar.field.abc'
diff --git a/tests/rustdoc/intra-doc/libstd-re-export.rs b/tests/rustdoc/intra-doc/libstd-re-export.rs
new file mode 100644
index 000000000..6c41eb2b5
--- /dev/null
+++ b/tests/rustdoc/intra-doc/libstd-re-export.rs
@@ -0,0 +1,4 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(intra_doc_pointers)]
+
+pub use std::*;
diff --git a/tests/rustdoc/intra-doc/macros-disambiguators.rs b/tests/rustdoc/intra-doc/macros-disambiguators.rs
new file mode 100644
index 000000000..cd4caa6a8
--- /dev/null
+++ b/tests/rustdoc/intra-doc/macros-disambiguators.rs
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! [foo!()]
+// @has foo/index.html '//a[@href="macro.foo.html"]' 'foo!()'
+
+//! [foo!{}]
+// @has - '//a[@href="macro.foo.html"]' 'foo!{}'
+
+//! [foo![]](foo![])
+// @has - '//a[@href="macro.foo.html"]' 'foo![]'
+
+//! [foo1](foo!())
+// @has - '//a[@href="macro.foo.html"]' 'foo1'
+
+//! [foo2](foo!{})
+// @has - '//a[@href="macro.foo.html"]' 'foo2'
+
+//! [foo3](foo![])
+// @has - '//a[@href="macro.foo.html"]' 'foo3'
+
+#[macro_export]
+macro_rules! foo {
+ () => {};
+}
diff --git a/tests/rustdoc/intra-doc/mod-ambiguity.rs b/tests/rustdoc/intra-doc/mod-ambiguity.rs
new file mode 100644
index 000000000..0c7acbaf0
--- /dev/null
+++ b/tests/rustdoc/intra-doc/mod-ambiguity.rs
@@ -0,0 +1,16 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+
+pub fn foo() {
+
+}
+
+pub mod foo {}
+// @has mod_ambiguity/struct.A.html '//a/@href' 'foo/index.html'
+/// Module is [`module@foo`]
+pub struct A;
+
+
+// @has mod_ambiguity/struct.B.html '//a/@href' 'fn.foo.html'
+/// Function is [`fn@foo`]
+pub struct B;
diff --git a/tests/rustdoc/intra-doc/mod-relative.rs b/tests/rustdoc/intra-doc/mod-relative.rs
new file mode 100644
index 000000000..49d3399b9
--- /dev/null
+++ b/tests/rustdoc/intra-doc/mod-relative.rs
@@ -0,0 +1,17 @@
+pub mod wrapper {
+
+ pub struct Test<'a> {
+ data: &'a (),
+ }
+
+ impl<'a> Test<'a> {
+ pub fn do_test(&self) {}
+ }
+
+ // @has mod_relative/wrapper/demo/index.html
+ // @has - '//a/@href' '../struct.Test.html#method.do_test'
+ /// [`Test::do_test`]
+ pub mod demo {
+ }
+
+}
diff --git a/tests/rustdoc/intra-doc/no-doc-primitive.rs b/tests/rustdoc/intra-doc/no-doc-primitive.rs
new file mode 100644
index 000000000..e5eba1d8d
--- /dev/null
+++ b/tests/rustdoc/intra-doc/no-doc-primitive.rs
@@ -0,0 +1,15 @@
+// Crate tree without a `doc(primitive)` module for primitive type linked to by a doc link.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+#![rustc_coherence_is_core]
+#![crate_type = "rlib"]
+
+// @has no_doc_primitive/index.html
+//! A [`char`] and its [`char::len_utf8`].
+impl char {
+ pub fn len_utf8(self) -> usize {
+ 42
+ }
+}
diff --git a/tests/rustdoc/intra-doc/non-path-primitives.rs b/tests/rustdoc/intra-doc/non-path-primitives.rs
new file mode 100644
index 000000000..be4b44b31
--- /dev/null
+++ b/tests/rustdoc/intra-doc/non-path-primitives.rs
@@ -0,0 +1,46 @@
+#![crate_name = "foo"]
+#![feature(intra_doc_pointers)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has foo/index.html '//a[@href="{{channel}}/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
+//! [slice::rotate_left]
+
+// @has - '//a[@href="{{channel}}/std/primitive.array.html#method.map"]' 'array::map'
+//! [array::map]
+
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.len"]' '&str::len'
+//! [owned str][str]
+//! [str ref][&str]
+//! [str::is_empty]
+//! [&str::len]
+
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
+//! [pointer::is_null]
+//! [*const::is_null]
+//! [*mut::is_null]
+
+// @has - '//a[@href="{{channel}}/std/primitive.unit.html"]' 'unit'
+//! [unit]
+
+// @has - '//a[@href="{{channel}}/std/primitive.tuple.html"]' 'tuple'
+//! [tuple]
+
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' 'reference'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&mut'
+//! [reference]
+//! [&]
+//! [&mut]
+
+// @has - '//a[@href="{{channel}}/std/primitive.fn.html"]' 'fn'
+//! [fn]
+
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' 'never'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' '!'
+//! [never]
+//! [!]
diff --git a/tests/rustdoc/intra-doc/prim-assoc.rs b/tests/rustdoc/intra-doc/prim-assoc.rs
new file mode 100644
index 000000000..dfa7db8a5
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-assoc.rs
@@ -0,0 +1,4 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! [i32::MAX]
+// @has prim_assoc/index.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
diff --git a/tests/rustdoc/intra-doc/prim-associated-traits.rs b/tests/rustdoc/intra-doc/prim-associated-traits.rs
new file mode 100644
index 000000000..8639a24f7
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-associated-traits.rs
@@ -0,0 +1,46 @@
+#![feature(never_type)]
+use std::str::FromStr;
+
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f64.html#method.from_str"]' 'f64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f32.html#method.from_str"]' 'f32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.isize.html#method.from_str"]' 'isize::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i8.html#method.from_str"]' 'i8::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i16.html#method.from_str"]' 'i16::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i32.html#method.from_str"]' 'i32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i64.html#method.from_str"]' 'i64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i128.html#method.from_str"]' 'i128::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.usize.html#method.from_str"]' 'usize::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u8.html#method.from_str"]' 'u8::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u16.html#method.from_str"]' 'u16::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u32.html#method.from_str"]' 'u32::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u64.html#method.from_str"]' 'u64::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u128.html#method.from_str"]' 'u128::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.char.html#method.from_str"]' 'char::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.bool.html#method.from_str"]' 'bool::from_str()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.str.html#method.eq"]' 'str::eq()'
+// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.never.html#method.eq"]' 'never::eq()'
+/// [`f64::from_str()`] [`f32::from_str()`] [`isize::from_str()`] [`i8::from_str()`]
+/// [`i16::from_str()`] [`i32::from_str()`] [`i64::from_str()`] [`i128::from_str()`]
+/// [`u16::from_str()`] [`u32::from_str()`] [`u64::from_str()`] [`u128::from_str()`]
+/// [`usize::from_str()`] [`u8::from_str()`] [`char::from_str()`] [`bool::from_str()`]
+/// [`str::eq()`] [`never::eq()`]
+pub struct Number {
+ pub f_64: f64,
+ pub f_32: f32,
+ pub i_size: isize,
+ pub i_8: i8,
+ pub i_16: i16,
+ pub i_32: i32,
+ pub i_64: i64,
+ pub i_128: i128,
+ pub u_size: usize,
+ pub u_8: u8,
+ pub u_16: u16,
+ pub u_32: u32,
+ pub u_64: u64,
+ pub u_128: u128,
+ pub ch: char,
+ pub boolean: bool,
+ pub string: str,
+ pub n: !,
+}
diff --git a/tests/rustdoc/intra-doc/prim-methods-external-core.rs b/tests/rustdoc/intra-doc/prim-methods-external-core.rs
new file mode 100644
index 000000000..c3340af33
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-methods-external-core.rs
@@ -0,0 +1,17 @@
+// aux-build:my-core.rs
+// build-aux-docs
+// ignore-cross-compile
+// only-linux
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type = "rlib"]
+
+// @has prim_methods_external_core/index.html
+// @has - '//*[@id="main-content"]//a[@href="../my_core/primitive.char.html"]' 'char'
+// @has - '//*[@id="main-content"]//a[@href="../my_core/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+
+//! A [`char`] and its [`char::len_utf8`].
+
+extern crate my_core;
diff --git a/tests/rustdoc/intra-doc/prim-methods-local.rs b/tests/rustdoc/intra-doc/prim-methods-local.rs
new file mode 100644
index 000000000..79d8df045
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-methods-local.rs
@@ -0,0 +1,29 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(no_core, lang_items, rustc_attrs, rustdoc_internals)]
+#![no_core]
+#![rustc_coherence_is_core]
+#![crate_type = "rlib"]
+
+// @has prim_methods_local/index.html
+// @has - '//*[@id="main-content"]//a[@href="primitive.char.html"]' 'char'
+// @has - '//*[@id="main-content"]//a[@href="primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+
+//! A [prim@`char`] and its [`char::len_utf8`].
+
+#[doc(primitive = "char")]
+mod char {}
+
+impl char {
+ pub fn len_utf8(self) -> usize {
+ 42
+ }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {}
+
+#[lang = "copy"]
+pub trait Copy: Clone {}
diff --git a/tests/rustdoc/intra-doc/prim-methods.rs b/tests/rustdoc/intra-doc/prim-methods.rs
new file mode 100644
index 000000000..a412a23fd
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-methods.rs
@@ -0,0 +1,7 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has prim_methods/index.html
+// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+
+//! A [`char`] and its [`char::len_utf8`].
diff --git a/tests/rustdoc/intra-doc/prim-precedence.rs b/tests/rustdoc/intra-doc/prim-precedence.rs
new file mode 100644
index 000000000..25625b952
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-precedence.rs
@@ -0,0 +1,16 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub mod char {
+ /// [char]
+ // @has prim_precedence/char/struct.Inner.html '//a/@href' '{{channel}}/std/primitive.char.html'
+ pub struct Inner;
+}
+
+/// See [prim@char]
+// @has prim_precedence/struct.MyString.html '//a/@href' '{{channel}}/std/primitive.char.html'
+pub struct MyString;
+
+/// See also [crate::char] and [mod@char]
+// @has prim_precedence/struct.MyString2.html '//*[@href="char/index.html"]' 'crate::char'
+// @has - '//*[@href="char/index.html"]' 'mod@char'
+pub struct MyString2;
diff --git a/tests/rustdoc/intra-doc/prim-self.rs b/tests/rustdoc/intra-doc/prim-self.rs
new file mode 100644
index 000000000..c7ce71b15
--- /dev/null
+++ b/tests/rustdoc/intra-doc/prim-self.rs
@@ -0,0 +1,41 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![rustc_coherence_is_core]
+#![allow(incomplete_features)] // inherent_associated_types
+#![feature(rustc_attrs)]
+#![feature(no_core)]
+#![feature(rustdoc_internals)]
+#![feature(inherent_associated_types)]
+#![feature(lang_items)]
+#![no_core]
+
+/// [Self::f]
+/// [Self::MAX]
+// @has prim_self/primitive.usize.html
+// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+impl usize {
+ /// Some docs
+ pub fn f() {}
+
+ /// 10 and 2^32 are basically the same.
+ pub const MAX: usize = 10;
+
+ // @has - '//a[@href="primitive.usize.html#associatedtype.ME"]' 'Self::ME'
+ /// [Self::ME]
+ pub type ME = usize;
+}
+
+#[doc(primitive = "usize")]
+/// This has some docs.
+mod usize {}
+
+/// [S::f]
+/// [Self::f]
+pub struct S;
+
+impl S {
+ pub fn f() {}
+}
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/rustdoc/intra-doc/primitive-disambiguators.rs b/tests/rustdoc/intra-doc/primitive-disambiguators.rs
new file mode 100644
index 000000000..adcab767d
--- /dev/null
+++ b/tests/rustdoc/intra-doc/primitive-disambiguators.rs
@@ -0,0 +1,4 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+// @has primitive_disambiguators/index.html
+// @has - '//a/@href' '{{channel}}/std/primitive.str.html#method.trim'
+//! [str::trim()]
diff --git a/tests/rustdoc/intra-doc/primitive-non-default-impl.rs b/tests/rustdoc/intra-doc/primitive-non-default-impl.rs
new file mode 100644
index 000000000..474bf3477
--- /dev/null
+++ b/tests/rustdoc/intra-doc/primitive-non-default-impl.rs
@@ -0,0 +1,31 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+
+// @has primitive_non_default_impl/fn.str_methods.html
+/// [`str::trim`]
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.trim"]' 'str::trim'
+/// [`str::to_lowercase`]
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
+/// [`str::into_boxed_bytes`]
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
+/// [`str::replace`]
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.replace"]' 'str::replace'
+pub fn str_methods() {}
+
+// @has primitive_non_default_impl/fn.f32_methods.html
+/// [f32::powi]
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.powi"]' 'f32::powi'
+/// [f32::sqrt]
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
+/// [f32::mul_add]
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
+pub fn f32_methods() {}
+
+// @has primitive_non_default_impl/fn.f64_methods.html
+/// [`f64::powi`]
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.powi"]' 'f64::powi'
+/// [`f64::sqrt`]
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
+/// [`f64::mul_add`]
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
+pub fn f64_methods() {}
diff --git a/tests/rustdoc/intra-doc/private-failures-ignored.rs b/tests/rustdoc/intra-doc/private-failures-ignored.rs
new file mode 100644
index 000000000..b272bfb5a
--- /dev/null
+++ b/tests/rustdoc/intra-doc/private-failures-ignored.rs
@@ -0,0 +1,8 @@
+// Rustdoc would previously report resolution failures on items that weren't in the public docs.
+// These failures were legitimate, but not truly relevant - the docs in question couldn't be
+// checked for accuracy anyway.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// ooh, i'm a [rebel] just for kicks
+struct SomeStruct;
diff --git a/tests/rustdoc/intra-doc/private.rs b/tests/rustdoc/intra-doc/private.rs
new file mode 100644
index 000000000..349091e93
--- /dev/null
+++ b/tests/rustdoc/intra-doc/private.rs
@@ -0,0 +1,20 @@
+// compile-flags: --document-private-items
+
+// make sure to update `rustdoc-ui/intra-doc/private.rs` if you update this file
+
+#![allow(rustdoc::private_intra_doc_links)]
+
+#![crate_name = "private"]
+
+/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
+// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html"]' 'DontDocMe'
+// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html#method.f"]' 'DontDocMe::f'
+// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html#structfield.x"]' 'DontDocMe::x'
+pub struct DocMe;
+struct DontDocMe {
+ x: usize,
+}
+
+impl DontDocMe {
+ fn f() {}
+}
diff --git a/tests/rustdoc/intra-doc/proc-macro.rs b/tests/rustdoc/intra-doc/proc-macro.rs
new file mode 100644
index 000000000..78379a902
--- /dev/null
+++ b/tests/rustdoc/intra-doc/proc-macro.rs
@@ -0,0 +1,27 @@
+// aux-build:proc-macro-macro.rs
+// build-aux-docs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate proc_macro_macro;
+
+
+pub use proc_macro_macro::{DeriveA, attr_a};
+use proc_macro_macro::{DeriveB, attr_b};
+
+// @has proc_macro/struct.Foo.html
+// @has - '//a/@href' 'derive.DeriveA.html'
+// @has - '//a/@href' 'attr.attr_a.html'
+// @has - '//a/@href' 'trait.DeriveTrait.html'
+// @has - '//a/@href' '../proc_macro_macro/derive.DeriveB.html'
+// @has - '//a/@href' '../proc_macro_macro/attr.attr_b.html'
+/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait]
+pub struct Foo;
+
+// @has proc_macro/struct.Bar.html
+// @has - '//a/@href' 'derive.DeriveA.html'
+// @has - '//a/@href' 'attr.attr_a.html'
+/// Link to [deriveA](derive@DeriveA) [attr](macro@attr_a)
+pub struct Bar;
+
+// this should not cause ambiguity errors
+pub trait DeriveTrait {}
diff --git a/tests/rustdoc/intra-doc/pub-use.rs b/tests/rustdoc/intra-doc/pub-use.rs
new file mode 100644
index 000000000..8a998496c
--- /dev/null
+++ b/tests/rustdoc/intra-doc/pub-use.rs
@@ -0,0 +1,17 @@
+// aux-build: intra-link-pub-use.rs
+#![deny(rustdoc::broken_intra_doc_links)]
+#![crate_name = "outer"]
+
+extern crate inner;
+
+/// [mod@std::env] [g]
+// @has outer/index.html
+// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env"
+// @has - '//a[@href="fn.f.html"]' "g"
+pub use f as g;
+
+// Make sure the documentation is actually correct by documenting an inlined re-export
+/// [mod@std::env]
+// @has outer/fn.f.html
+// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env"
+pub use inner::f;
diff --git a/tests/rustdoc/intra-doc/raw-ident-self.rs b/tests/rustdoc/intra-doc/raw-ident-self.rs
new file mode 100644
index 000000000..1ed33db93
--- /dev/null
+++ b/tests/rustdoc/intra-doc/raw-ident-self.rs
@@ -0,0 +1,13 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+pub mod r#impl {
+ pub struct S;
+
+ impl S {
+ /// See [Self::b].
+ // @has raw_ident_self/impl/struct.S.html
+ // @has - '//a[@href="struct.S.html#method.b"]' 'Self::b'
+ pub fn a() {}
+
+ pub fn b() {}
+ }
+}
diff --git a/tests/rustdoc/intra-doc/reexport-additional-docs.rs b/tests/rustdoc/intra-doc/reexport-additional-docs.rs
new file mode 100644
index 000000000..64683bacd
--- /dev/null
+++ b/tests/rustdoc/intra-doc/reexport-additional-docs.rs
@@ -0,0 +1,23 @@
+// aux-build:intra-link-reexport-additional-docs.rs
+// build-aux-docs
+#![crate_name = "foo"]
+extern crate inner;
+
+// @has foo/struct.Inner.html '//a[@href="fn.with_code.html"]' 'crate::with_code'
+/// [crate::with_code]
+// @has - '//a[@href="fn.with_code.html"]' 'different text'
+/// [different text][with_code]
+// @has - '//a[@href="fn.me_too.html"]' 'me_too'
+#[doc = "[me_too]"]
+// @has - '//a[@href="fn.me_three.html"]' 'reference link'
+/// This [reference link]
+#[doc = "has an attr in the way"]
+///
+/// [reference link]: me_three
+// Should still resolve links from the original module in that scope
+// @has - '//a[@href="../inner/fn.f.html"]' 'f()'
+pub use inner::Inner;
+
+pub fn with_code() {}
+pub fn me_too() {}
+pub fn me_three() {}
diff --git a/tests/rustdoc/intra-doc/self-cache.rs b/tests/rustdoc/intra-doc/self-cache.rs
new file mode 100644
index 000000000..63bf7fa57
--- /dev/null
+++ b/tests/rustdoc/intra-doc/self-cache.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+// @has foo/enum.E1.html '//a/@href' 'enum.E1.html#variant.A'
+
+/// [Self::A::b]
+pub enum E1 {
+ A { b: usize }
+}
+
+// @has foo/enum.E2.html '//a/@href' 'enum.E2.html#variant.A'
+
+/// [Self::A::b]
+pub enum E2 {
+ A { b: usize }
+}
diff --git a/tests/rustdoc/intra-doc/self.rs b/tests/rustdoc/intra-doc/self.rs
new file mode 100644
index 000000000..0ba7df8a7
--- /dev/null
+++ b/tests/rustdoc/intra-doc/self.rs
@@ -0,0 +1,116 @@
+#![crate_name = "foo"]
+
+
+// @has foo/index.html '//a/@href' 'struct.Foo.html#method.new'
+// @has foo/struct.Foo.html '//a/@href' 'struct.Foo.html#method.new'
+
+/// Use [`new`] to create a new instance.
+///
+/// [`new`]: Self::new
+pub struct Foo;
+
+impl Foo {
+ pub fn new() -> Self {
+ unimplemented!()
+ }
+}
+
+// @has foo/index.html '//a/@href' 'struct.Bar.html#method.new2'
+// @has foo/struct.Bar.html '//a/@href' 'struct.Bar.html#method.new2'
+
+/// Use [`new2`] to create a new instance.
+///
+/// [`new2`]: Self::new2
+pub struct Bar;
+
+impl Bar {
+ pub fn new2() -> Self {
+ unimplemented!()
+ }
+}
+
+pub struct MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#structfield.struct_field'
+
+ /// [`struct_field`]
+ ///
+ /// [`struct_field`]: Self::struct_field
+ pub struct_field: u8,
+}
+
+pub enum MyEnum {
+ // @has foo/enum.MyEnum.html '//a/@href' 'enum.MyEnum.html#variant.EnumVariant'
+
+ /// [`EnumVariant`]
+ ///
+ /// [`EnumVariant`]: Self::EnumVariant
+ EnumVariant,
+}
+
+pub union MyUnion {
+ // @has foo/union.MyUnion.html '//a/@href' 'union.MyUnion.html#structfield.union_field'
+
+ /// [`union_field`]
+ ///
+ /// [`union_field`]: Self::union_field
+ pub union_field: f32,
+}
+
+pub trait MyTrait {
+ // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#associatedtype.AssoType'
+
+ /// [`AssoType`]
+ ///
+ /// [`AssoType`]: Self::AssoType
+ type AssoType;
+
+ // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#associatedconstant.ASSO_CONST'
+
+ /// [`ASSO_CONST`]
+ ///
+ /// [`ASSO_CONST`]: Self::ASSO_CONST
+ const ASSO_CONST: i32 = 1;
+
+ // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#method.asso_fn'
+
+ /// [`asso_fn`]
+ ///
+ /// [`asso_fn`]: Self::asso_fn
+ fn asso_fn() {}
+}
+
+impl MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.for_impl'
+
+ /// [`for_impl`]
+ ///
+ /// [`for_impl`]: Self::for_impl
+ pub fn for_impl() {
+ unimplemented!()
+ }
+}
+
+impl MyTrait for MyStruct {
+ // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedtype.AssoType'
+
+ /// [`AssoType`]
+ ///
+ /// [`AssoType`]: Self::AssoType
+ type AssoType = u32;
+
+ // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedconstant.ASSO_CONST'
+
+ /// [`ASSO_CONST`]
+ ///
+ /// [`ASSO_CONST`]: Self::ASSO_CONST
+ const ASSO_CONST: i32 = 10;
+
+ // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.asso_fn'
+
+ /// [`asso_fn`]
+ ///
+ /// [`asso_fn`]: Self::asso_fn
+ fn asso_fn() {
+ unimplemented!()
+ }
+}
diff --git a/tests/rustdoc/intra-doc/trait-impl.rs b/tests/rustdoc/intra-doc/trait-impl.rs
new file mode 100644
index 000000000..cf60dc1db
--- /dev/null
+++ b/tests/rustdoc/intra-doc/trait-impl.rs
@@ -0,0 +1,34 @@
+#![crate_name = "foo"]
+
+
+pub struct MyStruct;
+
+impl MyTrait for MyStruct {
+
+// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedtype.AssoType'
+
+ /// [`AssoType`]
+ ///
+ /// [`AssoType`]: MyStruct::AssoType
+ type AssoType = u32;
+
+// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedconstant.ASSO_CONST'
+
+ /// [`ASSO_CONST`]
+ ///
+ /// [`ASSO_CONST`]: MyStruct::ASSO_CONST
+ const ASSO_CONST: i32 = 10;
+
+// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.trait_fn'
+
+ /// [`trait_fn`]
+ ///
+ /// [`trait_fn`]: MyStruct::trait_fn
+ fn trait_fn() { }
+}
+
+pub trait MyTrait {
+ type AssoType;
+ const ASSO_CONST: i32 = 1;
+ fn trait_fn();
+}
diff --git a/tests/rustdoc/intra-doc/trait-item.rs b/tests/rustdoc/intra-doc/trait-item.rs
new file mode 100644
index 000000000..e95dba33b
--- /dev/null
+++ b/tests/rustdoc/intra-doc/trait-item.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+/// Link to [S::assoc_fn()]
+/// Link to [Default::default()]
+// @has trait_item/struct.S.html '//*[@href="struct.S.html#method.assoc_fn"]' 'S::assoc_fn()'
+// @has - '//*[@href="{{channel}}/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
+pub struct S;
+
+impl S {
+ pub fn assoc_fn() {}
+}
diff --git a/tests/rustdoc/intra-doc/true-false.rs b/tests/rustdoc/intra-doc/true-false.rs
new file mode 100644
index 000000000..e02be9cab
--- /dev/null
+++ b/tests/rustdoc/intra-doc/true-false.rs
@@ -0,0 +1,8 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+#![crate_name = "foo"]
+
+// @has foo/index.html
+// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'true'
+// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'false'
+
+//! A `bool` is either [`true`] or [`false`].
diff --git a/tests/rustdoc/intra-doc/type-alias.rs b/tests/rustdoc/intra-doc/type-alias.rs
new file mode 100644
index 000000000..6c52082a2
--- /dev/null
+++ b/tests/rustdoc/intra-doc/type-alias.rs
@@ -0,0 +1,19 @@
+// Regression test for issue #86120.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+/// You should really try [`Self::bar`]!
+pub type Bar = Foo;
+
+impl Bar {
+ pub fn bar() {}
+}
+
+/// The minimum is [`Self::MIN`].
+pub type Int = i32;
+
+// @has foo/type.Bar.html '//a[@href="struct.Foo.html#method.bar"]' 'Self::bar'
+// @has foo/type.Int.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MIN"]' 'Self::MIN'
diff --git a/tests/rustdoc/invalid.crate.name.rs b/tests/rustdoc/invalid.crate.name.rs
new file mode 100644
index 000000000..c19713b56
--- /dev/null
+++ b/tests/rustdoc/invalid.crate.name.rs
@@ -0,0 +1,3 @@
+// compile-flags: --crate-name foo
+
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs b/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs
new file mode 100644
index 000000000..3e20c5c07
--- /dev/null
+++ b/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-100204-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name="second"]
+
+extern crate first;
+
+pub mod prelude {}
+
+// @has first/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
+// @has second/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
+#[doc(inline)]
+pub use first::*;
diff --git a/tests/rustdoc/issue-100241.rs b/tests/rustdoc/issue-100241.rs
new file mode 100644
index 000000000..9e9cba13a
--- /dev/null
+++ b/tests/rustdoc/issue-100241.rs
@@ -0,0 +1,12 @@
+//! See [`S`].
+
+// Check that this isn't an ICE
+// should-fail
+
+mod foo {
+ pub use inner::S;
+ //~^ ERROR unresolved imports `inner`, `foo::S`
+}
+
+use foo::*;
+use foo::S;
diff --git a/tests/rustdoc/issue-100620.rs b/tests/rustdoc/issue-100620.rs
new file mode 100644
index 000000000..097666eb5
--- /dev/null
+++ b/tests/rustdoc/issue-100620.rs
@@ -0,0 +1,19 @@
+pub trait Bar<S> {}
+
+pub trait Qux<T> {}
+
+pub trait Foo<T, S> {
+ fn bar()
+ where
+ T: Bar<S>,
+ {
+ }
+}
+
+pub struct Concrete;
+
+impl<S> Foo<(), S> for Concrete {}
+
+impl<T, S> Bar<S> for T where S: Qux<T> {}
+
+impl<T, S> Qux<T> for S where T: Bar<S> {}
diff --git a/tests/rustdoc/issue-100679-sidebar-links-deref.rs b/tests/rustdoc/issue-100679-sidebar-links-deref.rs
new file mode 100644
index 000000000..f09d23206
--- /dev/null
+++ b/tests/rustdoc/issue-100679-sidebar-links-deref.rs
@@ -0,0 +1,30 @@
+#![crate_name="foo"]
+
+pub struct Vec;
+
+pub struct Slice;
+
+impl std::ops::Deref for Vec {
+ type Target = Slice;
+ fn deref(&self) -> &Slice {
+ &Slice
+ }
+}
+
+// @has foo/struct.Vec.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty"]' \
+// "is_empty"
+impl Vec {
+ pub fn is_empty(&self) -> bool {
+ true
+ }
+}
+
+// @has foo/struct.Vec.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty-1"]' \
+// "is_empty"
+// @has foo/struct.Slice.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty"]' \
+// "is_empty"
+impl Slice {
+ pub fn is_empty(&self) -> bool {
+ true
+ }
+}
diff --git a/tests/rustdoc/issue-101743-bold-tag.rs b/tests/rustdoc/issue-101743-bold-tag.rs
new file mode 100644
index 000000000..631181fec
--- /dev/null
+++ b/tests/rustdoc/issue-101743-bold-tag.rs
@@ -0,0 +1,19 @@
+// Regression test for https://github.com/rust-lang/rust/issues/101743
+
+#![crate_name="foo"]
+
+pub type Word = usize;
+pub struct Repr<const B: usize>([i32; B]);
+pub struct IBig(usize);
+
+pub const fn base_as_ibig<const B: Word>() -> IBig {
+ IBig(B)
+}
+
+impl<const B: Word> Repr<B> {
+ // If we change back to rendering the value of consts, check this doesn't add
+ // a <b> tag, but escapes correctly
+
+ // @has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '= _'
+ pub const BASE: IBig = base_as_ibig::<B>();
+}
diff --git a/tests/rustdoc/issue-102154.rs b/tests/rustdoc/issue-102154.rs
new file mode 100644
index 000000000..b36f27080
--- /dev/null
+++ b/tests/rustdoc/issue-102154.rs
@@ -0,0 +1,13 @@
+trait A<Y, N> {
+ type B;
+}
+type MaybeBox<T> = <T as A<T, Box<T>>>::B;
+struct P {
+ t: MaybeBox<P>
+}
+impl<Y, N> A<Y, N> for P {
+ type B = N;
+}
+fn main() {
+ let t: MaybeBox<P>;
+}
diff --git a/tests/rustdoc/issue-105952.rs b/tests/rustdoc/issue-105952.rs
new file mode 100644
index 000000000..e3f1df006
--- /dev/null
+++ b/tests/rustdoc/issue-105952.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+#![feature(associated_const_equality)]
+pub enum ParseMode {
+ Raw,
+}
+pub trait Parse {
+ const PARSE_MODE: ParseMode;
+}
+pub trait RenderRaw {}
+
+// @hasraw foo/trait.RenderRaw.html 'impl'
+// @hasraw foo/trait.RenderRaw.html 'ParseMode::Raw'
+impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}
diff --git a/tests/rustdoc/issue-107350.rs b/tests/rustdoc/issue-107350.rs
new file mode 100644
index 000000000..75f378ed2
--- /dev/null
+++ b/tests/rustdoc/issue-107350.rs
@@ -0,0 +1,18 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/107350>.
+// It shouldn't loop indefinitely.
+
+#![crate_name = "foo"]
+
+// @has 'foo/oops/enum.OhNo.html'
+
+pub mod oops {
+ pub use crate::oops::OhNo;
+
+ mod inner {
+ pub enum OhNo {
+ Item = 1,
+ }
+ }
+
+ pub use self::inner::*;
+}
diff --git a/tests/rustdoc/issue-12834.rs b/tests/rustdoc/issue-12834.rs
new file mode 100644
index 000000000..9605a1e78
--- /dev/null
+++ b/tests/rustdoc/issue-12834.rs
@@ -0,0 +1,12 @@
+// Tests that failing to syntax highlight a rust code-block doesn't cause
+// rustdoc to fail, while still rendering the code-block (without highlighting).
+
+#![allow(rustdoc::invalid_rust_codeblocks)]
+
+// @has issue_12834/fn.foo.html
+// @has - //pre 'a + b '
+
+/// ```
+/// a + b ∈ Self ∀ a, b ∈ Self
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-13698.rs b/tests/rustdoc/issue-13698.rs
new file mode 100644
index 000000000..3046a8a28
--- /dev/null
+++ b/tests/rustdoc/issue-13698.rs
@@ -0,0 +1,16 @@
+// aux-build:issue-13698.rs
+// ignore-cross-compile
+
+extern crate issue_13698;
+
+pub struct Foo;
+// @!has issue_13698/struct.Foo.html '//*[@id="method.foo"]' 'fn foo'
+impl issue_13698::Foo for Foo {}
+
+pub trait Bar {
+ #[doc(hidden)]
+ fn bar(&self) {}
+}
+
+// @!has issue_13698/struct.Foo.html '//*[@id="method.bar"]' 'fn bar'
+impl Bar for Foo {}
diff --git a/tests/rustdoc/issue-15169.rs b/tests/rustdoc/issue-15169.rs
new file mode 100644
index 000000000..e525d85e2
--- /dev/null
+++ b/tests/rustdoc/issue-15169.rs
@@ -0,0 +1,3 @@
+// @has issue_15169/struct.Foo.html '//*[@id="method.eq"]' 'fn eq'
+#[derive(PartialEq)]
+pub struct Foo;
diff --git a/tests/rustdoc/issue-15318-2.rs b/tests/rustdoc/issue-15318-2.rs
new file mode 100644
index 000000000..f7f5052a3
--- /dev/null
+++ b/tests/rustdoc/issue-15318-2.rs
@@ -0,0 +1,12 @@
+// aux-build:issue-15318.rs
+// ignore-cross-compile
+#![no_std]
+
+extern crate issue_15318;
+
+pub use issue_15318::ptr;
+
+// @has issue_15318_2/fn.bar.html \
+// '//*[@href="primitive.pointer.html"]' \
+// '*mut T'
+pub fn bar<T>(ptr: *mut T) {}
diff --git a/tests/rustdoc/issue-15318-3.rs b/tests/rustdoc/issue-15318-3.rs
new file mode 100644
index 000000000..2fadc26b0
--- /dev/null
+++ b/tests/rustdoc/issue-15318-3.rs
@@ -0,0 +1,7 @@
+#![feature(rustdoc_internals)]
+
+// @has issue_15318_3/primitive.pointer.html
+
+/// dox
+#[doc(primitive = "pointer")]
+pub mod ptr {}
diff --git a/tests/rustdoc/issue-15318.rs b/tests/rustdoc/issue-15318.rs
new file mode 100644
index 000000000..0349fe285
--- /dev/null
+++ b/tests/rustdoc/issue-15318.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-15318.rs
+// ignore-cross-compile
+
+#![no_std]
+
+extern crate issue_15318;
+
+// @has issue_15318/fn.bar.html \
+// '//*[@href="http://example.com/issue_15318/primitive.pointer.html"]' \
+// '*mut T'
+pub fn bar<T>(ptr: *mut T) {}
diff --git a/tests/rustdoc/issue-15347.rs b/tests/rustdoc/issue-15347.rs
new file mode 100644
index 000000000..e93d74011
--- /dev/null
+++ b/tests/rustdoc/issue-15347.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Z unstable-options --document-hidden-items
+
+// @has issue_15347/fn.foo.html
+#[doc(hidden)]
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-16019.rs b/tests/rustdoc/issue-16019.rs
new file mode 100644
index 000000000..239d92378
--- /dev/null
+++ b/tests/rustdoc/issue-16019.rs
@@ -0,0 +1,9 @@
+macro_rules! define_struct {
+ ($rounds:expr) => (
+ struct Struct {
+ sk: [u32; $rounds + 1]
+ }
+ )
+}
+
+define_struct!(2);
diff --git a/tests/rustdoc/issue-16265-1.rs b/tests/rustdoc/issue-16265-1.rs
new file mode 100644
index 000000000..2fda637a6
--- /dev/null
+++ b/tests/rustdoc/issue-16265-1.rs
@@ -0,0 +1,10 @@
+pub struct Foo;
+
+// @hasraw issue_16265_1/traits/index.html 'source'
+pub mod traits {
+ impl PartialEq for super::Foo {
+ fn eq(&self, _: &super::Foo) -> bool {
+ true
+ }
+ }
+}
diff --git a/tests/rustdoc/issue-16265-2.rs b/tests/rustdoc/issue-16265-2.rs
new file mode 100644
index 000000000..c3eb35617
--- /dev/null
+++ b/tests/rustdoc/issue-16265-2.rs
@@ -0,0 +1,4 @@
+// @hasraw issue_16265_2/index.html 'source'
+
+trait Y {}
+impl Y for Option<u32> {}
diff --git a/tests/rustdoc/issue-17476.rs b/tests/rustdoc/issue-17476.rs
new file mode 100644
index 000000000..a5b484c98
--- /dev/null
+++ b/tests/rustdoc/issue-17476.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-17476.rs
+// ignore-cross-compile
+
+extern crate issue_17476;
+
+pub struct Foo;
+
+// @has issue_17476/struct.Foo.html \
+// '//*[@href="http://example.com/issue_17476/trait.Foo.html#method.foo"]' \
+// 'foo'
+impl issue_17476::Foo for Foo {}
diff --git a/tests/rustdoc/issue-18199.rs b/tests/rustdoc/issue-18199.rs
new file mode 100644
index 000000000..bc0c4a565
--- /dev/null
+++ b/tests/rustdoc/issue-18199.rs
@@ -0,0 +1,9 @@
+// compile-flags:--test
+
+#![doc(test(attr(feature(staged_api))))]
+
+/// ```
+/// #![unstable(feature="test", issue="18199")]
+/// fn main() {}
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-19181.rs b/tests/rustdoc/issue-19181.rs
new file mode 100644
index 000000000..3dea152fc
--- /dev/null
+++ b/tests/rustdoc/issue-19181.rs
@@ -0,0 +1,5 @@
+// compile-flags:--test
+
+// rustdoc should not panic when target crate has compilation errors
+
+fn main() { 0 }
diff --git a/tests/rustdoc/issue-19190-2.rs b/tests/rustdoc/issue-19190-2.rs
new file mode 100644
index 000000000..b6416e2e5
--- /dev/null
+++ b/tests/rustdoc/issue-19190-2.rs
@@ -0,0 +1,12 @@
+use std::ops::Deref;
+
+pub struct Bar;
+
+impl Deref for Bar {
+ type Target = String;
+ fn deref(&self) -> &String { loop {} }
+}
+
+// @has issue_19190_2/struct.Bar.html
+// @!has - '//*[@id="method.new"]' 'fn new() -> String'
+// @has - '//*[@id="method.as_str"]' 'fn as_str(&self) -> &str'
diff --git a/tests/rustdoc/issue-19190-3.rs b/tests/rustdoc/issue-19190-3.rs
new file mode 100644
index 000000000..4d34ce650
--- /dev/null
+++ b/tests/rustdoc/issue-19190-3.rs
@@ -0,0 +1,27 @@
+// aux-build:issue-19190-3.rs
+// ignore-cross-compile
+
+extern crate issue_19190_3;
+
+use std::ops::Deref;
+use issue_19190_3::Baz;
+
+// @has issue_19190_3/struct.Foo.html
+// @has - '//*[@id="method.as_str"]' 'fn as_str(&self) -> &str'
+// @!has - '//*[@id="method.new"]' 'fn new() -> String'
+pub use issue_19190_3::Foo;
+
+// @has issue_19190_3/struct.Bar.html
+// @has - '//*[@id="method.baz"]' 'fn baz(&self)'
+// @!has - '//*[@id="method.static_baz"]' 'fn static_baz()'
+pub use issue_19190_3::Bar;
+
+// @has issue_19190_3/struct.MyBar.html
+// @has - '//*[@id="method.baz"]' 'fn baz(&self)'
+// @!has - '//*[@id="method.static_baz"]' 'fn static_baz()'
+pub struct MyBar;
+
+impl Deref for MyBar {
+ type Target = Baz;
+ fn deref(&self) -> &Baz { loop {} }
+}
diff --git a/tests/rustdoc/issue-19190.rs b/tests/rustdoc/issue-19190.rs
new file mode 100644
index 000000000..2046273e2
--- /dev/null
+++ b/tests/rustdoc/issue-19190.rs
@@ -0,0 +1,20 @@
+use std::ops::Deref;
+
+pub struct Foo;
+pub struct Bar;
+
+impl Foo {
+ pub fn foo(&self) {}
+ pub fn static_foo() {}
+}
+
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Foo { loop {} }
+}
+
+// @has issue_19190/struct.Bar.html
+// @has - '//*[@id="method.foo"]//h4[@class="code-header"]' 'fn foo(&self)'
+// @has - '//*[@id="method.foo"]' 'fn foo(&self)'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
diff --git a/tests/rustdoc/issue-20175.rs b/tests/rustdoc/issue-20175.rs
new file mode 100644
index 000000000..6a42e2afb
--- /dev/null
+++ b/tests/rustdoc/issue-20175.rs
@@ -0,0 +1,10 @@
+pub trait Foo {
+ fn foo(&self) {}
+}
+
+pub struct Bar;
+
+// @has issue_20175/struct.Bar.html \
+// '//*[@id="method.foo"]' \
+// 'fn foo'
+impl<'a> Foo for &'a Bar {}
diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/issue-20646.rs
new file mode 100644
index 000000000..a774b0ca7
--- /dev/null
+++ b/tests/rustdoc/issue-20646.rs
@@ -0,0 +1,26 @@
+// aux-build:issue-20646.rs
+// ignore-cross-compile
+
+#![feature(associated_types)]
+
+extern crate issue_20646;
+
+// @has issue_20646/trait.Trait.html \
+// '//*[@id="associatedtype.Output"]' \
+// 'type Output'
+pub trait Trait {
+ type Output;
+}
+
+// @has issue_20646/fn.fun.html \
+// '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+pub fn fun<T>(_: T) where T: Trait<Output=i32> {}
+
+pub mod reexport {
+ // @has issue_20646/reexport/trait.Trait.html \
+ // '//*[@id="associatedtype.Output"]' \
+ // 'type Output'
+ // @has issue_20646/reexport/fn.fun.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+ pub use issue_20646::{Trait, fun};
+}
diff --git a/tests/rustdoc/issue-20727-2.rs b/tests/rustdoc/issue-20727-2.rs
new file mode 100644
index 000000000..026b4f5ac
--- /dev/null
+++ b/tests/rustdoc/issue-20727-2.rs
@@ -0,0 +1,22 @@
+// aux-build:issue-20727.rs
+// ignore-cross-compile
+
+extern crate issue_20727;
+
+// @has issue_20727_2/trait.Add.html
+pub trait Add<RHS = Self> {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+ type Output;
+
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+// @has issue_20727_2/reexport/trait.Add.html
+pub mod reexport {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ pub use issue_20727::Add;
+}
diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/issue-20727-3.rs
new file mode 100644
index 000000000..741ce8023
--- /dev/null
+++ b/tests/rustdoc/issue-20727-3.rs
@@ -0,0 +1,24 @@
+// aux-build:issue-20727.rs
+// ignore-cross-compile
+
+extern crate issue_20727;
+
+pub trait Bar {}
+
+// @has issue_20727_3/trait.Deref2.html
+pub trait Deref2 {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+ type Target: Bar;
+
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ fn deref(&self) -> Self::Target;
+}
+
+// @has issue_20727_3/reexport/trait.Deref2.html
+pub mod reexport {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ pub use issue_20727::Deref2;
+}
diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/issue-20727-4.rs
new file mode 100644
index 000000000..b8fac4da6
--- /dev/null
+++ b/tests/rustdoc/issue-20727-4.rs
@@ -0,0 +1,40 @@
+// aux-build:issue-20727.rs
+// ignore-cross-compile
+
+extern crate issue_20727;
+
+// @has issue_20727_4/trait.Index.html
+pub trait Index<Idx: ?Sized> {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx: ?Sized> {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+ type Output: ?Sized;
+
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'fn index(&self, index: Idx) -> &Self::Output'
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+// @has issue_20727_4/trait.IndexMut.html
+pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'trait IndexMut<Idx: ?Sized>: Index<Idx> {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
+ fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
+}
+
+pub mod reexport {
+ // @has issue_20727_4/reexport/trait.Index.html
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx>where Idx: ?Sized,{'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'fn index(&self, index: Idx) -> &Self::Output'
+ pub use issue_20727::Index;
+
+ // @has issue_20727_4/reexport/trait.IndexMut.html
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
+ pub use issue_20727::IndexMut;
+}
diff --git a/tests/rustdoc/issue-20727.rs b/tests/rustdoc/issue-20727.rs
new file mode 100644
index 000000000..df334821c
--- /dev/null
+++ b/tests/rustdoc/issue-20727.rs
@@ -0,0 +1,24 @@
+// aux-build:issue-20727.rs
+// ignore-cross-compile
+
+extern crate issue_20727;
+
+// @has issue_20727/trait.Deref.html
+pub trait Deref {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+ type Target: ?Sized;
+
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // "fn deref<'a>(&'a self) -> &'a Self::Target;"
+ fn deref<'a>(&'a self) -> &'a Self::Target;
+}
+
+// @has issue_20727/reexport/trait.Deref.html
+pub mod reexport {
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // "fn deref<'a>(&'a self) -> &'a Self::Target;"
+ pub use issue_20727::Deref;
+}
diff --git a/tests/rustdoc/issue-21092.rs b/tests/rustdoc/issue-21092.rs
new file mode 100644
index 000000000..b054145a4
--- /dev/null
+++ b/tests/rustdoc/issue-21092.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-21092.rs
+// ignore-cross-compile
+
+extern crate issue_21092;
+
+// @has issue_21092/struct.Bar.html
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar = i32'
+pub use issue_21092::{Foo, Bar};
diff --git a/tests/rustdoc/issue-21474.rs b/tests/rustdoc/issue-21474.rs
new file mode 100644
index 000000000..43ce13fd9
--- /dev/null
+++ b/tests/rustdoc/issue-21474.rs
@@ -0,0 +1,11 @@
+pub use inner::*;
+
+mod inner {
+ impl super::Blah for super::What { }
+}
+
+pub trait Blah { }
+
+// @count issue_21474/struct.What.html \
+// '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+pub struct What;
diff --git a/tests/rustdoc/issue-21801.rs b/tests/rustdoc/issue-21801.rs
new file mode 100644
index 000000000..29d2ec64c
--- /dev/null
+++ b/tests/rustdoc/issue-21801.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-21801.rs
+// ignore-cross-compile
+
+extern crate issue_21801;
+
+// @has issue_21801/struct.Foo.html
+// @has - '//*[@id="method.new"]' \
+// 'fn new<F>(f: F) -> Foowhere F: FnMut() -> i32'
+pub use issue_21801::Foo;
diff --git a/tests/rustdoc/issue-22025.rs b/tests/rustdoc/issue-22025.rs
new file mode 100644
index 000000000..a721a15f4
--- /dev/null
+++ b/tests/rustdoc/issue-22025.rs
@@ -0,0 +1,6 @@
+// aux-build:issue-22025.rs
+// ignore-cross-compile
+
+extern crate issue_22025;
+
+pub use issue_22025::foo::{Foo, Bar};
diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/issue-22038.rs
new file mode 100644
index 000000000..19e626ba1
--- /dev/null
+++ b/tests/rustdoc/issue-22038.rs
@@ -0,0 +1,19 @@
+extern "C" {
+ // @has issue_22038/fn.foo1.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
+ pub fn foo1();
+}
+
+extern "system" {
+ // @has issue_22038/fn.foo2.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
+ pub fn foo2();
+}
+
+// @has issue_22038/fn.bar.html \
+// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
+pub extern "C" fn bar() {}
+
+// @has issue_22038/fn.baz.html \
+// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "system" fn baz()'
+pub extern "system" fn baz() {}
diff --git a/tests/rustdoc/issue-23106.rs b/tests/rustdoc/issue-23106.rs
new file mode 100644
index 000000000..8cda2fc33
--- /dev/null
+++ b/tests/rustdoc/issue-23106.rs
@@ -0,0 +1,7 @@
+// compile-flags:--test
+
+/// ```
+/// #
+/// ```
+pub fn main() {
+}
diff --git a/tests/rustdoc/issue-23207.rs b/tests/rustdoc/issue-23207.rs
new file mode 100644
index 000000000..1a4b849ee
--- /dev/null
+++ b/tests/rustdoc/issue-23207.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-23207-1.rs
+// aux-build:issue-23207-2.rs
+// ignore-cross-compile
+
+extern crate issue_23207_2;
+
+// @has issue_23207/fmt/index.html
+// @count - '//*[@class="struct"]' 1
+pub use issue_23207_2::fmt;
diff --git a/tests/rustdoc/issue-23511.rs b/tests/rustdoc/issue-23511.rs
new file mode 100644
index 000000000..7576ebb03
--- /dev/null
+++ b/tests/rustdoc/issue-23511.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+#![feature(rustdoc_internals)]
+#![no_std]
+
+pub mod str {
+ #![doc(primitive = "str")]
+
+ impl str {
+ // @hasraw search-index.js foo
+ #[rustc_allow_incoherent_impl]
+ pub fn foo(&self) {}
+ }
+}
diff --git a/tests/rustdoc/issue-23744.rs b/tests/rustdoc/issue-23744.rs
new file mode 100644
index 000000000..642817396
--- /dev/null
+++ b/tests/rustdoc/issue-23744.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test
+
+/// Example of rustdoc incorrectly parsing <code>```rust,should_panic</code>.
+///
+/// ```should_panic
+/// fn main() { panic!("fee"); }
+/// ```
+///
+/// ```rust,should_panic
+/// fn main() { panic!("fum"); }
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-23812.rs b/tests/rustdoc/issue-23812.rs
new file mode 100644
index 000000000..08fd1833b
--- /dev/null
+++ b/tests/rustdoc/issue-23812.rs
@@ -0,0 +1,36 @@
+macro_rules! doc {
+ (#[$outer:meta] mod $i:ident { #![$inner:meta] }) =>
+ (
+ #[$outer]
+ pub mod $i {
+ #![$inner]
+ }
+ )
+}
+
+doc! {
+ /// Outer comment
+ mod Foo {
+ //! Inner comment
+ }
+}
+
+// @has issue_23812/Foo/index.html
+// @hasraw - 'Outer comment'
+// @!hasraw - '/// Outer comment'
+// @hasraw - 'Inner comment'
+// @!hasraw - '//! Inner comment'
+
+
+doc! {
+ /** Outer block comment */
+ mod Bar {
+ /*! Inner block comment */
+ }
+}
+
+// @has issue_23812/Bar/index.html
+// @hasraw - 'Outer block comment'
+// @!hasraw - '/** Outer block comment */'
+// @hasraw - 'Inner block comment'
+// @!hasraw - '/*! Inner block comment */'
diff --git a/tests/rustdoc/issue-25001.rs b/tests/rustdoc/issue-25001.rs
new file mode 100644
index 000000000..c97b35ada
--- /dev/null
+++ b/tests/rustdoc/issue-25001.rs
@@ -0,0 +1,43 @@
+// @has issue_25001/struct.Foo.html
+pub struct Foo<T>(T);
+
+pub trait Bar {
+ type Item;
+
+ fn quux(self);
+}
+
+impl Foo<u8> {
+ // @has - '//*[@id="method.pass"]//h4[@class="code-header"]' 'fn pass()'
+ pub fn pass() {}
+}
+impl Foo<u16> {
+ // @has - '//*[@id="method.pass-1"]//h4[@class="code-header"]' 'fn pass() -> usize'
+ pub fn pass() -> usize { 42 }
+}
+impl Foo<u32> {
+ // @has - '//*[@id="method.pass-2"]//h4[@class="code-header"]' 'fn pass() -> isize'
+ pub fn pass() -> isize { 42 }
+}
+
+impl<T> Bar for Foo<T> {
+ // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' 'type Item = T'
+ type Item=T;
+
+ // @has - '//*[@id="method.quux"]//h4[@class="code-header"]' 'fn quux(self)'
+ fn quux(self) {}
+}
+impl<'a, T> Bar for &'a Foo<T> {
+ // @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item = &'a T"
+ type Item=&'a T;
+
+ // @has - '//*[@id="method.quux-1"]//h4[@class="code-header"]' 'fn quux(self)'
+ fn quux(self) {}
+}
+impl<'a, T> Bar for &'a mut Foo<T> {
+ // @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item = &'a mut T"
+ type Item=&'a mut T;
+
+ // @has - '//*[@id="method.quux-2"]//h4[@class="code-header"]' 'fn quux(self)'
+ fn quux(self) {}
+}
diff --git a/tests/rustdoc/issue-25944.rs b/tests/rustdoc/issue-25944.rs
new file mode 100644
index 000000000..49625294b
--- /dev/null
+++ b/tests/rustdoc/issue-25944.rs
@@ -0,0 +1,11 @@
+// compile-flags:--test
+
+/// ```
+/// let a = r#"
+/// foo
+/// bar"#;
+/// let b = "\nfoo\nbar";
+/// assert_eq!(a, b);
+/// ```
+pub fn main() {
+}
diff --git a/tests/rustdoc/issue-26606.rs b/tests/rustdoc/issue-26606.rs
new file mode 100644
index 000000000..d5cb2c710
--- /dev/null
+++ b/tests/rustdoc/issue-26606.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-26606-macro.rs
+// ignore-cross-compile
+// build-aux-docs
+
+// @has issue_26606_macro/macro.make_item.html
+#[macro_use]
+extern crate issue_26606_macro;
+
+// @has issue_26606/constant.FOO.html
+// @has - '//a[@href="../src/issue_26606/issue-26606.rs.html#11"]' 'source'
+make_item!(FOO);
diff --git a/tests/rustdoc/issue-26995.rs b/tests/rustdoc/issue-26995.rs
new file mode 100644
index 000000000..fedc9f517
--- /dev/null
+++ b/tests/rustdoc/issue-26995.rs
@@ -0,0 +1,7 @@
+// ignore-windows
+// compile-flags: --no-defaults
+
+// @has src/issue_26995/dev/null.html
+// @has issue_26995/null/index.html '//a/@href' '../../src/issue_26995/dev/null.html'
+#[path="/dev/null"]
+pub mod null;
diff --git a/tests/rustdoc/issue-27104.rs b/tests/rustdoc/issue-27104.rs
new file mode 100644
index 000000000..9f2fd9071
--- /dev/null
+++ b/tests/rustdoc/issue-27104.rs
@@ -0,0 +1,10 @@
+// compile-flags:--no-defaults --passes strip-priv-imports
+// aux-build:empty.rs
+// ignore-cross-compile
+
+// @has issue_27104/index.html
+// @!hasraw - 'extern crate std'
+// @!hasraw - 'use std::prelude::'
+
+// @hasraw - 'pub extern crate empty'
+pub extern crate empty;
diff --git a/tests/rustdoc/issue-27362.rs b/tests/rustdoc/issue-27362.rs
new file mode 100644
index 000000000..097e4e3b0
--- /dev/null
+++ b/tests/rustdoc/issue-27362.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-27362-aux.rs
+// ignore-cross-compile
+
+extern crate issue_27362_aux;
+
+pub use issue_27362_aux::*;
+
+// @matches issue_27362/fn.foo.html '//pre' "pub const fn foo()"
+// @matches issue_27362/fn.bar.html '//pre' "pub const unsafe fn bar()"
+// @matches issue_27362/struct.Foo.html '//h4[@class="code-header"]' "const unsafe fn baz()"
diff --git a/tests/rustdoc/issue-27759.rs b/tests/rustdoc/issue-27759.rs
new file mode 100644
index 000000000..65e0f7cb8
--- /dev/null
+++ b/tests/rustdoc/issue-27759.rs
@@ -0,0 +1,14 @@
+#![feature(staged_api)]
+#![doc(issue_tracker_base_url = "http://issue_url/")]
+
+#![unstable(feature="test", issue="27759")]
+
+// @has issue_27759/unstable/index.html
+// @hasraw - '<code>test</code>&nbsp;<a href="http://issue_url/27759">#27759</a>'
+#[unstable(feature="test", issue="27759")]
+pub mod unstable {
+ // @has issue_27759/unstable/fn.issue.html
+ // @hasraw - '<code>test_function</code>&nbsp;<a href="http://issue_url/12345">#12345</a>'
+ #[unstable(feature="test_function", issue="12345")]
+ pub fn issue() {}
+}
diff --git a/tests/rustdoc/issue-27862.rs b/tests/rustdoc/issue-27862.rs
new file mode 100644
index 000000000..77522f1be
--- /dev/null
+++ b/tests/rustdoc/issue-27862.rs
@@ -0,0 +1,4 @@
+/// Tests | Table
+/// ------|-------------
+/// t = b | id = \|x\| x
+pub struct Foo; // @has issue_27862/struct.Foo.html //td 'id = |x| x'
diff --git a/tests/rustdoc/issue-28478.rs b/tests/rustdoc/issue-28478.rs
new file mode 100644
index 000000000..497276e68
--- /dev/null
+++ b/tests/rustdoc/issue-28478.rs
@@ -0,0 +1,31 @@
+#![feature(associated_type_defaults)]
+
+// @has issue_28478/trait.Bar.html
+pub trait Bar {
+ // @has - '//*[@id="associatedtype.Bar"]' 'type Bar = ()'
+ // @has - '//*[@href="#associatedtype.Bar"]' 'Bar'
+ type Bar = ();
+ // @has - '//*[@id="associatedconstant.Baz"]' 'const Baz: usize'
+ // @has - '//*[@href="#associatedconstant.Baz"]' 'Baz'
+ const Baz: usize = 7;
+ // @has - '//*[@id="tymethod.bar"]' 'fn bar'
+ fn bar();
+ // @has - '//*[@id="method.baz"]' 'fn baz'
+ fn baz() { }
+}
+
+// @has issue_28478/struct.Foo.html
+pub struct Foo;
+
+impl Foo {
+ // @has - '//*[@href="#method.foo"]' 'foo'
+ pub fn foo() {}
+}
+
+impl Bar for Foo {
+ // @has - '//*[@href="trait.Bar.html#associatedtype.Bar"]' 'Bar'
+ // @has - '//*[@href="trait.Bar.html#associatedconstant.Baz"]' 'Baz'
+ // @has - '//*[@href="trait.Bar.html#tymethod.bar"]' 'bar'
+ fn bar() {}
+ // @has - '//*[@href="trait.Bar.html#method.baz"]' 'baz'
+}
diff --git a/tests/rustdoc/issue-28927.rs b/tests/rustdoc/issue-28927.rs
new file mode 100644
index 000000000..38a520850
--- /dev/null
+++ b/tests/rustdoc/issue-28927.rs
@@ -0,0 +1,6 @@
+// aux-build:issue-28927-2.rs
+// aux-build:issue-28927-1.rs
+// ignore-cross-compile
+
+pub extern crate issue_28927_1 as inner1;
+pub use inner1 as foo;
diff --git a/tests/rustdoc/issue-29449.rs b/tests/rustdoc/issue-29449.rs
new file mode 100644
index 000000000..0d829cf6f
--- /dev/null
+++ b/tests/rustdoc/issue-29449.rs
@@ -0,0 +1,20 @@
+// @has issue_29449/struct.Foo.html
+pub struct Foo;
+
+impl Foo {
+ // @has - '//*[@id="examples"]//a' 'Examples'
+ // @has - '//*[@id="panics"]//a' 'Panics'
+ /// # Examples
+ /// # Panics
+ pub fn bar() {}
+
+ // @has - '//*[@id="examples-1"]//a' 'Examples'
+ /// # Examples
+ pub fn bar_1() {}
+
+ // @has - '//*[@id="examples-2"]//a' 'Examples'
+ // @has - '//*[@id="panics-1"]//a' 'Panics'
+ /// # Examples
+ /// # Panics
+ pub fn bar_2() {}
+}
diff --git a/tests/rustdoc/issue-29503.rs b/tests/rustdoc/issue-29503.rs
new file mode 100644
index 000000000..01ae44385
--- /dev/null
+++ b/tests/rustdoc/issue-29503.rs
@@ -0,0 +1,18 @@
+use std::fmt;
+
+// @has issue_29503/trait.MyTrait.html
+pub trait MyTrait {
+ fn my_string(&self) -> String;
+}
+
+// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header']" "impl<T> MyTrait for Twhere T: Debug"
+impl<T> MyTrait for T
+where
+ T: fmt::Debug,
+{
+ fn my_string(&self) -> String {
+ format!("{:?}", self)
+ }
+}
+
+pub fn main() {}
diff --git a/tests/rustdoc/issue-29584.rs b/tests/rustdoc/issue-29584.rs
new file mode 100644
index 000000000..4364a9649
--- /dev/null
+++ b/tests/rustdoc/issue-29584.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-29584.rs
+// ignore-cross-compile
+
+extern crate issue_29584;
+
+// @has issue_29584/struct.Foo.html
+// @!hasraw - 'impl Bar for'
+pub use issue_29584::Foo;
diff --git a/tests/rustdoc/issue-30109.rs b/tests/rustdoc/issue-30109.rs
new file mode 100644
index 000000000..e9447538a
--- /dev/null
+++ b/tests/rustdoc/issue-30109.rs
@@ -0,0 +1,14 @@
+// build-aux-docs
+// aux-build:issue-30109-1.rs
+// ignore-cross-compile
+
+pub mod quux {
+ extern crate issue_30109_1 as bar;
+ use self::bar::Bar;
+
+ pub trait Foo {}
+
+ // @has issue_30109/quux/trait.Foo.html \
+ // '//a/@href' '../issue_30109_1/struct.Bar.html'
+ impl Foo for Bar {}
+}
diff --git a/tests/rustdoc/issue-30252.rs b/tests/rustdoc/issue-30252.rs
new file mode 100644
index 000000000..c3777362a
--- /dev/null
+++ b/tests/rustdoc/issue-30252.rs
@@ -0,0 +1,6 @@
+// compile-flags:--test --cfg feature="bar"
+
+/// ```rust
+/// assert_eq!(cfg!(feature = "bar"), true);
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-30366.rs b/tests/rustdoc/issue-30366.rs
new file mode 100644
index 000000000..c6274a058
--- /dev/null
+++ b/tests/rustdoc/issue-30366.rs
@@ -0,0 +1,6 @@
+// @has issue_30366/index.html '//a/@href' 'http://www.rust-lang.org/'
+
+/// Describe it. [Link somewhere][1].
+///
+/// [1]: http://www.rust-lang.org/
+pub fn here_is_a_fn() { }
diff --git a/tests/rustdoc/issue-31808.rs b/tests/rustdoc/issue-31808.rs
new file mode 100644
index 000000000..e55c5bd4f
--- /dev/null
+++ b/tests/rustdoc/issue-31808.rs
@@ -0,0 +1,11 @@
+// Test that associated item impls on primitive types don't crash rustdoc
+
+pub trait Foo {
+ const BAR: usize;
+ type BAZ;
+}
+
+impl Foo for () {
+ const BAR: usize = 0;
+ type BAZ = usize;
+}
diff --git a/tests/rustdoc/issue-31899.rs b/tests/rustdoc/issue-31899.rs
new file mode 100644
index 000000000..3eee37446
--- /dev/null
+++ b/tests/rustdoc/issue-31899.rs
@@ -0,0 +1,59 @@
+// @has issue_31899/index.html
+// @hasraw - 'Make this line a bit longer.'
+// @!hasraw - 'rust rust-example-rendered'
+// @!hasraw - 'use ndarray::arr2'
+// @!hasraw - 'prohibited'
+
+/// A tuple or fixed size array that can be used to index an array.
+/// Make this line a bit longer.
+///
+/// ```
+/// use ndarray::arr2;
+///
+/// let mut a = arr2(&[[0, 1], [0, 0]]);
+/// a[[1, 1]] = 1;
+/// assert_eq!(a[[0, 1]], 1);
+/// assert_eq!(a[[1, 1]], 1);
+/// ```
+///
+/// **Note** the blanket implementation that's not visible in rustdoc:
+/// `impl<D> NdIndex for D where D: Dimension { ... }`
+pub fn bar() {}
+
+/// Some line
+///
+/// # prohibited
+pub fn foo() {}
+
+/// Some line
+///
+/// 1. prohibited
+/// 2. bar
+pub fn baz() {}
+
+/// Some line
+///
+/// - prohibited
+/// - bar
+pub fn qux() {}
+
+/// Some line
+///
+/// * prohibited
+/// * bar
+pub fn quz() {}
+
+/// Some line
+///
+/// > prohibited
+/// > bar
+pub fn qur() {}
+
+/// Some line
+///
+/// prohibited
+/// =====
+///
+/// Second
+/// ------
+pub fn qut() {}
diff --git a/tests/rustdoc/issue-32374.rs b/tests/rustdoc/issue-32374.rs
new file mode 100644
index 000000000..8d2c27cf3
--- /dev/null
+++ b/tests/rustdoc/issue-32374.rs
@@ -0,0 +1,31 @@
+#![feature(staged_api)]
+#![doc(issue_tracker_base_url = "https://issue_url/")]
+#![unstable(feature = "test", issue = "32374")]
+
+// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
+// 'Deprecated'
+// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
+// 'Experimental'
+// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
+
+// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' '👎'
+// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' \
+// 'Deprecated since 1.0.0: text'
+// @hasraw - '<code>test</code>&nbsp;<a href="https://issue_url/32374">#32374</a>'
+// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' '🔬'
+// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
+// 'This is a nightly-only experimental API. \(test\s#32374\)$'
+/// Docs
+#[deprecated(since = "1.0.0", note = "text")]
+#[unstable(feature = "test", issue = "32374")]
+pub struct T;
+
+// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' '👎'
+// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \
+// 'Deprecated since 1.0.0: deprecated'
+// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' '🔬'
+// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \
+// 'This is a nightly-only experimental API. (test #32374)'
+#[deprecated(since = "1.0.0", note = "deprecated")]
+#[unstable(feature = "test", issue = "32374", reason = "unstable")]
+pub struct U;
diff --git a/tests/rustdoc/issue-32395.rs b/tests/rustdoc/issue-32395.rs
new file mode 100644
index 000000000..5552300f9
--- /dev/null
+++ b/tests/rustdoc/issue-32395.rs
@@ -0,0 +1,15 @@
+// aux-build:variant-struct.rs
+// build-aux-docs
+// ignore-cross-compile
+
+// @has variant_struct/enum.Foo.html
+// @!hasraw - 'pub qux'
+// @!hasraw - 'pub(crate) qux'
+// @!hasraw - 'pub Bar'
+extern crate variant_struct;
+
+// @has issue_32395/enum.Foo.html
+// @!hasraw - 'pub qux'
+// @!hasraw - 'pub(crate) qux'
+// @!hasraw - 'pub Bar'
+pub use variant_struct::Foo;
diff --git a/tests/rustdoc/issue-32556.rs b/tests/rustdoc/issue-32556.rs
new file mode 100644
index 000000000..e1cf11509
--- /dev/null
+++ b/tests/rustdoc/issue-32556.rs
@@ -0,0 +1,5 @@
+/// Blah blah blah
+/// ```ignore (testing rustdoc's handling of ignore)
+/// bad_assert!();
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-32890.rs b/tests/rustdoc/issue-32890.rs
new file mode 100644
index 000000000..970954433
--- /dev/null
+++ b/tests/rustdoc/issue-32890.rs
@@ -0,0 +1,17 @@
+// @has issue_32890/struct.Foo.html
+pub struct Foo<T>(T);
+
+impl Foo<u8> {
+ // @has - '//a[@href="#method.pass"]' 'pass'
+ pub fn pass() {}
+}
+
+impl Foo<u16> {
+ // @has - '//a[@href="#method.pass-1"]' 'pass'
+ pub fn pass() {}
+}
+
+impl Foo<u32> {
+ // @has - '//a[@href="#method.pass-2"]' 'pass'
+ pub fn pass() {}
+}
diff --git a/tests/rustdoc/issue-33069.rs b/tests/rustdoc/issue-33069.rs
new file mode 100644
index 000000000..0213a53ca
--- /dev/null
+++ b/tests/rustdoc/issue-33069.rs
@@ -0,0 +1,10 @@
+pub trait Bar {}
+
+#[doc(hidden)]
+pub mod hidden {
+ pub struct Foo;
+}
+
+// @has issue_33069/trait.Bar.html
+// @!has - '//code' 'impl Bar for Foo'
+impl Bar for hidden::Foo {}
diff --git a/tests/rustdoc/issue-33178-1.rs b/tests/rustdoc/issue-33178-1.rs
new file mode 100644
index 000000000..4dc425346
--- /dev/null
+++ b/tests/rustdoc/issue-33178-1.rs
@@ -0,0 +1,10 @@
+// aux-build:empty.rs
+// aux-build:variant-struct.rs
+// ignore-cross-compile
+
+// @has issue_33178_1/index.html
+// @!has - //a/@title empty
+pub extern crate empty;
+
+// @!has - //a/@title variant_struct
+pub extern crate variant_struct as foo;
diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/issue-33178.rs
new file mode 100644
index 000000000..1f45fe723
--- /dev/null
+++ b/tests/rustdoc/issue-33178.rs
@@ -0,0 +1,13 @@
+// aux-build:empty.rs
+// aux-build:variant-struct.rs
+// build-aux-docs
+// ignore-cross-compile
+
+// @has issue_33178/index.html
+// @has - //a/@title empty
+// @has - //a/@href ../empty/index.html
+pub extern crate empty;
+
+// @has - //a/@title variant_struct
+// @has - //a/@href ../variant_struct/index.html
+pub extern crate variant_struct as foo;
diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/issue-33302.rs
new file mode 100644
index 000000000..b4c52e2f1
--- /dev/null
+++ b/tests/rustdoc/issue-33302.rs
@@ -0,0 +1,51 @@
+// Ensure constant and array length values are not taken from source
+// code, which wreaks havoc with macros.
+
+macro_rules! make {
+ ($n:expr) => {
+ pub struct S;
+
+ // @has issue_33302/constant.CST.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
+ pub const CST: i32 = ($n * $n);
+ // @has issue_33302/static.ST.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub static ST: i32'
+ pub static ST: i32 = ($n * $n);
+
+ pub trait T<X> {
+ fn ignore(_: &X) {}
+ const C: X;
+ // @has issue_33302/trait.T.html \
+ // '//div[@class="item-decl"]/pre[@class="rust"]' 'const D: i32'
+ // @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
+ const D: i32 = ($n * $n);
+ }
+
+ // @has issue_33302/struct.S.html \
+ // '//*[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
+ // @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]'
+ // @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
+ impl T<[i32; ($n * $n)]> for S {
+ const C: [i32; ($n * $n)] = [0; ($n * $n)];
+ }
+
+ // @has issue_33302/struct.S.html \
+ // '//*[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
+ // @has - '//*[@id="associatedconstant.C-1"]' 'const C: (i32,)'
+ // @has - '//*[@id="associatedconstant.D-1"]' 'const D: i32'
+ impl T<(i32,)> for S {
+ const C: (i32,) = ($n,);
+ }
+
+ // @has issue_33302/struct.S.html \
+ // '//*[@class="impl has-srclink"]' 'impl T<(i32, i32)> for S'
+ // @has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)'
+ // @has - '//*[@id="associatedconstant.D-2"]' 'const D: i32'
+ impl T<(i32, i32)> for S {
+ const C: (i32, i32) = ($n, $n);
+ const D: i32 = ($n / $n);
+ }
+ };
+}
+
+make!(4);
diff --git a/tests/rustdoc/issue-33592.rs b/tests/rustdoc/issue-33592.rs
new file mode 100644
index 000000000..7a128f0b8
--- /dev/null
+++ b/tests/rustdoc/issue-33592.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+pub trait Foo<T> {}
+
+pub struct Bar;
+
+pub struct Baz;
+
+// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl Foo<i32> for Bar'
+impl Foo<i32> for Bar {}
+
+// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl<T> Foo<T> for Baz'
+impl<T> Foo<T> for Baz {}
diff --git a/tests/rustdoc/issue-34025.rs b/tests/rustdoc/issue-34025.rs
new file mode 100644
index 000000000..9b9f21cb3
--- /dev/null
+++ b/tests/rustdoc/issue-34025.rs
@@ -0,0 +1,12 @@
+#![crate_name = "foo"]
+
+// @!has 'foo/sys/index.html'
+// @!has 'foo/sys/sidebar-items.js'
+#[doc(hidden)]
+pub mod sys {
+ extern "C" {
+ // @!has 'foo/sys/fn.foo.html'
+ #[doc(hidden)]
+ pub fn foo();
+ }
+}
diff --git a/tests/rustdoc/issue-34274.rs b/tests/rustdoc/issue-34274.rs
new file mode 100644
index 000000000..ce5be84a5
--- /dev/null
+++ b/tests/rustdoc/issue-34274.rs
@@ -0,0 +1,10 @@
+// aux-build:issue-34274.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate issue_34274;
+
+// @has foo/fn.extern_c_fn.html '//a/@href' '../src/issue_34274/issue-34274.rs.html#2'
+pub use issue_34274::extern_c_fn;
diff --git a/tests/rustdoc/issue-34423.rs b/tests/rustdoc/issue-34423.rs
new file mode 100644
index 000000000..b429bf8c9
--- /dev/null
+++ b/tests/rustdoc/issue-34423.rs
@@ -0,0 +1,10 @@
+pub struct Foo;
+
+pub trait Bar {
+ #[doc(hidden)]
+ fn bar() {}
+}
+
+impl Bar for Foo {
+ fn bar() {}
+}
diff --git a/tests/rustdoc/issue-34473.rs b/tests/rustdoc/issue-34473.rs
new file mode 100644
index 000000000..37da3dd19
--- /dev/null
+++ b/tests/rustdoc/issue-34473.rs
@@ -0,0 +1,11 @@
+#![crate_name = "foo"]
+
+mod second {
+ pub struct SomeTypeWithLongName;
+}
+
+// @has foo/index.html
+// @!hasraw - SomeTypeWithLongName
+// @has foo/struct.SomeType.html
+// @!has foo/struct.SomeTypeWithLongName.html
+pub use second::{SomeTypeWithLongName as SomeType};
diff --git a/tests/rustdoc/issue-34928.rs b/tests/rustdoc/issue-34928.rs
new file mode 100644
index 000000000..91b677574
--- /dev/null
+++ b/tests/rustdoc/issue-34928.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+pub trait Bar {}
+
+// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T)where T: Bar;'
+pub struct Foo<T>(pub T) where T: Bar;
diff --git a/tests/rustdoc/issue-35169-2.rs b/tests/rustdoc/issue-35169-2.rs
new file mode 100644
index 000000000..f08466baf
--- /dev/null
+++ b/tests/rustdoc/issue-35169-2.rs
@@ -0,0 +1,40 @@
+use std::ops::Deref;
+use std::ops::DerefMut;
+
+pub struct Foo;
+pub struct Bar;
+
+impl Foo {
+ pub fn by_ref(&self) {}
+ pub fn by_explicit_ref(self: &Foo) {}
+ pub fn by_mut_ref(&mut self) {}
+ pub fn by_explicit_mut_ref(self: &mut Foo) {}
+ pub fn by_explicit_box(self: Box<Foo>) {}
+ pub fn by_explicit_self_box(self: Box<Self>) {}
+ pub fn static_foo() {}
+}
+
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Foo { loop {} }
+}
+
+impl DerefMut for Bar {
+ fn deref_mut(&mut self) -> &mut Foo { loop {} }
+}
+
+// @has issue_35169_2/struct.Bar.html
+// @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)'
+// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)'
+// @has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)'
+// @has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)'
+// @has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
diff --git a/tests/rustdoc/issue-35169.rs b/tests/rustdoc/issue-35169.rs
new file mode 100644
index 000000000..70a2265c8
--- /dev/null
+++ b/tests/rustdoc/issue-35169.rs
@@ -0,0 +1,35 @@
+use std::ops::Deref;
+
+pub struct Foo;
+pub struct Bar;
+
+impl Foo {
+ pub fn by_ref(&self) {}
+ pub fn by_explicit_ref(self: &Foo) {}
+ pub fn by_mut_ref(&mut self) {}
+ pub fn by_explicit_mut_ref(self: &mut Foo) {}
+ pub fn by_explicit_box(self: Box<Foo>) {}
+ pub fn by_explicit_self_box(self: Box<Self>) {}
+ pub fn static_foo() {}
+}
+
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Foo { loop {} }
+}
+
+// @has issue_35169/struct.Bar.html
+// @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)'
+// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)'
+// @!has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)'
+// @!has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)'
+// @!has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @!has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
diff --git a/tests/rustdoc/issue-35488.rs b/tests/rustdoc/issue-35488.rs
new file mode 100644
index 000000000..c1bf9ceea
--- /dev/null
+++ b/tests/rustdoc/issue-35488.rs
@@ -0,0 +1,13 @@
+mod foo {
+ pub enum Foo {
+ Bar,
+ }
+ pub use self::Foo::*;
+}
+
+// @has 'issue_35488/index.html' '//code' 'pub use self::Foo::*;'
+// @has 'issue_35488/enum.Foo.html'
+pub use self::foo::*;
+
+// @has 'issue_35488/index.html' '//code' 'pub use std::option::Option::None;'
+pub use std::option::Option::None;
diff --git a/tests/rustdoc/issue-36031.rs b/tests/rustdoc/issue-36031.rs
new file mode 100644
index 000000000..af1b32fd2
--- /dev/null
+++ b/tests/rustdoc/issue-36031.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-36031.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate issue_36031;
+
+pub use issue_36031::Foo;
diff --git a/tests/rustdoc/issue-38129.rs b/tests/rustdoc/issue-38129.rs
new file mode 100644
index 000000000..156d50fa5
--- /dev/null
+++ b/tests/rustdoc/issue-38129.rs
@@ -0,0 +1,99 @@
+// compile-flags:--test
+
+// This file tests the source-partitioning behavior of rustdoc.
+// Each test contains some code that should be put into the generated
+// `fn main` and some attributes should be left outside (except the first
+// one, which has no attributes).
+// If the #![recursion_limit] attribute is incorrectly left inside,
+// then the tests will fail because the macro recurses 128 times.
+
+/// ```
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn simple() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn non_feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// #![feature(core_intrinsics)]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs_reverse() {}
diff --git a/tests/rustdoc/issue-38219.rs b/tests/rustdoc/issue-38219.rs
new file mode 100644
index 000000000..fa57c58c7
--- /dev/null
+++ b/tests/rustdoc/issue-38219.rs
@@ -0,0 +1,8 @@
+// compile-flags:--test
+// should-fail
+
+/// ```
+/// fail
+/// ```
+#[macro_export]
+macro_rules! foo { () => {} }
diff --git a/tests/rustdoc/issue-40936.rs b/tests/rustdoc/issue-40936.rs
new file mode 100644
index 000000000..4d2e4c17b
--- /dev/null
+++ b/tests/rustdoc/issue-40936.rs
@@ -0,0 +1,6 @@
+// aux-build:issue-40936.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+extern crate issue_40936;
diff --git a/tests/rustdoc/issue-41783.codeblock.html b/tests/rustdoc/issue-41783.codeblock.html
new file mode 100644
index 000000000..3bca4536c
--- /dev/null
+++ b/tests/rustdoc/issue-41783.codeblock.html
@@ -0,0 +1,5 @@
+<code># single
+## double
+### triple
+<span class="attr">#[outer]
+#![inner]</span></code>
diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/issue-41783.rs
new file mode 100644
index 000000000..7578d49da
--- /dev/null
+++ b/tests/rustdoc/issue-41783.rs
@@ -0,0 +1,19 @@
+// @has issue_41783/struct.Foo.html
+// @!hasraw - 'space'
+// @!hasraw - 'comment'
+// @hasraw - '<span class="attr">#[outer]'
+// @!hasraw - '<span class="attr">#[outer]</span>'
+// @hasraw - '#![inner]</span>'
+// @!hasraw - '<span class="attr">#![inner]</span>'
+// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code'
+
+/// ```no_run
+/// # # space
+/// # comment
+/// ## single
+/// ### double
+/// #### triple
+/// ##[outer]
+/// ##![inner]
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc/issue-42760.rs b/tests/rustdoc/issue-42760.rs
new file mode 100644
index 000000000..a5394c7d9
--- /dev/null
+++ b/tests/rustdoc/issue-42760.rs
@@ -0,0 +1,15 @@
+#![allow(rustdoc::invalid_rust_codeblocks)]
+
+// @has issue_42760/struct.NonGen.html
+// @has - '//h2' 'Example'
+
+/// Item docs.
+///
+#[doc="Hello there!"]
+///
+/// # Example
+///
+/// ```rust
+/// // some code here
+/// ```
+pub struct NonGen;
diff --git a/tests/rustdoc/issue-43153.rs b/tests/rustdoc/issue-43153.rs
new file mode 100644
index 000000000..0fe680f10
--- /dev/null
+++ b/tests/rustdoc/issue-43153.rs
@@ -0,0 +1,10 @@
+// Test that `include!` in a doc test searches relative to the directory in
+// which the test is declared.
+
+// compile-flags:--test
+
+/// ```rust
+/// include!("auxiliary/empty.rs");
+/// fn main() {}
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc/issue-43701.rs b/tests/rustdoc/issue-43701.rs
new file mode 100644
index 000000000..44335e961
--- /dev/null
+++ b/tests/rustdoc/issue-43701.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+pub use std::vec::Vec;
+
+// @!has implementors/core/clone/trait.Clone.js
diff --git a/tests/rustdoc/issue-43869.rs b/tests/rustdoc/issue-43869.rs
new file mode 100644
index 000000000..767d09d85
--- /dev/null
+++ b/tests/rustdoc/issue-43869.rs
@@ -0,0 +1,72 @@
+pub fn g() -> impl Iterator<Item=u8> {
+ Some(1u8).into_iter()
+}
+
+#[allow(unused_parens)]
+pub fn h() -> (impl Iterator<Item=u8>) {
+ Some(1u8).into_iter()
+}
+
+pub fn i() -> impl Iterator<Item=u8> + 'static {
+ Some(1u8).into_iter()
+}
+
+pub fn j() -> impl Iterator<Item=u8> + Clone {
+ Some(1u8).into_iter()
+}
+
+pub fn k() -> [impl Clone; 2] {
+ [123u32, 456u32]
+}
+
+pub fn l() -> (impl Clone, impl Default) {
+ (789u32, -123i32)
+}
+
+pub fn m() -> &'static impl Clone {
+ &1u8
+}
+
+pub fn n() -> *const impl Clone {
+ &1u8
+}
+
+pub fn o() -> &'static [impl Clone] {
+ b":)"
+}
+
+// issue #44731
+pub fn test_44731_0() -> Box<impl Iterator<Item=u8>> {
+ Box::new(g())
+}
+
+pub fn test_44731_1() -> Result<Box<impl Clone>, ()> {
+ Ok(Box::new(j()))
+}
+
+// NOTE these involve Fn sugar, where impl Trait is disallowed for now, see issue #45994
+//
+//pub fn test_44731_2() -> Box<Fn(impl Clone)> {
+// Box::new(|_: u32| {})
+//}
+//
+//pub fn test_44731_3() -> Box<Fn() -> impl Clone> {
+// Box::new(|| 0u32)
+//}
+
+pub fn test_44731_4() -> Box<Iterator<Item=impl Clone>> {
+ Box::new(g())
+}
+
+// @has issue_43869/fn.g.html
+// @has issue_43869/fn.h.html
+// @has issue_43869/fn.i.html
+// @has issue_43869/fn.j.html
+// @has issue_43869/fn.k.html
+// @has issue_43869/fn.l.html
+// @has issue_43869/fn.m.html
+// @has issue_43869/fn.n.html
+// @has issue_43869/fn.o.html
+// @has issue_43869/fn.test_44731_0.html
+// @has issue_43869/fn.test_44731_1.html
+// @has issue_43869/fn.test_44731_4.html
diff --git a/tests/rustdoc/issue-43893.rs b/tests/rustdoc/issue-43893.rs
new file mode 100644
index 000000000..95d551934
--- /dev/null
+++ b/tests/rustdoc/issue-43893.rs
@@ -0,0 +1,19 @@
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+pub trait SomeTrait {}
+pub struct SomeStruct;
+
+// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#9'
+impl SomeTrait for usize {}
+
+// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#12-14'
+impl SomeTrait for SomeStruct {
+ // deliberately multi-line impl
+}
+
+pub trait AnotherTrait {}
+
+// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#19'
+impl<T> AnotherTrait for T {}
diff --git a/tests/rustdoc/issue-45584.rs b/tests/rustdoc/issue-45584.rs
new file mode 100644
index 000000000..86479e6fb
--- /dev/null
+++ b/tests/rustdoc/issue-45584.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+
+pub trait Bar<T, U> {}
+
+// @has 'foo/struct.Foo1.html'
+pub struct Foo1;
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @has - '//*[@class="impl has-srclink"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
+impl Bar<Foo1, &'static Foo1> for Foo1 {}
+
+// @has 'foo/struct.Foo2.html'
+pub struct Foo2;
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @has - '//*[@class="impl has-srclink"]' "impl Bar<&'static Foo2, Foo2> for u8"
+impl Bar<&'static Foo2, Foo2> for u8 {}
diff --git a/tests/rustdoc/issue-46271.rs b/tests/rustdoc/issue-46271.rs
new file mode 100644
index 000000000..b38ef20c5
--- /dev/null
+++ b/tests/rustdoc/issue-46271.rs
@@ -0,0 +1,5 @@
+// hopefully this doesn't cause an ICE
+
+pub fn foo() {
+ extern crate std;
+}
diff --git a/tests/rustdoc/issue-46377.rs b/tests/rustdoc/issue-46377.rs
new file mode 100644
index 000000000..4489f038c
--- /dev/null
+++ b/tests/rustdoc/issue-46377.rs
@@ -0,0 +1,3 @@
+// @has 'issue_46377/index.html' '//*[@class="item-right docblock-short"]' 'Check out this struct!'
+/// # Check out this struct!
+pub struct SomeStruct;
diff --git a/tests/rustdoc/issue-46380-2.rs b/tests/rustdoc/issue-46380-2.rs
new file mode 100644
index 000000000..7004d18dc
--- /dev/null
+++ b/tests/rustdoc/issue-46380-2.rs
@@ -0,0 +1,9 @@
+pub trait PublicTrait<T> {}
+
+// @has issue_46380_2/struct.PublicStruct.html
+pub struct PublicStruct;
+
+// @!has - '//*[@class="impl"]' 'impl PublicTrait<PrivateStruct> for PublicStruct'
+impl PublicTrait<PrivateStruct> for PublicStruct {}
+
+struct PrivateStruct;
diff --git a/tests/rustdoc/issue-46727.rs b/tests/rustdoc/issue-46727.rs
new file mode 100644
index 000000000..8cfc4827a
--- /dev/null
+++ b/tests/rustdoc/issue-46727.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-46727.rs
+
+extern crate issue_46727;
+
+// @has issue_46727/trait.Foo.html
+// @has - '//h3[@class="code-header"]' 'impl<T> Foo for Bar<[T; 3]>'
+pub use issue_46727::{Foo, Bar};
diff --git a/tests/rustdoc/issue-46766.rs b/tests/rustdoc/issue-46766.rs
new file mode 100644
index 000000000..36ab73956
--- /dev/null
+++ b/tests/rustdoc/issue-46766.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+pub enum Enum{Variant}
+pub use self::Enum::Variant;
+
+// @!has foo/index.html '//a/@href' './Enum/index.html'
diff --git a/tests/rustdoc/issue-46767.rs b/tests/rustdoc/issue-46767.rs
new file mode 100644
index 000000000..ef6ed104b
--- /dev/null
+++ b/tests/rustdoc/issue-46767.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+mod private {
+ pub enum Enum{Variant}
+}
+pub use self::private::Enum::*;
+
+// @!has-dir foo/private
+// @!has foo/index.html '//a/@href' 'private/index.html'
diff --git a/tests/rustdoc/issue-46976.rs b/tests/rustdoc/issue-46976.rs
new file mode 100644
index 000000000..c59f8c72e
--- /dev/null
+++ b/tests/rustdoc/issue-46976.rs
@@ -0,0 +1 @@
+pub fn ice(f: impl Fn()) {}
diff --git a/tests/rustdoc/issue-47038.rs b/tests/rustdoc/issue-47038.rs
new file mode 100644
index 000000000..810ddca3e
--- /dev/null
+++ b/tests/rustdoc/issue-47038.rs
@@ -0,0 +1,10 @@
+#![feature(decl_macro)]
+
+#![crate_name = "foo"]
+
+use std::vec;
+
+// @has 'foo/index.html'
+// @!has - '//*[@id="macros"]' 'Macros'
+// @!has - '//a/@href' 'macro.vec.html'
+// @!has 'foo/macro.vec.html'
diff --git a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs b/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs
new file mode 100644
index 000000000..19994475d
--- /dev/null
+++ b/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs
@@ -0,0 +1,8 @@
+// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html
+
+/**
+* snow
+
+* ice
+*/
+pub fn whose_woods_these_are_i_think_i_know() {}
diff --git a/tests/rustdoc/issue-47639.rs b/tests/rustdoc/issue-47639.rs
new file mode 100644
index 000000000..4b3456b86
--- /dev/null
+++ b/tests/rustdoc/issue-47639.rs
@@ -0,0 +1,6 @@
+// This should not ICE
+pub fn test() {
+ macro_rules! foo {
+ () => ()
+ }
+}
diff --git a/tests/rustdoc/issue-48377.rs b/tests/rustdoc/issue-48377.rs
new file mode 100644
index 000000000..c32bcf380
--- /dev/null
+++ b/tests/rustdoc/issue-48377.rs
@@ -0,0 +1,13 @@
+// compile-flags:--test
+
+//! This is a doc comment
+//!
+//! ```rust
+//! fn main() {}
+//! ```
+//!
+//! With a trailing code fence
+//! ```
+
+/// Some foo function
+pub fn foo() {}
diff --git a/tests/rustdoc/issue-48414.rs b/tests/rustdoc/issue-48414.rs
new file mode 100644
index 000000000..b35743d88
--- /dev/null
+++ b/tests/rustdoc/issue-48414.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-48414.rs
+
+// ICE when resolving paths for a trait that linked to another trait, when both were in an external
+// crate
+
+#![crate_name = "base"]
+
+extern crate issue_48414;
+
+#[doc(inline)]
+pub use issue_48414::{SomeTrait, OtherTrait};
diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/issue-50159.rs
new file mode 100644
index 000000000..04bc4f304
--- /dev/null
+++ b/tests/rustdoc/issue-50159.rs
@@ -0,0 +1,20 @@
+pub trait Signal {
+ type Item;
+}
+
+pub trait Signal2 {
+ type Item2;
+}
+
+impl<B, C> Signal2 for B where B: Signal<Item = C> {
+ type Item2 = C;
+}
+
+// @has issue_50159/struct.Switch.html
+// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
+// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
+// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
+pub struct Switch<B: Signal> {
+ pub inner: <B as Signal2>::Item2,
+}
diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/issue-51236.rs
new file mode 100644
index 000000000..1c7aa9c7e
--- /dev/null
+++ b/tests/rustdoc/issue-51236.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomData;
+
+pub mod traits {
+ pub trait Owned<'a> {
+ type Reader;
+ }
+}
+
+// @has issue_51236/struct.Owned.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> Send for Owned<T>where <T as Owned<'static>>::Reader: Send"
+pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
+ marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
+}
diff --git a/tests/rustdoc/issue-52873.rs b/tests/rustdoc/issue-52873.rs
new file mode 100644
index 000000000..8000ce73b
--- /dev/null
+++ b/tests/rustdoc/issue-52873.rs
@@ -0,0 +1,171 @@
+// Regression test for #52873. We used to ICE due to unexpected
+// overflows when checking for "blanket impl inclusion".
+
+use std::marker::PhantomData;
+use std::cmp::Ordering;
+use std::ops::{Add, Mul};
+
+pub type True = B1;
+pub type False = B0;
+pub type U0 = UTerm;
+pub type U1 = UInt<UTerm, B1>;
+
+pub trait NonZero {}
+
+pub trait Bit {
+}
+
+pub trait Unsigned {
+}
+
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
+pub struct B0;
+
+impl B0 {
+ #[inline]
+ pub fn new() -> B0 {
+ B0
+ }
+}
+
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
+pub struct B1;
+
+impl B1 {
+ #[inline]
+ pub fn new() -> B1 {
+ B1
+ }
+}
+
+impl Bit for B0 {
+}
+
+impl Bit for B1 {
+}
+
+impl NonZero for B1 {}
+
+pub trait PrivatePow<Y, N> {
+ type Output;
+}
+pub type PrivatePowOut<A, Y, N> = <A as PrivatePow<Y, N>>::Output;
+
+pub type Add1<A> = <A as Add<::B1>>::Output;
+pub type Prod<A, B> = <A as Mul<B>>::Output;
+pub type Square<A> = <A as Mul>::Output;
+pub type Sum<A, B> = <A as Add<B>>::Output;
+
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
+pub struct UTerm;
+
+impl UTerm {
+ #[inline]
+ pub fn new() -> UTerm {
+ UTerm
+ }
+}
+
+impl Unsigned for UTerm {
+}
+
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
+pub struct UInt<U, B> {
+ _marker: PhantomData<(U, B)>,
+}
+
+impl<U: Unsigned, B: Bit> UInt<U, B> {
+ #[inline]
+ pub fn new() -> UInt<U, B> {
+ UInt {
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<U: Unsigned, B: Bit> Unsigned for UInt<U, B> {
+}
+
+impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}
+
+impl Add<B0> for UTerm {
+ type Output = UTerm;
+ fn add(self, _: B0) -> Self::Output {
+ UTerm
+ }
+}
+
+impl<U: Unsigned, B: Bit> Add<B0> for UInt<U, B> {
+ type Output = UInt<U, B>;
+ fn add(self, _: B0) -> Self::Output {
+ UInt::new()
+ }
+}
+
+impl<U: Unsigned> Add<U> for UTerm {
+ type Output = U;
+ fn add(self, _: U) -> Self::Output {
+ unimplemented!()
+ }
+}
+
+impl<U: Unsigned, B: Bit> Mul<B0> for UInt<U, B> {
+ type Output = UTerm;
+ fn mul(self, _: B0) -> Self::Output {
+ UTerm
+ }
+}
+
+impl<U: Unsigned, B: Bit> Mul<B1> for UInt<U, B> {
+ type Output = UInt<U, B>;
+ fn mul(self, _: B1) -> Self::Output {
+ UInt::new()
+ }
+}
+
+impl<U: Unsigned> Mul<U> for UTerm {
+ type Output = UTerm;
+ fn mul(self, _: U) -> Self::Output {
+ UTerm
+ }
+}
+
+impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B0>
+where
+ Ul: Mul<UInt<Ur, B>>,
+{
+ type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
+ fn mul(self, _: UInt<Ur, B>) -> Self::Output {
+ unimplemented!()
+ }
+}
+
+pub trait Pow<Exp> {
+ type Output;
+}
+
+impl<X: Unsigned, N: Unsigned> Pow<N> for X
+where
+ X: PrivatePow<U1, N>,
+{
+ type Output = PrivatePowOut<X, U1, N>;
+}
+
+impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U0> for X {
+ type Output = Y;
+}
+
+impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U1> for X
+where
+ X: Mul<Y>,
+{
+ type Output = Prod<X, Y>;
+}
+
+impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B0>> for X
+where
+ X: Mul,
+ Square<X>: PrivatePow<Y, UInt<U, B>>,
+{
+ type Output = PrivatePowOut<Square<X>, Y, UInt<U, B>>;
+}
diff --git a/tests/rustdoc/issue-53689.rs b/tests/rustdoc/issue-53689.rs
new file mode 100644
index 000000000..832140e06
--- /dev/null
+++ b/tests/rustdoc/issue-53689.rs
@@ -0,0 +1,16 @@
+// aux-build:issue-53689.rs
+
+#![crate_name = "foo"]
+
+extern crate issue_53689;
+
+// @has foo/trait.MyTrait.html
+// @!hasraw - 'MyStruct'
+// @count - '//*[h3="impl<T> MyTrait for T"]' 1
+pub trait MyTrait {}
+
+impl<T> MyTrait for T {}
+
+mod a {
+ pub use issue_53689::MyStruct;
+}
diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/issue-53812.rs
new file mode 100644
index 000000000..c68ffd521
--- /dev/null
+++ b/tests/rustdoc/issue-53812.rs
@@ -0,0 +1,20 @@
+pub trait MyIterator {}
+
+pub struct MyStruct<T>(T);
+
+macro_rules! array_impls {
+ ($($N:expr)+) => {
+ $(
+ impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> {
+ }
+ )+
+ }
+}
+
+// @has issue_53812/trait.MyIterator.html
+// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][1]' 'MyStruct<[T; 0]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][2]' 'MyStruct<[T; 1]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][3]' 'MyStruct<[T; 2]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][4]' 'MyStruct<[T; 3]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][5]' 'MyStruct<[T; 10]>'
+array_impls! { 10 3 2 1 0 }
diff --git a/tests/rustdoc/issue-54478-demo-allocator.rs b/tests/rustdoc/issue-54478-demo-allocator.rs
new file mode 100644
index 000000000..4811f363b
--- /dev/null
+++ b/tests/rustdoc/issue-54478-demo-allocator.rs
@@ -0,0 +1,42 @@
+// Issue #54478: regression test showing that we can demonstrate
+// `#[global_allocator]` in code blocks built by `rustdoc`.
+//
+// ## Background
+//
+// Changes in lang-item visibility injected failures that were only
+// exposed when compiling with `-C prefer-dynamic`. But `rustdoc` used
+// `-C prefer-dynamic` (and had done so for years, for reasons we did
+// not document at that time).
+//
+// Rather than try to revise the visbility semanics, we instead
+// decided to change `rustdoc` to behave more like the compiler's
+// default setting, by leaving off `-C prefer-dynamic`.
+
+// compile-flags:--test
+
+//! This is a doc comment
+//!
+//! ```rust
+//! use std::alloc::*;
+//!
+//! #[global_allocator]
+//! static ALLOC: A = A;
+//!
+//! static mut HIT: bool = false;
+//!
+//! struct A;
+//!
+//! unsafe impl GlobalAlloc for A {
+//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+//! HIT = true;
+//! System.alloc(layout)
+//! }
+//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+//! System.dealloc(ptr, layout);
+//! }
+//! }
+//!
+//! fn main() {
+//! assert!(unsafe { HIT });
+//! }
+//! ```
diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/issue-54705.rs
new file mode 100644
index 000000000..7b7290ab4
--- /dev/null
+++ b/tests/rustdoc/issue-54705.rs
@@ -0,0 +1,27 @@
+pub trait ScopeHandle<'scope> {}
+
+// @has issue_54705/struct.ScopeFutureContents.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync"
+//
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync"
+pub struct ScopeFutureContents<'scope, S>
+ where S: ScopeHandle<'scope>,
+{
+ dummy: &'scope S,
+ this: Box<ScopeFuture<'scope, S>>,
+}
+
+struct ScopeFuture<'scope, S>
+ where S: ScopeHandle<'scope>,
+{
+ contents: ScopeFutureContents<'scope, S>,
+}
+
+unsafe impl<'scope, S> Send for ScopeFuture<'scope, S>
+ where S: ScopeHandle<'scope>,
+{}
+unsafe impl<'scope, S> Sync for ScopeFuture<'scope, S>
+ where S: ScopeHandle<'scope>,
+{}
diff --git a/tests/rustdoc/issue-55001.rs b/tests/rustdoc/issue-55001.rs
new file mode 100644
index 000000000..f6c7f9a3d
--- /dev/null
+++ b/tests/rustdoc/issue-55001.rs
@@ -0,0 +1,31 @@
+// Regression test for issue #55001. Previously, we would incorrectly
+// cache certain trait selection results when checking for blanket impls,
+// resulting in an ICE when we tried to confirm the cached ParamCandidate
+// against an obligation.
+
+pub struct DefaultAllocator;
+pub struct Standard;
+pub struct Inner;
+
+pub trait Rand {}
+
+pub trait Distribution<T> {}
+pub trait Allocator<N> {}
+
+impl<T> Rand for T where Standard: Distribution<T> {}
+
+impl<A> Distribution<Point<A>> for Standard
+where
+DefaultAllocator: Allocator<A>,
+Standard: Distribution<A> {}
+
+impl Distribution<Inner> for Standard {}
+
+
+pub struct Point<N>
+where DefaultAllocator: Allocator<N>
+{
+ field: N
+}
+
+fn main() {}
diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/issue-55321.rs
new file mode 100644
index 000000000..22a18ef90
--- /dev/null
+++ b/tests/rustdoc/issue-55321.rs
@@ -0,0 +1,18 @@
+#![feature(negative_impls)]
+
+// @has issue_55321/struct.A.html
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl !Send for A"
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl !Sync for A"
+pub struct A();
+
+impl !Send for A {}
+impl !Sync for A {}
+
+// @has issue_55321/struct.B.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Send for B<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Sync for B<T>"
+pub struct B<T: ?Sized>(A, Box<T>);
diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/issue-55364.rs
new file mode 100644
index 000000000..14a6f5041
--- /dev/null
+++ b/tests/rustdoc/issue-55364.rs
@@ -0,0 +1,86 @@
+// First a module with inner documentation
+
+// @has issue_55364/subone/index.html
+// These foo/bar links in the module's documentation should refer inside `subone`
+// @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo'
+// @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar'
+pub mod subone {
+ //! See either [foo] or [bar].
+
+ // This should refer to subone's `bar`
+ // @has issue_55364/subone/fn.foo.html
+ // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar'
+ /// See [bar]
+ pub fn foo() {}
+ // This should refer to subone's `foo`
+ // @has issue_55364/subone/fn.bar.html
+ // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo'
+ /// See [foo]
+ pub fn bar() {}
+}
+
+// A module with outer documentation
+
+// @has issue_55364/subtwo/index.html
+// These foo/bar links in the module's documentation should not reference inside `subtwo`
+// @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo'
+// @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar'
+// Instead it should be referencing the top level functions
+// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo'
+// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar'
+// Though there should be such links later
+// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.foo.html"]' 'foo'
+// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.bar.html"]' 'bar'
+/// See either [foo] or [bar].
+pub mod subtwo {
+
+ // Despite the module's docs referring to the top level foo/bar,
+ // this should refer to subtwo's `bar`
+ // @has issue_55364/subtwo/fn.foo.html
+ // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar'
+ /// See [bar]
+ pub fn foo() {}
+ // Despite the module's docs referring to the top level foo/bar,
+ // this should refer to subtwo's `foo`
+ // @has issue_55364/subtwo/fn.bar.html
+ // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo'
+ /// See [foo]
+ pub fn bar() {}
+}
+
+// These are the function referred to by the module above with outer docs
+
+/// See [bar]
+pub fn foo() {}
+/// See [foo]
+pub fn bar() {}
+
+// This module refers to the outer foo/bar by means of `super::`
+
+// @has issue_55364/subthree/index.html
+// This module should also refer to the top level foo/bar
+// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo'
+// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar'
+pub mod subthree {
+ //! See either [foo][super::foo] or [bar][super::bar]
+}
+
+// Next we go *deeper* - In order to ensure it's not just "this or parent"
+// we test `crate::` and a `super::super::...` chain
+// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html
+// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
+// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
+pub mod subfour {
+ pub mod subfive {
+ pub mod subsix {
+ pub mod subseven {
+ pub mod subeight {
+ /// See [other foo][crate::subone::foo]
+ pub fn foo() {}
+ /// See [other bar][super::super::super::super::super::subtwo::bar]
+ pub fn bar() {}
+ }
+ }
+ }
+ }
+}
diff --git a/tests/rustdoc/issue-56701.rs b/tests/rustdoc/issue-56701.rs
new file mode 100644
index 000000000..ba00743fc
--- /dev/null
+++ b/tests/rustdoc/issue-56701.rs
@@ -0,0 +1,33 @@
+// This shouldn't cause a stack overflow when rustdoc is run
+
+use std::ops::Deref;
+use std::ops::DerefMut;
+
+pub trait SimpleTrait {
+ type SimpleT;
+}
+
+impl<Inner: SimpleTrait, Outer: Deref<Target = Inner>> SimpleTrait for Outer {
+ type SimpleT = Inner::SimpleT;
+}
+
+pub trait AnotherTrait {
+ type AnotherT;
+}
+
+impl<T, Simple: SimpleTrait<SimpleT = Vec<T>>> AnotherTrait for Simple {
+ type AnotherT = T;
+}
+
+pub struct Unrelated<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>>(UnrelatedT);
+
+impl<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>> Deref for Unrelated<Inner, UnrelatedT> {
+ type Target = Vec<Inner>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+
+pub fn main() { }
diff --git a/tests/rustdoc/issue-56822.rs b/tests/rustdoc/issue-56822.rs
new file mode 100644
index 000000000..b4eef344b
--- /dev/null
+++ b/tests/rustdoc/issue-56822.rs
@@ -0,0 +1,24 @@
+struct Wrapper<T>(T);
+
+trait MyTrait {
+ type Output;
+}
+
+impl<'a, I, T: 'a> MyTrait for Wrapper<I>
+ where I: MyTrait<Output=&'a T>
+{
+ type Output = T;
+}
+
+struct Inner<'a, T>(&'a T);
+
+impl<'a, T> MyTrait for Inner<'a, T> {
+ type Output = &'a T;
+}
+
+// @has issue_56822/struct.Parser.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'a> Send for Parser<'a>"
+pub struct Parser<'a> {
+ field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
+}
diff --git a/tests/rustdoc/issue-57180.rs b/tests/rustdoc/issue-57180.rs
new file mode 100644
index 000000000..14bd2b0fe
--- /dev/null
+++ b/tests/rustdoc/issue-57180.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-57180.rs
+
+extern crate issue_57180;
+use issue_57180::Trait;
+
+fn main() {
+}
diff --git a/tests/rustdoc/issue-60482.rs b/tests/rustdoc/issue-60482.rs
new file mode 100644
index 000000000..0fd1daa74
--- /dev/null
+++ b/tests/rustdoc/issue-60482.rs
@@ -0,0 +1,9 @@
+// This code caused a panic in `pulldown-cmark` 0.4.1.
+
+pub const BASIC_UNICODE: bool = true;
+
+
+/// # `BASIC_UNICODE`: `A` `|`
+/// ```text
+/// ```
+pub const BASIC_FONTS: bool = true;
diff --git a/tests/rustdoc/issue-60726.rs b/tests/rustdoc/issue-60726.rs
new file mode 100644
index 000000000..fbb0f82ae
--- /dev/null
+++ b/tests/rustdoc/issue-60726.rs
@@ -0,0 +1,35 @@
+use std::marker::PhantomData;
+
+pub struct True;
+pub struct False;
+
+pub trait InterfaceType{
+ type Send;
+}
+
+
+pub struct FooInterface<T>(PhantomData<fn()->T>);
+
+impl<T> InterfaceType for FooInterface<T> {
+ type Send=False;
+}
+
+
+pub struct DynTrait<I>{
+ _interface:PhantomData<fn()->I>,
+ _unsync_unsend:PhantomData<::std::rc::Rc<()>>,
+}
+
+unsafe impl<I> Send for DynTrait<I>
+where
+ I:InterfaceType<Send=True>
+{}
+
+// @has issue_60726/struct.IntoIter.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Send for IntoIter<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Sync for IntoIter<T>"
+pub struct IntoIter<T>{
+ hello:DynTrait<FooInterface<T>>,
+}
diff --git a/tests/rustdoc/issue-61592.rs b/tests/rustdoc/issue-61592.rs
new file mode 100644
index 000000000..4b6c37b94
--- /dev/null
+++ b/tests/rustdoc/issue-61592.rs
@@ -0,0 +1,15 @@
+// aux-build:issue-61592.rs
+
+extern crate foo;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooTrait as _;'
+// @!has - '//a[@href="trait._.html"]' ''
+pub use foo::FooTrait as _;
+
+// @has issue_61592/index.html
+// @has - '//a[@href="#reexports"]' 'Re-exports'
+// @has - '//code' 'pub use foo::FooStruct as _;'
+// @!has - '//a[@href="struct._.html"]' ''
+pub use foo::FooStruct as _;
diff --git a/tests/rustdoc/issue-67851-both.rs b/tests/rustdoc/issue-67851-both.rs
new file mode 100644
index 000000000..d69b94317
--- /dev/null
+++ b/tests/rustdoc/issue-67851-both.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-private-items --document-hidden-items
+
+// @has issue_67851_both/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_both/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/issue-67851-hidden.rs b/tests/rustdoc/issue-67851-hidden.rs
new file mode 100644
index 000000000..8a3cafe4c
--- /dev/null
+++ b/tests/rustdoc/issue-67851-hidden.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-hidden-items
+
+// @has issue_67851_hidden/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_hidden/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/issue-67851-neither.rs b/tests/rustdoc/issue-67851-neither.rs
new file mode 100644
index 000000000..4e3cd8328
--- /dev/null
+++ b/tests/rustdoc/issue-67851-neither.rs
@@ -0,0 +1,6 @@
+// @!has issue_67851_neither/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_neither/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/issue-67851-private.rs b/tests/rustdoc/issue-67851-private.rs
new file mode 100644
index 000000000..8addc7f3e
--- /dev/null
+++ b/tests/rustdoc/issue-67851-private.rs
@@ -0,0 +1,8 @@
+// compile-flags: --document-private-items
+
+// @!has issue_67851_private/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_private/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/issue-72340.rs b/tests/rustdoc/issue-72340.rs
new file mode 100644
index 000000000..64044cfe9
--- /dev/null
+++ b/tests/rustdoc/issue-72340.rs
@@ -0,0 +1,19 @@
+#![crate_name = "foo"]
+
+pub struct Body;
+
+impl Body {
+ pub fn empty() -> Self {
+ Body
+ }
+
+}
+
+impl Default for Body {
+ // @has foo/struct.Body.html '//a/@href' 'struct.Body.html#method.empty'
+
+ /// Returns [`Body::empty()`](Body::empty).
+ fn default() -> Body {
+ Body::empty()
+ }
+}
diff --git a/tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs b/tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
new file mode 100644
index 000000000..2700f2370
--- /dev/null
+++ b/tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
@@ -0,0 +1,14 @@
+// Regression test for ICE #73061
+
+// aux-build:issue-73061.rs
+
+extern crate issue_73061;
+
+pub struct Z;
+
+impl issue_73061::Foo for Z {
+ type X = <issue_73061::F as issue_73061::Foo>::X;
+ fn x(&self) -> Self::X {
+ issue_73061::F.x()
+ }
+}
diff --git a/tests/rustdoc/issue-74083.rs b/tests/rustdoc/issue-74083.rs
new file mode 100644
index 000000000..c7f5d7eaa
--- /dev/null
+++ b/tests/rustdoc/issue-74083.rs
@@ -0,0 +1,21 @@
+use std::ops::Deref;
+
+pub struct Foo;
+
+impl Foo {
+ pub fn foo(&mut self) {}
+}
+
+// @has issue_74083/struct.Bar.html
+// @!has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
+pub struct Bar {
+ foo: Foo,
+}
+
+impl Deref for Bar {
+ type Target = Foo;
+
+ fn deref(&self) -> &Foo {
+ &self.foo
+ }
+}
diff --git a/tests/rustdoc/issue-75588.rs b/tests/rustdoc/issue-75588.rs
new file mode 100644
index 000000000..3b11059a7
--- /dev/null
+++ b/tests/rustdoc/issue-75588.rs
@@ -0,0 +1,17 @@
+// aux-build:realcore.rs
+// aux-build:real_gimli.rs
+
+// Ensure unstably exported traits have their Implementors sections.
+
+#![crate_name = "foo"]
+#![feature(extremely_unstable_foo)]
+
+extern crate realcore;
+extern crate real_gimli;
+
+// issue #74672
+// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header"]' 'impl Deref for EndianSlice'
+pub use realcore::Deref;
+
+// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header"]' 'impl Join for Foo'
+pub use realcore::Join;
diff --git a/tests/rustdoc/issue-76501.rs b/tests/rustdoc/issue-76501.rs
new file mode 100644
index 000000000..a90e0fea0
--- /dev/null
+++ b/tests/rustdoc/issue-76501.rs
@@ -0,0 +1,17 @@
+// @has 'issue_76501/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
+/// A useless function that always returns 1.
+pub const fn bloop() -> i32 {
+ 1
+}
+
+/// A struct.
+pub struct Struct {}
+
+impl Struct {
+ // @has 'issue_76501/struct.Struct.html' '//*[@class="method has-srclink"]' \
+ // 'pub const fn blurp() -> i32'
+ /// A useless function that always returns 1.
+ pub const fn blurp() -> i32 {
+ 1
+ }
+}
diff --git a/tests/rustdoc/issue-78673.rs b/tests/rustdoc/issue-78673.rs
new file mode 100644
index 000000000..2e4bec254
--- /dev/null
+++ b/tests/rustdoc/issue-78673.rs
@@ -0,0 +1,24 @@
+#![crate_name = "issue_78673"]
+
+pub trait Something {}
+
+pub trait AnAmazingTrait {}
+
+impl<T: Something> AnAmazingTrait for T {}
+
+// @has 'issue_78673/struct.MyStruct.html'
+// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for MyStruct'
+// @!has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
+pub struct MyStruct;
+
+impl AnAmazingTrait for MyStruct {}
+
+// generic structs may have _both_ specific and blanket impls that apply
+
+// @has 'issue_78673/struct.AnotherStruct.html'
+// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for AnotherStruct<()>'
+// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
+pub struct AnotherStruct<T>(T);
+
+impl<T: Something> Something for AnotherStruct<T> {}
+impl AnAmazingTrait for AnotherStruct<()> {}
diff --git a/tests/rustdoc/issue-78701.rs b/tests/rustdoc/issue-78701.rs
new file mode 100644
index 000000000..e3e46468f
--- /dev/null
+++ b/tests/rustdoc/issue-78701.rs
@@ -0,0 +1,20 @@
+#![crate_name = "foo"]
+
+// This test ensures that if a blanket impl has the same ID as another impl, it'll
+// link to the blanket impl and not the other impl. Basically, we're checking if
+// the ID is correctly derived.
+
+// @has 'foo/struct.AnotherStruct.html'
+// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3C()%3E"]' 1
+// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3CT%3E"]' 1
+
+pub trait Something {}
+
+pub trait AnAmazingTrait {}
+
+impl<T: Something> AnAmazingTrait for T {}
+
+pub struct AnotherStruct<T>(T);
+
+impl<T: Something> Something for AnotherStruct<T> {}
+impl AnAmazingTrait for AnotherStruct<()> {}
diff --git a/tests/rustdoc/issue-79201.rs b/tests/rustdoc/issue-79201.rs
new file mode 100644
index 000000000..f95d79cd4
--- /dev/null
+++ b/tests/rustdoc/issue-79201.rs
@@ -0,0 +1,41 @@
+#![feature(doc_cfg)]
+
+// @has 'issue_79201/trait.Foo.html'
+// @count - '//*[@class="stab portability"]' 6
+// @matches - '//*[@class="stab portability"]' 'crate feature foo-root'
+// @matches - '//*[@class="stab portability"]' 'crate feature foo-public-mod'
+// @matches - '//*[@class="stab portability"]' 'crate feature foo-private-mod'
+// @matches - '//*[@class="stab portability"]' 'crate feature foo-fn'
+// @matches - '//*[@class="stab portability"]' 'crate feature foo-method'
+
+pub trait Foo {}
+
+#[doc(cfg(feature = "foo-root"))]
+impl crate::Foo for usize {}
+
+#[doc(cfg(feature = "foo-public-mod"))]
+pub mod public {
+ impl crate::Foo for u8 {}
+}
+
+#[doc(cfg(feature = "foo-private-mod"))]
+mod private {
+ impl crate::Foo for u16 {}
+}
+
+#[doc(cfg(feature = "foo-const"))]
+const _: () = {
+ impl crate::Foo for u32 {}
+};
+
+#[doc(cfg(feature = "foo-fn"))]
+fn __() {
+ impl crate::Foo for u64 {}
+}
+
+#[doc(cfg(feature = "foo-method"))]
+impl dyn Foo {
+ fn __() {
+ impl crate::Foo for u128 {}
+ }
+}
diff --git a/tests/rustdoc/issue-80233-normalize-auto-trait.rs b/tests/rustdoc/issue-80233-normalize-auto-trait.rs
new file mode 100644
index 000000000..62fbc2444
--- /dev/null
+++ b/tests/rustdoc/issue-80233-normalize-auto-trait.rs
@@ -0,0 +1,37 @@
+// Regression test for issue #80233
+// Tests that we don't ICE when processing auto traits
+
+#![crate_type = "lib"]
+pub trait Trait1 {}
+
+pub trait Trait2 {
+ type Type2;
+}
+
+pub trait Trait3 {
+ type Type3;
+}
+
+impl Trait2 for Struct1 {
+ type Type2 = Struct1;
+}
+
+impl<I: Trait2> Trait2 for Vec<I> {
+ type Type2 = Vec<I::Type2>;
+}
+
+impl<T: Trait1> Trait3 for T {
+ type Type3 = Struct1;
+}
+
+impl<T: Trait3> Trait3 for Vec<T> {
+ type Type3 = Vec<T::Type3>;
+}
+
+pub struct Struct1 {}
+
+// @has issue_80233_normalize_auto_trait/struct.Question.html
+// @has - '//h3[@class="code-header"]' 'impl<T> Send for Question<T>'
+pub struct Question<T: Trait1> {
+ pub ins: <<Vec<T> as Trait3>::Type3 as Trait2>::Type2,
+}
diff --git a/tests/rustdoc/issue-82465-asref-for-and-of-local.rs b/tests/rustdoc/issue-82465-asref-for-and-of-local.rs
new file mode 100644
index 000000000..adf4d111a
--- /dev/null
+++ b/tests/rustdoc/issue-82465-asref-for-and-of-local.rs
@@ -0,0 +1,16 @@
+use std::convert::AsRef;
+pub struct Local;
+
+// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header"]' 'impl AsRef<str> for Local'
+impl AsRef<str> for Local {
+ fn as_ref(&self) -> &str {
+ todo!()
+ }
+}
+
+// @has - '//h3[@class="code-header"]' 'impl AsRef<Local> for str'
+impl AsRef<Local> for str {
+ fn as_ref(&self) -> &Local {
+ todo!()
+ }
+}
diff --git a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
new file mode 100644
index 000000000..d3a7a870b
--- /dev/null
+++ b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+pub mod sub {
+ pub struct Item;
+
+ pub mod prelude {
+ pub use super::Item;
+ }
+}
+
+#[doc(inline)]
+pub use sub::*;
+
+// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/prelude/index.html '//div[@class="item-row"]' 0
+pub mod prelude {}
diff --git a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
new file mode 100644
index 000000000..b83692509
--- /dev/null
+++ b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+pub mod sub {
+ pub struct Item;
+
+ pub mod prelude {
+ pub use super::Item;
+ }
+}
+
+// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/prelude/index.html '//div[@class="item-row"]' 0
+pub mod prelude {}
+
+#[doc(inline)]
+pub use sub::*;
diff --git a/tests/rustdoc/issue-85454.rs b/tests/rustdoc/issue-85454.rs
new file mode 100644
index 000000000..74fc22b31
--- /dev/null
+++ b/tests/rustdoc/issue-85454.rs
@@ -0,0 +1,29 @@
+// aux-build:issue-85454.rs
+// build-aux-docs
+#![crate_name = "foo"]
+
+extern crate issue_85454;
+
+// @has foo/trait.FromResidual.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+pub trait FromResidual<R = <Self as Try>::Residual> {
+ fn from_residual(residual: R) -> Self;
+}
+
+pub trait Try: FromResidual {
+ type Output;
+ type Residual;
+ fn from_output(output: Self::Output) -> Self;
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+}
+
+pub enum ControlFlow<B, C = ()> {
+ Continue(C),
+ Break(B),
+}
+
+pub mod reexport {
+ // @has foo/reexport/trait.FromResidual.html
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+ pub use issue_85454::*;
+}
diff --git a/tests/rustdoc/issue-86620.rs b/tests/rustdoc/issue-86620.rs
new file mode 100644
index 000000000..ef15946ec
--- /dev/null
+++ b/tests/rustdoc/issue-86620.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-86620-1.rs
+
+extern crate issue_86620_1;
+
+use issue_86620_1::*;
+
+// @!has issue_86620/struct.S.html '//*[@id="method.vzip"]//a[@class="fnname"]/@href' #tymethod.vzip
+// @has issue_86620/struct.S.html '//*[@id="method.vzip"]//a[@class="anchor"]/@href' #method.vzip
+pub struct S;
diff --git a/tests/rustdoc/issue-88600.rs b/tests/rustdoc/issue-88600.rs
new file mode 100644
index 000000000..db0d102b7
--- /dev/null
+++ b/tests/rustdoc/issue-88600.rs
@@ -0,0 +1,35 @@
+// This test ensure that #[doc(hidden)] is applied correctly in enum variant fields.
+
+// Denotes a field which should be hidden.
+pub struct H;
+
+// Denotes a field which should not be hidden (shown).
+pub struct S;
+
+// @has issue_88600/enum.FooEnum.html
+pub enum FooEnum {
+ // @has - '//*[@id="variant.HiddenTupleItem"]//h3' 'HiddenTupleItem(_)'
+ // @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0
+ HiddenTupleItem(#[doc(hidden)] H),
+ // @has - '//*[@id="variant.MultipleHidden"]//h3' 'MultipleHidden(_, _)'
+ // @count - '//*[@id="variant.MultipleHidden.field.0"]' 0
+ // @count - '//*[@id="variant.MultipleHidden.field.1"]' 0
+ MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H),
+ // @has - '//*[@id="variant.MixedHiddenFirst"]//h3' 'MixedHiddenFirst(_, S)'
+ // @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0
+ // @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S'
+ MixedHiddenFirst(#[doc(hidden)] H, /** dox */ S),
+ // @has - '//*[@id="variant.MixedHiddenLast"]//h3' 'MixedHiddenLast(S, _)'
+ // @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S'
+ // @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0
+ MixedHiddenLast(/** dox */ S, #[doc(hidden)] H),
+ // @has - '//*[@id="variant.HiddenStruct"]//h3' 'HiddenStruct'
+ // @count - '//*[@id="variant.HiddenStruct.field.h"]' 0
+ // @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S'
+ HiddenStruct {
+ #[doc(hidden)]
+ h: H,
+ /// dox
+ s: S,
+ },
+}
diff --git a/tests/rustdoc/issue-89309-heading-levels.rs b/tests/rustdoc/issue-89309-heading-levels.rs
new file mode 100644
index 000000000..bb706c28f
--- /dev/null
+++ b/tests/rustdoc/issue-89309-heading-levels.rs
@@ -0,0 +1,29 @@
+#![crate_name = "foo"]
+
+// @has foo/trait.Read.html
+// @has - '//h2' 'Trait examples'
+/// # Trait examples
+pub trait Read {
+ // @has - '//h5' 'Function examples'
+ /// # Function examples
+ fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()>;
+}
+
+pub struct Foo;
+
+// @has foo/struct.Foo.html
+impl Foo {
+ // @has - '//h5' 'Implementation header'
+ /// # Implementation header
+ pub fn bar(&self) -> usize {
+ 1
+ }
+}
+
+impl Read for Foo {
+ // @has - '//h5' 'Trait implementation header'
+ /// # Trait implementation header
+ fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
+ Ok(1)
+ }
+}
diff --git a/tests/rustdoc/issue-89852.rs b/tests/rustdoc/issue-89852.rs
new file mode 100644
index 000000000..4f2da5e07
--- /dev/null
+++ b/tests/rustdoc/issue-89852.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @matchesraw 'issue_89852/sidebar-items.js' '"repro"'
+// @!matchesraw 'issue_89852/sidebar-items.js' '"repro".*"repro"'
+
+#[macro_export]
+macro_rules! repro {
+ () => {};
+}
+
+pub use crate::repro as repro2;
diff --git a/tests/rustdoc/issue-95633.rs b/tests/rustdoc/issue-95633.rs
new file mode 100644
index 000000000..a71d0a037
--- /dev/null
+++ b/tests/rustdoc/issue-95633.rs
@@ -0,0 +1,7 @@
+// compile-flags: --document-private-items
+
+// This ensures that no ICE is triggered when rustdoc is run on this code.
+
+mod stdlib {
+ pub (crate) use std::i8;
+}
diff --git a/tests/rustdoc/issue-95873.rs b/tests/rustdoc/issue-95873.rs
new file mode 100644
index 000000000..ff33fb63a
--- /dev/null
+++ b/tests/rustdoc/issue-95873.rs
@@ -0,0 +1,2 @@
+// @has issue_95873/index.html "//*[@class='item-left import-item']" "pub use ::std as x;"
+pub use ::std as x;
diff --git a/tests/rustdoc/issue-96381.rs b/tests/rustdoc/issue-96381.rs
new file mode 100644
index 000000000..f0f123f85
--- /dev/null
+++ b/tests/rustdoc/issue-96381.rs
@@ -0,0 +1,16 @@
+// should-fail
+
+#![allow(unused)]
+
+trait Foo<T>: Sized {
+ fn bar(i: i32, t: T, s: &Self) -> (T, i32);
+}
+
+impl Foo<usize> for () {
+ fn bar(i: _, t: _, s: _) -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+ (1, 2)
+ }
+}
+
+fn main() {}
diff --git a/tests/rustdoc/issue-98697.rs b/tests/rustdoc/issue-98697.rs
new file mode 100644
index 000000000..884b63ac9
--- /dev/null
+++ b/tests/rustdoc/issue-98697.rs
@@ -0,0 +1,17 @@
+// aux-build:issue-98697-reexport-with-anonymous-lifetime.rs
+// ignore-cross-compile
+
+// When reexporting a function with a HRTB with anonymous lifetimes,
+// make sure the anonymous lifetimes are not rendered.
+//
+// https://github.com/rust-lang/rust/issues/98697
+
+extern crate issue_98697_reexport_with_anonymous_lifetime;
+
+// @has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'fn repro<F>()where F: Fn(&str)'
+// @!has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'for<'
+pub use issue_98697_reexport_with_anonymous_lifetime::repro;
+
+// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
+// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl<'
+pub use issue_98697_reexport_with_anonymous_lifetime::Extra;
diff --git a/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs
new file mode 100644
index 000000000..e74881d38
--- /dev/null
+++ b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs
@@ -0,0 +1,19 @@
+// aux-build:issue-99221-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate issue_99221_aux;
+
+pub use issue_99221_aux::*;
+
+// @count foo/index.html '//a[@class="macro"]' 1
+
+mod inner {
+ #[macro_export]
+ macro_rules! print {
+ () => ()
+ }
+}
diff --git a/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs
new file mode 100644
index 000000000..46d59654b
--- /dev/null
+++ b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs
@@ -0,0 +1,17 @@
+// aux-build:issue-99221-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate issue_99221_aux;
+
+pub use issue_99221_aux::*;
+
+// @count foo/index.html '//a[@class="macro"]' 1
+
+#[macro_export]
+macro_rules! print {
+ () => ()
+}
diff --git a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs
new file mode 100644
index 000000000..41e64726a
--- /dev/null
+++ b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-99221-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate issue_99221_aux;
+
+pub use issue_99221_aux::*;
+
+// @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1
+
+pub struct Print;
diff --git a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs
new file mode 100644
index 000000000..3208fea05
--- /dev/null
+++ b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs
@@ -0,0 +1,16 @@
+// aux-build:issue-99734-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate issue_99734_aux;
+
+pub use issue_99734_aux::*;
+
+// @count foo/index.html '//a[@class="fn"][@title="foo::main fn"]' 1
+
+extern "C" {
+ pub fn main() -> std::ffi::c_int;
+}
diff --git a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs
new file mode 100644
index 000000000..b2f9b8b46
--- /dev/null
+++ b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-99734-aux.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate issue_99734_aux;
+
+pub use issue_99734_aux::*;
+
+// @count foo/index.html '//a[@class="mod"][@title="foo::task mod"]' 1
+
+pub mod task {}
diff --git a/tests/rustdoc/keyword.rs b/tests/rustdoc/keyword.rs
new file mode 100644
index 000000000..4d047af32
--- /dev/null
+++ b/tests/rustdoc/keyword.rs
@@ -0,0 +1,23 @@
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+// @has foo/index.html '//h2[@id="keywords"]' 'Keywords'
+// @has foo/index.html '//a[@href="keyword.match.html"]' 'match'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords'
+// @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
+// @has foo/keyword.match.html '//h1' 'Keyword match'
+// @has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has foo/index.html '//a/@href' '../foo/index.html'
+// @!has foo/foo/index.html
+// @!has-dir foo/foo
+// @!has foo/index.html '//span' '🔒'
+#[doc(keyword = "match")]
+/// this is a test!
+mod foo{}
+
+// @has foo/keyword.foo.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
+#[doc(keyword = "foo")]
+/// hello
+mod bar {}
diff --git a/tests/rustdoc/legacy-const-generic.rs b/tests/rustdoc/legacy-const-generic.rs
new file mode 100644
index 000000000..14533624e
--- /dev/null
+++ b/tests/rustdoc/legacy-const-generic.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+#![feature(rustc_attrs)]
+
+// @has 'foo/fn.foo.html'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+#[rustc_legacy_const_generics(1)]
+pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+ [x, Y, z]
+}
+
+// @has 'foo/fn.bar.html'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+#[rustc_legacy_const_generics(1, 2)]
+pub fn bar<const Y: usize, const Z: usize>(x: usize) -> [usize; 3] {
+ [x, Y, z]
+}
diff --git a/tests/rustdoc/lifetime-name.rs b/tests/rustdoc/lifetime-name.rs
new file mode 100644
index 000000000..0fb660591
--- /dev/null
+++ b/tests/rustdoc/lifetime-name.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has 'foo/type.Resolutions.html'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+pub type Resolutions<'tcx> = &'tcx u8;
diff --git a/tests/rustdoc/line-breaks.rs b/tests/rustdoc/line-breaks.rs
new file mode 100644
index 000000000..29c16fcd4
--- /dev/null
+++ b/tests/rustdoc/line-breaks.rs
@@ -0,0 +1,30 @@
+#![crate_name = "foo"]
+
+use std::ops::Add;
+use std::fmt::Display;
+
+//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
+pub fn function_with_a_really_long_name(parameter_one: i32,
+ parameter_two: i32)
+ -> Option<i32> {
+ Some(parameter_one + parameter_two)
+}
+
+//@count foo/fn.short_name.html //pre/br 0
+pub fn short_name(param: i32) -> i32 { param + 1 }
+
+//@count foo/fn.where_clause.html //pre/br 4
+pub fn where_clause<T, U>(param_one: T,
+ param_two: U)
+ where T: Add<U> + Display + Copy,
+ U: Add<T> + Display + Copy,
+ T::Output: Display + Add<U::Output> + Copy,
+ <T::Output as Add<U::Output>>::Output: Display,
+ U::Output: Display + Copy
+{
+ let x = param_one + param_two;
+ println!("{} + {} = {}", param_one, param_two, x);
+ let y = param_two + param_one;
+ println!("{} + {} = {}", param_two, param_one, y);
+ println!("{} + {} = {}", x, y, x + y);
+}
diff --git a/tests/rustdoc/link-assoc-const.rs b/tests/rustdoc/link-assoc-const.rs
new file mode 100644
index 000000000..75a2531a3
--- /dev/null
+++ b/tests/rustdoc/link-assoc-const.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//a[@href="foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST'
+// @has foo/index.html '//a[@href="struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST'
+
+//! We have here [`foo::FIRSTCONST`] and [`Bar::CONST`].
+
+pub mod foo {
+ pub const FIRSTCONST: u32 = 42;
+}
+
+pub struct Bar;
+
+impl Bar {
+ pub const CONST: u32 = 42;
+}
diff --git a/tests/rustdoc/link-title-escape.rs b/tests/rustdoc/link-title-escape.rs
new file mode 100644
index 000000000..7a322ea6d
--- /dev/null
+++ b/tests/rustdoc/link-title-escape.rs
@@ -0,0 +1,9 @@
+#![allow(rustdoc::broken_intra_doc_links)]
+
+#![crate_name = "foo"]
+
+//! hello [foo]
+//!
+//! [foo]: url 'title & <stuff> & "things"'
+
+// @hasraw 'foo/index.html' 'title &amp; &lt;stuff&gt; &amp; &quot;things&quot;'
diff --git a/tests/rustdoc/local-reexport-doc.rs b/tests/rustdoc/local-reexport-doc.rs
new file mode 100644
index 000000000..5dc857773
--- /dev/null
+++ b/tests/rustdoc/local-reexport-doc.rs
@@ -0,0 +1,16 @@
+// This test ensures that the reexports of local items also get the doc from
+// the reexport.
+
+#![crate_name = "foo"]
+
+// @has 'foo/fn.g.html'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' \
+// 'outer module inner module'
+
+mod inner_mod {
+ /// inner module
+ pub fn g() {}
+}
+
+/// outer module
+pub use inner_mod::g;
diff --git a/tests/rustdoc/logo-class-default.rs b/tests/rustdoc/logo-class-default.rs
new file mode 100644
index 000000000..d2d439199
--- /dev/null
+++ b/tests/rustdoc/logo-class-default.rs
@@ -0,0 +1,4 @@
+// Note: this test is paired with logo-class.rs.
+// @has logo_class_default/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
+// @has src/logo_class_default/logo-class-default.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
+pub struct SomeStruct;
diff --git a/tests/rustdoc/logo-class.rs b/tests/rustdoc/logo-class.rs
new file mode 100644
index 000000000..d3aa446da
--- /dev/null
+++ b/tests/rustdoc/logo-class.rs
@@ -0,0 +1,10 @@
+#![doc(html_logo_url =
+ "https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png")]
+// Note: this test is paired with logo-class-default.rs.
+
+// @has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
+// @!has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
+//
+// @has src/logo_class/logo-class.rs.html '//*[@class="sub-logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
+// @!has src/logo_class/logo-class.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
+pub struct SomeStruct;
diff --git a/tests/rustdoc/macro-document-private-duplicate.rs b/tests/rustdoc/macro-document-private-duplicate.rs
new file mode 100644
index 000000000..d3cf7e140
--- /dev/null
+++ b/tests/rustdoc/macro-document-private-duplicate.rs
@@ -0,0 +1,25 @@
+// ignore-test (fails spuriously, see issue #89228)
+
+// FIXME: If two macros in the same module have the same name
+// (yes, that's a thing), rustdoc lists both of them on the index page,
+// but only documents the first one on the page for the macro.
+// Fortunately, this can only happen in document private items mode,
+// but it still isn't ideal behavior.
+//
+// See https://github.com/rust-lang/rust/pull/88019#discussion_r693920453
+//
+// compile-flags: --document-private-items
+
+// @hasraw macro_document_private_duplicate/index.html 'Doc 1.'
+// @hasraw macro_document_private_duplicate/macro.a_macro.html 'Doc 1.'
+/// Doc 1.
+macro_rules! a_macro {
+ () => ()
+}
+
+// @hasraw macro_document_private_duplicate/index.html 'Doc 2.'
+// @!hasraw macro_document_private_duplicate/macro.a_macro.html 'Doc 2.'
+/// Doc 2.
+macro_rules! a_macro {
+ () => ()
+}
diff --git a/tests/rustdoc/macro-document-private.rs b/tests/rustdoc/macro-document-private.rs
new file mode 100644
index 000000000..d2496913f
--- /dev/null
+++ b/tests/rustdoc/macro-document-private.rs
@@ -0,0 +1,19 @@
+// Checks that private macros are documented when `--document-private-items`
+// is present.
+//
+// This is a regression test for issue #73754.
+//
+// compile-flags: --document-private-items
+
+#![feature(decl_macro)]
+
+
+// @has macro_document_private/macro.some_macro.html
+macro some_macro {
+ (a: tt) => {}
+}
+
+// @has macro_document_private/macro.another_macro.html
+macro_rules! another_macro {
+ (a: tt) => {}
+}
diff --git a/tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html b/tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html
new file mode 100644
index 000000000..ce5d3a846
--- /dev/null
+++ b/tests/rustdoc/macro-generated-macro.macro_linebreak_pre.html
@@ -0,0 +1,6 @@
+macro_rules! linebreak {
+ (
+ <= 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
+ 26 27 28 =>
+ ) => { ... };
+} \ No newline at end of file
diff --git a/tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html b/tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html
new file mode 100644
index 000000000..28f15522a
--- /dev/null
+++ b/tests/rustdoc/macro-generated-macro.macro_morestuff_pre.html
@@ -0,0 +1,15 @@
+macro_rules! morestuff {
+ (
+ <= "space between most kinds of tokens" : 1 $x + @ :: >>= 'static
+ "no space inside paren or bracket" : (2 a) [2 a] $(2 $a:tt)*
+ "space inside curly brace" : { 2 a }
+ "no space inside empty delimiters" : () [] {}
+ "no space before comma or semicolon" : a, (a), { a }, a; [T; 0];
+ "the three repetition specifiers" : $(@)*, $(@)+, $(@)?
+ "repetition separators" : $(@)|*, $(@)|+, $(@)==*, $(@)static*
+ "plus or star cannot be a repetition separator" : $(@)+ * $(@)* +
+ "no space between ident and paren" : let _ = f(0) + f[0] + Struct {};
+ "space between keyword and paren" : return (a,) & for x in (..)
+ "some special case keywords" : pub(crate), fn() -> u8, Self(0, 0) =>
+ ) => { ... };
+} \ No newline at end of file
diff --git a/tests/rustdoc/macro-generated-macro.rs b/tests/rustdoc/macro-generated-macro.rs
new file mode 100644
index 000000000..1a423cac1
--- /dev/null
+++ b/tests/rustdoc/macro-generated-macro.rs
@@ -0,0 +1,39 @@
+macro_rules! make_macro {
+ ($macro_name:ident $($matcher:tt)*) => {
+ #[macro_export]
+ macro_rules! $macro_name {
+ (<= $($matcher)* =>) => {};
+ }
+ }
+}
+
+// @has macro_generated_macro/macro.interpolations.html //pre 'macro_rules! interpolations {'
+// @has - //pre '(<= type $($i:ident)::* + $e:expr =>) => { ... };'
+make_macro!(interpolations type $($i:ident)::* + $e:expr);
+interpolations!(<= type foo::bar + x.sort() =>);
+
+// @has macro_generated_macro/macro.attributes.html //pre 'macro_rules! attributes {'
+// @has - //pre '(<= #![no_std] #[cfg(feature = "alloc")] =>) => { ... };'
+make_macro!(attributes #![no_std] #[cfg(feature = "alloc")]);
+
+// @has macro_generated_macro/macro.groups.html //pre 'macro_rules! groups {'
+// @has - //pre '(<= fn {} () { foo[0] } =>) => { ... };'
+make_macro!(groups fn {}() {foo[0]});
+
+// @snapshot macro_linebreak_pre macro_generated_macro/macro.linebreak.html //pre/text()
+make_macro!(linebreak 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28);
+
+// @snapshot macro_morestuff_pre macro_generated_macro/macro.morestuff.html //pre/text()
+make_macro!(morestuff
+ "space between most kinds of tokens": 1 $x + @ :: >>= 'static
+ "no space inside paren or bracket": (2 a) [2 a] $(2 $a:tt)*
+ "space inside curly brace": { 2 a }
+ "no space inside empty delimiters": () [] {}
+ "no space before comma or semicolon": a, (a), { a }, a; [T; 0];
+ "the three repetition specifiers": $(@)*, $(@)+, $(@)?
+ "repetition separators": $(@)|*, $(@)|+, $(@)==*, $(@)static*
+ "plus or star cannot be a repetition separator": $(@)+ * $(@)* +
+ "no space between ident and paren": let _ = f(0) + f[0] + Struct {};
+ "space between keyword and paren": return (a,) & for x in (..)
+ "some special case keywords": pub(crate), fn() -> u8, Self(0, 0)
+);
diff --git a/tests/rustdoc/macro-higher-kinded-function.rs b/tests/rustdoc/macro-higher-kinded-function.rs
new file mode 100644
index 000000000..b8c52b7b7
--- /dev/null
+++ b/tests/rustdoc/macro-higher-kinded-function.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+pub struct TyCtxt<'tcx>(&'tcx u8);
+
+macro_rules! gen {
+ ($(($name:ident, $tcx:lifetime, [$k:ty], [$r:ty]))*) => {
+ pub struct Providers {
+ $(pub $name: for<$tcx> fn(TyCtxt<$tcx>, $k) -> $r,)*
+ }
+ }
+}
+
+// @has 'foo/struct.Providers.html'
+// @has - '//*[@class="item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
+// @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
+gen! {
+ (a, 'tcx, [u8], [i8])
+ (b, 'tcx, [u16], [i16])
+}
diff --git a/tests/rustdoc/macro-in-async-block.rs b/tests/rustdoc/macro-in-async-block.rs
new file mode 100644
index 000000000..b4aaacf7b
--- /dev/null
+++ b/tests/rustdoc/macro-in-async-block.rs
@@ -0,0 +1,9 @@
+// Regression issue for rustdoc ICE encountered in PR #72088.
+// edition:2018
+#![feature(decl_macro)]
+
+fn main() {
+ async {
+ macro m() {}
+ };
+}
diff --git a/tests/rustdoc/macro-in-closure.rs b/tests/rustdoc/macro-in-closure.rs
new file mode 100644
index 000000000..b4411d927
--- /dev/null
+++ b/tests/rustdoc/macro-in-closure.rs
@@ -0,0 +1,16 @@
+// Regression issue for rustdoc ICE encountered in PR #65252.
+
+#![feature(decl_macro)]
+
+fn main() {
+ || {
+ macro m() {}
+ };
+
+ let _ = || {
+ macro n() {}
+ };
+
+ let cond = true;
+ let _ = || if cond { macro n() {} } else { panic!() };
+}
diff --git a/tests/rustdoc/macro-indirect-use.rs b/tests/rustdoc/macro-indirect-use.rs
new file mode 100644
index 000000000..b2d9336cf
--- /dev/null
+++ b/tests/rustdoc/macro-indirect-use.rs
@@ -0,0 +1,16 @@
+// Checks that it is possible to make a macro public through a `pub use` of its
+// parent module.
+//
+// This is a regression test for issue #87257.
+
+#![feature(decl_macro)]
+
+mod outer {
+ pub mod inner {
+ pub macro some_macro() {}
+ }
+}
+
+// @has macro_indirect_use/inner/index.html
+// @has macro_indirect_use/inner/macro.some_macro.html
+pub use outer::inner;
diff --git a/tests/rustdoc/macro-private-not-documented.rs b/tests/rustdoc/macro-private-not-documented.rs
new file mode 100644
index 000000000..f135a3a9c
--- /dev/null
+++ b/tests/rustdoc/macro-private-not-documented.rs
@@ -0,0 +1,19 @@
+// Checks that private macros aren't documented by default. They
+// should be still be documented in `--document-private-items` mode,
+// but that's tested in `macro-document-private.rs`.
+//
+//
+// This is a regression text for issue #88453.
+#![feature(decl_macro)]
+
+// @!hasraw macro_private_not_documented/index.html 'a_macro'
+// @!has macro_private_not_documented/macro.a_macro.html
+macro_rules! a_macro {
+ () => ()
+}
+
+// @!hasraw macro_private_not_documented/index.html 'another_macro'
+// @!has macro_private_not_documented/macro.another_macro.html
+macro another_macro {
+ () => ()
+}
diff --git a/tests/rustdoc/macro_pub_in_module.rs b/tests/rustdoc/macro_pub_in_module.rs
new file mode 100644
index 000000000..4fd85d689
--- /dev/null
+++ b/tests/rustdoc/macro_pub_in_module.rs
@@ -0,0 +1,82 @@
+// aux-build:macro_pub_in_module.rs
+// edition:2018
+// build-aux-docs
+
+//! See issue #74355
+#![feature(decl_macro, no_core, rustc_attrs)]
+#![crate_name = "krate"]
+#![no_core]
+
+ // @has external_crate/some_module/macro.external_macro.html
+ // @!has external_crate/macro.external_macro.html
+extern crate external_crate;
+
+pub mod inner {
+ // @has krate/inner/macro.raw_const.html
+ // @!has krate/macro.raw_const.html
+ pub macro raw_const() {}
+
+ // @has krate/inner/macro.test.html
+ // @!has krate/macro.test.html
+ #[rustc_builtin_macro]
+ pub macro test($item:item) {}
+
+ // @has krate/inner/macro.Clone.html
+ // @!has krate/macro.Clone.html
+ #[rustc_builtin_macro]
+ pub macro Clone($item:item) {}
+
+ // Make sure the logic is not affected by re-exports.
+ mod unrenamed {
+ // @!has krate/macro.unrenamed.html
+ #[rustc_macro_transparency = "semitransparent"]
+ pub macro unrenamed() {}
+ }
+ // @has krate/inner/macro.unrenamed.html
+ pub use unrenamed::unrenamed;
+
+ mod private {
+ // @!has krate/macro.m.html
+ pub macro m() {}
+ }
+ // @has krate/inner/macro.renamed.html
+ // @!has krate/macro.renamed.html
+ pub use private::m as renamed;
+
+ mod private2 {
+ // @!has krate/macro.m2.html
+ pub macro m2() {}
+ }
+ use private2 as renamed_mod;
+ // @has krate/inner/macro.m2.html
+ pub use renamed_mod::m2;
+
+ // @has krate/inner/macro.external_macro.html
+ // @!has krate/macro.external_macro.html
+ pub use ::external_crate::some_module::external_macro;
+}
+
+// Namespaces: Make sure the logic does not mix up a function name with a module name…
+fn both_fn_and_mod() {
+ // @!has krate/macro.in_both_fn_and_mod.html
+ pub macro in_both_fn_and_mod() {}
+}
+pub mod both_fn_and_mod {
+ // @!has krate/both_fn_and_mod/macro.in_both_fn_and_mod.html
+}
+
+const __: () = {
+ // @!has krate/macro.in_both_const_and_mod.html
+ pub macro in_both_const_and_mod() {}
+};
+pub mod __ {
+ // @!has krate/__/macro.in_both_const_and_mod.html
+}
+
+enum Enum {
+ Crazy = {
+ // @!has krate/macro.this_is_getting_weird.html;
+ pub macro this_is_getting_weird() {}
+ 42
+ },
+}
diff --git a/tests/rustdoc/macro_rules-matchers.rs b/tests/rustdoc/macro_rules-matchers.rs
new file mode 100644
index 000000000..96f4126c7
--- /dev/null
+++ b/tests/rustdoc/macro_rules-matchers.rs
@@ -0,0 +1,34 @@
+// This is a regression test for issue #86208.
+// It is also a general test of macro_rules! display.
+
+#![crate_name = "foo"]
+
+// @has 'foo/macro.todo.html'
+// @has - '//span[@class="macro"]' 'macro_rules!'
+// @hasraw - ' todo {'
+
+// @hasraw - '{ () =&gt; { ... }; ($('
+// @has - '//span[@class="macro-nonterminal"]' '$'
+// @has - '//span[@class="macro-nonterminal"]' 'arg'
+// @hasraw - ':tt)+'
+// @hasraw - ') =&gt; { ... }; }'
+pub use std::todo;
+
+mod mod1 {
+ // @has 'foo/macro.macro1.html'
+ // @hasraw - 'macro_rules!'
+ // @hasraw - 'macro1'
+ // @hasraw - '{ () =&gt; { ... }; ($('
+ // @has - '//span[@class="macro-nonterminal"]' '$'
+ // @has - '//span[@class="macro-nonterminal"]' 'arg'
+ // @hasraw - ':'
+ // @hasraw - 'expr'
+ // @hasraw - '),'
+ // @hasraw - '+'
+ // @hasraw - ') =&gt; { ... }; }'
+ #[macro_export]
+ macro_rules! macro1 {
+ () => {};
+ ($($arg:expr),+) => { stringify!($($arg),+) };
+ }
+}
diff --git a/tests/rustdoc/macros.rs b/tests/rustdoc/macros.rs
new file mode 100644
index 000000000..ae0cf7a14
--- /dev/null
+++ b/tests/rustdoc/macros.rs
@@ -0,0 +1,24 @@
+// @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
+// @has - //pre '() => { ... };'
+// @has - //pre '($a:tt) => { ... };'
+// @has - //pre '($e:expr) => { ... };'
+#[macro_export]
+macro_rules! my_macro {
+ () => [];
+ ($a:tt) => ();
+ ($e:expr) => {};
+}
+
+// Check that exported macro defined in a module are shown at crate root.
+// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
+// @has - //pre '() => { ... };'
+// @has - //pre '($a:tt) => { ... };'
+// @has - //pre '($e:expr) => { ... };'
+mod sub {
+ #[macro_export]
+ macro_rules! my_sub_macro {
+ () => {};
+ ($a:tt) => {};
+ ($e:expr) => {};
+ }
+}
diff --git a/tests/rustdoc/manual_impl.rs b/tests/rustdoc/manual_impl.rs
new file mode 100644
index 000000000..b2ee077bc
--- /dev/null
+++ b/tests/rustdoc/manual_impl.rs
@@ -0,0 +1,77 @@
+// @has manual_impl/trait.T.html
+// @has - '//*[@class="docblock"]' 'Docs associated with the trait definition.'
+// @has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.'
+// @has - '//*[@class="docblock"]' 'Docs associated with the trait b_method definition.'
+/// Docs associated with the trait definition.
+pub trait T {
+ /// Docs associated with the trait a_method definition.
+ fn a_method(&self) -> usize;
+
+ /// Docs associated with the trait b_method definition.
+ fn b_method(&self) -> usize {
+ self.a_method()
+ }
+
+ /// Docs associated with the trait c_method definition.
+ ///
+ /// There is another line
+ fn c_method(&self) -> usize {
+ self.a_method()
+ }
+}
+
+// @has manual_impl/struct.S1.html '//*[@class="trait"]' 'T'
+// @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait implementation.'
+// @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait a_method implementation.'
+// @!has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.'
+// @has - '//div[@class="impl-items"]//div[@class="docblock"]' 'Docs associated with the trait b_method definition.'
+// @has - '//div[@class="impl-items"]//div[@class="docblock"]' 'Docs associated with the trait c_method definition.'
+// @!has - '//*[@class="docblock"]' 'There is another line'
+// @has - '//div[@class="impl-items"]//div[@class="docblock"]' 'Read more'
+pub struct S1(usize);
+
+/// Docs associated with the S1 trait implementation.
+impl T for S1 {
+ /// Docs associated with the S1 trait a_method implementation.
+ fn a_method(&self) -> usize {
+ self.0
+ }
+}
+
+// @has manual_impl/struct.S2.html '//*[@class="trait"]' 'T'
+// @has - '//*[@class="docblock"]' 'Docs associated with the S2 trait implementation.'
+// @has - '//*[@class="docblock"]' 'Docs associated with the S2 trait a_method implementation.'
+// @has - '//*[@class="docblock"]' 'Docs associated with the S2 trait c_method implementation.'
+// @has - '//div[@class="impl-items"]//div[@class="docblock"]' 'Docs associated with the trait b_method definition.'
+pub struct S2(usize);
+
+/// Docs associated with the S2 trait implementation.
+impl T for S2 {
+ /// Docs associated with the S2 trait a_method implementation.
+ fn a_method(&self) -> usize {
+ self.0
+ }
+
+ /// Docs associated with the S2 trait c_method implementation.
+ fn c_method(&self) -> usize {
+ 5
+ }
+}
+
+// @has manual_impl/struct.S3.html '//*[@class="trait"]' 'T'
+// @has - '//div[@class="docblock"]' 'Docs associated with the S3 trait implementation.'
+// @has - '//div[@class="docblock"]' 'Docs associated with the S3 trait b_method implementation.'
+// @has - '//div[@class="impl-items"]//div[@class="docblock"]' 'Docs associated with the trait a_method definition.'
+pub struct S3(usize);
+
+/// Docs associated with the S3 trait implementation.
+impl T for S3 {
+ fn a_method(&self) -> usize {
+ self.0
+ }
+
+ /// Docs associated with the S3 trait b_method implementation.
+ fn b_method(&self) -> usize {
+ 5
+ }
+}
diff --git a/tests/rustdoc/markdown-summaries.rs b/tests/rustdoc/markdown-summaries.rs
new file mode 100644
index 000000000..31e7072b5
--- /dev/null
+++ b/tests/rustdoc/markdown-summaries.rs
@@ -0,0 +1,27 @@
+#![crate_type = "lib"]
+#![crate_name = "summaries"]
+
+//! This *summary* has a [link] and `code`.
+//!
+//! This is the second paragraph.
+//!
+//! [link]: https://example.com
+
+// @hasraw search-index.js 'This <em>summary</em> has a link and <code>code</code>.'
+// @!hasraw - 'second paragraph'
+
+/// This `code` will be rendered in a code tag.
+///
+/// This text should not be rendered.
+pub struct Sidebar;
+
+// @hasraw search-index.js 'This <code>code</code> will be rendered in a code tag.'
+// @hasraw summaries/sidebar-items.js 'This `code` will be rendered in a code tag.'
+// @!hasraw - 'text should not be rendered'
+
+/// ```text
+/// this block should not be rendered
+/// ```
+pub struct Sidebar2;
+
+// @!hasraw summaries/sidebar-items.js 'block should not be rendered'
diff --git a/tests/rustdoc/masked.rs b/tests/rustdoc/masked.rs
new file mode 100644
index 000000000..875c026fd
--- /dev/null
+++ b/tests/rustdoc/masked.rs
@@ -0,0 +1,31 @@
+// aux-build:masked.rs
+
+#![feature(doc_masked)]
+
+#![crate_name = "foo"]
+
+#[doc(masked)]
+extern crate masked;
+
+// @!hasraw 'search-index.js' 'masked_method'
+
+// @!hasraw 'foo/struct.String.html' 'MaskedTrait'
+// @!hasraw 'foo/struct.String.html' 'MaskedBlanketTrait'
+// @!hasraw 'foo/struct.String.html' 'masked_method'
+pub use std::string::String;
+
+// @!hasraw 'foo/trait.Clone.html' 'MaskedStruct'
+pub use std::clone::Clone;
+
+// @!hasraw 'foo/struct.MyStruct.html' 'MaskedTrait'
+// @!hasraw 'foo/struct.MyStruct.html' 'masked_method'
+pub struct MyStruct;
+
+impl masked::MaskedTrait for MyStruct {
+ fn masked_method() {}
+}
+
+// @!hasraw 'foo/trait.MyTrait.html' 'MaskedStruct'
+pub trait MyTrait {}
+
+impl MyTrait for masked::MaskedStruct {}
diff --git a/tests/rustdoc/method-list.rs b/tests/rustdoc/method-list.rs
new file mode 100644
index 000000000..50f4af3aa
--- /dev/null
+++ b/tests/rustdoc/method-list.rs
@@ -0,0 +1,18 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="sidebar-elems"]//section//a' 'super_long_name'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'Disp'
+pub struct Foo(usize);
+
+impl Foo {
+ pub fn super_long_name() {}
+}
+
+pub trait Disp {
+ fn disp_trait_method();
+}
+
+impl Disp for Foo {
+ fn disp_trait_method() {}
+}
diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.S1_top-doc.html b/tests/rustdoc/mixing-doc-comments-and-attrs.S1_top-doc.html
new file mode 100644
index 000000000..8ff114b99
--- /dev/null
+++ b/tests/rustdoc/mixing-doc-comments-and-attrs.S1_top-doc.html
@@ -0,0 +1,4 @@
+<div class="docblock"><p>Hello world!</p>
+<p>Goodbye!
+Hello again!</p>
+</div> \ No newline at end of file
diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html b/tests/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html
new file mode 100644
index 000000000..8ff114b99
--- /dev/null
+++ b/tests/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html
@@ -0,0 +1,4 @@
+<div class="docblock"><p>Hello world!</p>
+<p>Goodbye!
+Hello again!</p>
+</div> \ No newline at end of file
diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.S3_top-doc.html b/tests/rustdoc/mixing-doc-comments-and-attrs.S3_top-doc.html
new file mode 100644
index 000000000..a4ee4b141
--- /dev/null
+++ b/tests/rustdoc/mixing-doc-comments-and-attrs.S3_top-doc.html
@@ -0,0 +1,3 @@
+<div class="docblock"><p>Par 1</p>
+<p>Par 2</p>
+</div> \ No newline at end of file
diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.rs b/tests/rustdoc/mixing-doc-comments-and-attrs.rs
new file mode 100644
index 000000000..010058361
--- /dev/null
+++ b/tests/rustdoc/mixing-doc-comments-and-attrs.rs
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.S1.html'
+// @snapshot S1_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
+
+#[doc = "Hello world!\n\n"]
+/// Goodbye!
+#[doc = " Hello again!\n"]
+pub struct S1;
+
+// @has 'foo/struct.S2.html'
+// @snapshot S2_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
+
+/// Hello world!
+///
+#[doc = "Goodbye!"]
+/// Hello again!
+pub struct S2;
+
+// @has 'foo/struct.S3.html'
+// @snapshot S3_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
+/** Par 1
+*/ ///
+/// Par 2
+pub struct S3;
diff --git a/tests/rustdoc/mod-stackoverflow.rs b/tests/rustdoc/mod-stackoverflow.rs
new file mode 100644
index 000000000..45b1de216
--- /dev/null
+++ b/tests/rustdoc/mod-stackoverflow.rs
@@ -0,0 +1,6 @@
+// aux-build:mod-stackoverflow.rs
+// ignore-cross-compile
+
+extern crate mod_stackoverflow;
+pub use mod_stackoverflow::tree;
+pub use mod_stackoverflow::tree2;
diff --git a/tests/rustdoc/module-impls.rs b/tests/rustdoc/module-impls.rs
new file mode 100644
index 000000000..852f444e9
--- /dev/null
+++ b/tests/rustdoc/module-impls.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+pub use std::marker::Send;
+
+// @!hasraw foo/index.html 'Implementations'
diff --git a/tests/rustdoc/multiple-import-levels.rs b/tests/rustdoc/multiple-import-levels.rs
new file mode 100644
index 000000000..29b67c6b2
--- /dev/null
+++ b/tests/rustdoc/multiple-import-levels.rs
@@ -0,0 +1,34 @@
+// The goal of this test is to ensure that the attributes of all imports are taken into
+// account.
+
+#![crate_name = "foo"]
+
+mod a {
+ /// 1
+ pub struct Type;
+}
+
+mod b {
+ /// 2
+ pub use crate::a::Type;
+}
+
+mod c {
+ /// 3
+ pub use crate::b::Type;
+ /// 4
+ pub use crate::b::Type as Woof;
+}
+
+// @has 'foo/struct.Type.html'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'foo 2 1'
+/// foo
+pub use b::Type;
+// @has 'foo/struct.Whatever.html'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1'
+/// whatever
+pub use c::Type as Whatever;
+// @has 'foo/struct.Woof.html'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1'
+/// a dog
+pub use c::Woof;
diff --git a/tests/rustdoc/must_implement_one_of.rs b/tests/rustdoc/must_implement_one_of.rs
new file mode 100644
index 000000000..1f1dd5d57
--- /dev/null
+++ b/tests/rustdoc/must_implement_one_of.rs
@@ -0,0 +1,10 @@
+#![crate_name = "c"]
+#![feature(rustc_attrs)]
+
+#[rustc_must_implement_one_of(a, b)]
+// @matches c/trait.Trait.html '//*[@class="stab must_implement"]' \
+// 'At least one of the `a`, `b` methods is required.$'
+pub trait Trait {
+ fn a() {}
+ fn b() {}
+}
diff --git a/tests/rustdoc/mut-params.rs b/tests/rustdoc/mut-params.rs
new file mode 100644
index 000000000..3b862e651
--- /dev/null
+++ b/tests/rustdoc/mut-params.rs
@@ -0,0 +1,18 @@
+// Rustdoc shouldn't display `mut` in function arguments, which are
+// implementation details. Regression test for #81289.
+
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method has-srclink"]' 2
+// @!has - '//*[@class="impl-items"]//*[@class="method"]' 'mut'
+impl Foo {
+ pub fn foo(mut self) {}
+
+ pub fn bar(mut bar: ()) {}
+}
+
+// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
+pub fn baz(mut foo: Foo) {}
diff --git a/tests/rustdoc/namespaces.rs b/tests/rustdoc/namespaces.rs
new file mode 100644
index 000000000..ad828e5ee
--- /dev/null
+++ b/tests/rustdoc/namespaces.rs
@@ -0,0 +1,16 @@
+// issue #34843: rustdoc prioritises documenting reexports from the type namespace
+
+mod inner {
+ pub mod sync {
+ pub struct SomeStruct;
+ }
+
+ pub fn sync() {}
+}
+
+// @has namespaces/sync/index.html
+// @has namespaces/fn.sync.html
+// @has namespaces/index.html '//a/@href' 'sync/index.html'
+// @has - '//a/@href' 'fn.sync.html'
+#[doc(inline)]
+pub use inner::sync;
diff --git a/tests/rustdoc/negative-impl-sidebar.rs b/tests/rustdoc/negative-impl-sidebar.rs
new file mode 100644
index 000000000..4af6d0084
--- /dev/null
+++ b/tests/rustdoc/negative-impl-sidebar.rs
@@ -0,0 +1,9 @@
+#![feature(negative_impls)]
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @has foo/struct.Foo.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#trait-implementations"]' 'Trait Implementations'
+// @has - '//*[@class="sidebar-elems"]//section//a' '!Sync'
+impl !Sync for Foo {}
diff --git a/tests/rustdoc/negative-impl.rs b/tests/rustdoc/negative-impl.rs
new file mode 100644
index 000000000..af19c784d
--- /dev/null
+++ b/tests/rustdoc/negative-impl.rs
@@ -0,0 +1,14 @@
+#![feature(negative_impls)]
+
+// @matches negative_impl/struct.Alpha.html '//pre' "pub struct Alpha"
+pub struct Alpha;
+// @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>"
+pub struct Bravo<B>(B);
+
+// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl !Send for Alpha"
+impl !Send for Alpha {}
+
+// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' "\
+// impl<B> !Send for Bravo<B>"
+impl<B> !Send for Bravo<B> {}
diff --git a/tests/rustdoc/nested-modules.rs b/tests/rustdoc/nested-modules.rs
new file mode 100644
index 000000000..12234d2cf
--- /dev/null
+++ b/tests/rustdoc/nested-modules.rs
@@ -0,0 +1,42 @@
+#![crate_name = "aCrate"]
+
+mod a_module {
+ pub fn private_function() {}
+
+ pub use a_module::private_function as other_private_function;
+
+ pub mod a_nested_module {
+ // @has aCrate/a_nested_module/index.html '//a[@href="fn.a_nested_public_function.html"]' 'a_nested_public_function'
+ // @hasraw aCrate/a_nested_module/fn.a_nested_public_function.html 'pub fn a_nested_public_function()'
+ pub fn a_nested_public_function() {}
+
+ // @has aCrate/a_nested_module/index.html '//a[@href="fn.another_nested_public_function.html"]' 'another_nested_public_function'
+ // @hasraw aCrate/a_nested_module/fn.another_nested_public_function.html 'pub fn another_nested_public_function()'
+ pub use a_nested_module::a_nested_public_function as another_nested_public_function;
+ }
+
+ // @!hasraw aCrate/a_nested_module/index.html 'yet_another_nested_public_function'
+ pub use a_nested_module::a_nested_public_function as yet_another_nested_public_function;
+
+ // @!hasraw aCrate/a_nested_module/index.html 'one_last_nested_public_function'
+ pub use a_nested_module::another_nested_public_function as one_last_nested_public_function;
+}
+
+// @!hasraw aCrate/index.html 'a_module'
+// @has aCrate/index.html '//a[@href="a_nested_module/index.html"]' 'a_nested_module'
+pub use a_module::a_nested_module;
+
+// @has aCrate/index.html '//a[@href="fn.a_nested_public_function.html"]' 'a_nested_public_function'
+// @has aCrate/index.html '//a[@href="fn.another_nested_public_function.html"]' 'another_nested_public_function'
+// @has aCrate/index.html '//a[@href="fn.yet_another_nested_public_function.html"]' 'yet_another_nested_public_function'
+// @has aCrate/index.html '//a[@href="fn.one_last_nested_public_function.html"]' 'one_last_nested_public_function'
+pub use a_module::{
+ a_nested_module::{a_nested_public_function, another_nested_public_function},
+ one_last_nested_public_function, yet_another_nested_public_function,
+};
+
+// @has aCrate/index.html '//a[@href="fn.private_function.html"]' 'private_function'
+// @!hasraw aCrate/fn.private_function.html 'a_module'
+// @has aCrate/index.html '//a[@href="fn.other_private_function.html"]' 'other_private_function'
+// @!hasraw aCrate/fn.other_private_function.html 'a_module'
+pub use a_module::{other_private_function, private_function};
diff --git a/tests/rustdoc/no-compiler-reexport.rs b/tests/rustdoc/no-compiler-reexport.rs
new file mode 100644
index 000000000..d28fdf87b
--- /dev/null
+++ b/tests/rustdoc/no-compiler-reexport.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z unstable-options --document-hidden-items --document-private-items
+
+#![crate_name = "foo"]
+
+// @!has 'foo/index.html' '//code' 'extern crate std;'
+// @!has 'foo/index.html' '//code' 'use std::prelude'
+pub struct Foo;
diff --git a/tests/rustdoc/no-crate-filter.rs b/tests/rustdoc/no-crate-filter.rs
new file mode 100644
index 000000000..b2f899064
--- /dev/null
+++ b/tests/rustdoc/no-crate-filter.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// compile-flags: -Z unstable-options --disable-per-crate-search
+
+// @!has 'foo/struct.Foo.html' '//*[id="crate-search"]' ''
+pub struct Foo;
diff --git a/tests/rustdoc/no-run-still-checks-lints.rs b/tests/rustdoc/no-run-still-checks-lints.rs
new file mode 100644
index 000000000..9f7d1c884
--- /dev/null
+++ b/tests/rustdoc/no-run-still-checks-lints.rs
@@ -0,0 +1,9 @@
+// compile-flags:--test
+// should-fail
+
+#![doc(test(attr(deny(warnings))))]
+
+/// ```no_run
+/// let a = 3;
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc/no-stack-overflow-25295.rs b/tests/rustdoc/no-stack-overflow-25295.rs
new file mode 100644
index 000000000..dd79f1e4b
--- /dev/null
+++ b/tests/rustdoc/no-stack-overflow-25295.rs
@@ -0,0 +1,35 @@
+// Ensure this code doesn't stack overflow.
+// aux-build:enum-primitive.rs
+
+#[macro_use] extern crate enum_primitive;
+
+enum_from_primitive! {
+ pub enum Test {
+ A1,A2,A3,A4,A5,A6,
+ B1,B2,B3,B4,B5,B6,
+ C1,C2,C3,C4,C5,C6,
+ D1,D2,D3,D4,D5,D6,
+ E1,E2,E3,E4,E5,E6,
+ F1,F2,F3,F4,F5,F6,
+ G1,G2,G3,G4,G5,G6,
+ H1,H2,H3,H4,H5,H6,
+ I1,I2,I3,I4,I5,I6,
+ J1,J2,J3,J4,J5,J6,
+ K1,K2,K3,K4,K5,K6,
+ L1,L2,L3,L4,L5,L6,
+ M1,M2,M3,M4,M5,M6,
+ N1,N2,N3,N4,N5,N6,
+ O1,O2,O3,O4,O5,O6,
+ P1,P2,P3,P4,P5,P6,
+ Q1,Q2,Q3,Q4,Q5,Q6,
+ R1,R2,R3,R4,R5,R6,
+ S1,S2,S3,S4,S5,S6,
+ T1,T2,T3,T4,T5,T6,
+ U1,U2,U3,U4,U5,U6,
+ V1,V2,V3,V4,V5,V6,
+ W1,W2,W3,W4,W5,W6,
+ X1,X2,X3,X4,X5,X6,
+ Y1,Y2,Y3,Y4,Y5,Y6,
+ Z1,Z2,Z3,Z4,Z5,Z6,
+ }
+}
diff --git a/tests/rustdoc/no-unit-struct-field.rs b/tests/rustdoc/no-unit-struct-field.rs
new file mode 100644
index 000000000..d301954b6
--- /dev/null
+++ b/tests/rustdoc/no-unit-struct-field.rs
@@ -0,0 +1,18 @@
+// This test ensures that the tuple struct fields are not generated in the
+// search index.
+
+// @!hasraw search-index.js '"0"'
+// @!hasraw search-index.js '"1"'
+// @hasraw search-index.js '"foo_a"'
+// @hasraw search-index.js '"bar_a"'
+
+pub struct Bar(pub u32, pub u8);
+pub struct Foo {
+ pub foo_a: u8,
+}
+pub enum Enum {
+ Foo(u8),
+ Bar {
+ bar_a: u8,
+ },
+}
diff --git a/tests/rustdoc/no_std-primitive.rs b/tests/rustdoc/no_std-primitive.rs
new file mode 100644
index 000000000..22fd392dd
--- /dev/null
+++ b/tests/rustdoc/no_std-primitive.rs
@@ -0,0 +1,6 @@
+#![no_std]
+
+/// Link to [intra-doc link][u8]
+// @has 'no_std_primitive/fn.foo.html' '//a[@href="{{channel}}/core/primitive.u8.html"]' 'intra-doc link'
+// @has - '//a[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+pub fn foo() -> u8 {}
diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/normalize-assoc-item.rs
new file mode 100644
index 000000000..659480479
--- /dev/null
+++ b/tests/rustdoc/normalize-assoc-item.rs
@@ -0,0 +1,82 @@
+// ignore-tidy-linelength
+// aux-build:normalize-assoc-item.rs
+// build-aux-docs
+// compile-flags:-Znormalize-docs
+
+pub trait Trait {
+ type X;
+}
+
+impl Trait for usize {
+ type X = isize;
+}
+
+impl Trait for () {
+ type X = fn() -> i32;
+}
+
+impl Trait for isize {
+ type X = <() as Trait>::X;
+}
+
+// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
+pub fn f() -> <usize as Trait>::X {
+ 0
+}
+
+// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f2() -> fn() -> i32'
+pub fn f2() -> <isize as Trait>::X {
+ todo!()
+}
+
+pub struct S {
+ // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.box_me_up"]' 'box_me_up: Box<S, Global>'
+ pub box_me_up: <S as Trait>::X,
+ // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.generic"]' 'generic: (usize, isize)'
+ pub generic: <Generic<usize> as Trait>::X,
+}
+
+impl Trait for S {
+ type X = Box<S>;
+}
+
+pub struct Generic<Inner>(Inner);
+
+impl<Inner: Trait> Trait for Generic<Inner> {
+ type X = (Inner, Inner::X);
+}
+
+// These can't be normalized because they depend on a generic parameter.
+// However the user can choose whether the text should be displayed as `Inner::X` or `<Inner as Trait>::X`.
+
+// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
+pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);
+
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
+pub struct Unknown2<Inner: Trait>(pub Inner::X);
+
+trait Lifetimes<'a> {
+ type Y;
+}
+
+impl<'a> Lifetimes<'a> for usize {
+ type Y = &'a isize;
+}
+
+// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
+pub fn g() -> <usize as Lifetimes<'static>>::Y {
+ &0
+}
+
+// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
+pub const A: <usize as Lifetimes<'static>>::Y = &0;
+
+// test cross-crate re-exports
+extern crate inner;
+// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
+pub use inner::foo;
+
+// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn h<T>() -> IntoIter<T, Global>"
+pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
+ vec![].into_iter()
+}
diff --git a/tests/rustdoc/not-wf-ambiguous-normalization.rs b/tests/rustdoc/not-wf-ambiguous-normalization.rs
new file mode 100644
index 000000000..1e9f925f8
--- /dev/null
+++ b/tests/rustdoc/not-wf-ambiguous-normalization.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Znormalize-docs
+
+#![feature(type_alias_impl_trait)]
+
+trait Allocator {
+ type Buffer;
+}
+
+struct DefaultAllocator;
+
+// This unconstrained impl parameter causes the normalization of
+// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
+// which caused an ICE with `-Znormalize-docs`.
+impl<T> Allocator for DefaultAllocator {
+ type Buffer = ();
+}
+
+type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
+
+fn foo() -> A {
+ |_| ()
+}
+
+fn main() {}
diff --git a/tests/rustdoc/nul-error.rs b/tests/rustdoc/nul-error.rs
new file mode 100644
index 000000000..3d30f5f6b
--- /dev/null
+++ b/tests/rustdoc/nul-error.rs
@@ -0,0 +1,8 @@
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html '//code' ''
+#[doc = "Attempted to pass a string containing `\0`"]
+pub fn foo() {}
diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs
new file mode 100644
index 000000000..69c896265
--- /dev/null
+++ b/tests/rustdoc/playground-arg.rs
@@ -0,0 +1,13 @@
+// compile-flags: --playground-url=https://example.com/ -Z unstable-options
+
+#![crate_name = "foo"]
+
+//! ```
+//! use foo::dummy;
+//! dummy();
+//! ```
+
+pub fn dummy() {}
+
+// ensure that `extern crate foo;` was inserted into code snips automatically:
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20r%23foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D&edition=2015"]' "Run"
diff --git a/tests/rustdoc/playground-empty.rs b/tests/rustdoc/playground-empty.rs
new file mode 100644
index 000000000..7d8bd3ffe
--- /dev/null
+++ b/tests/rustdoc/playground-empty.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+#![doc(html_playground_url = "")]
+
+// compile-flags:-Z unstable-options --playground-url https://play.rust-lang.org/
+
+//! module docs
+//!
+//! ```
+//! println!("Hello, world!");
+//! ```
+
+// @!has foo/index.html '//a[@class="test-arrow"]' "Run"
diff --git a/tests/rustdoc/playground-none.rs b/tests/rustdoc/playground-none.rs
new file mode 100644
index 000000000..ff51c68d8
--- /dev/null
+++ b/tests/rustdoc/playground-none.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+//! module docs
+//!
+//! ```
+//! println!("Hello, world!");
+//! ```
+
+// @!has foo/index.html '//a[@class="test-arrow"]' "Run"
diff --git a/tests/rustdoc/playground-syntax-error.rs b/tests/rustdoc/playground-syntax-error.rs
new file mode 100644
index 000000000..8918ae874
--- /dev/null
+++ b/tests/rustdoc/playground-syntax-error.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+#![doc(html_playground_url = "https://play.rust-lang.org/")]
+
+/// bar docs
+///
+/// ```edition2015
+/// use std::future::Future;
+/// use std::pin::Pin;
+/// fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
+/// Box::pin(async move {
+/// if n > 0 {
+/// foo_recursive(n - 1).await;
+/// }
+/// })
+/// }
+/// ```
+pub fn bar() {}
+
+// @has foo/fn.bar.html
+// @has - '//a[@class="test-arrow"]' "Run"
+// @has - '//*[@class="docblock"]' 'foo_recursive'
diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs
new file mode 100644
index 000000000..877ea1cfb
--- /dev/null
+++ b/tests/rustdoc/playground.rs
@@ -0,0 +1,27 @@
+#![crate_name = "foo"]
+
+#![doc(html_playground_url = "https://www.example.com/")]
+
+//! module docs
+//!
+//! ```
+//! println!("Hello, world!");
+//! ```
+//!
+//! ```
+//! fn main() {
+//! println!("Hello, world!");
+//! }
+//! ```
+//!
+//! ```
+//! #![feature(something)]
+//!
+//! fn main() {
+//! println!("Hello, world!");
+//! }
+//! ```
+
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly&edition=2015"]' "Run"
diff --git a/tests/rustdoc/primitive-link.rs b/tests/rustdoc/primitive-link.rs
new file mode 100644
index 000000000..125e0c849
--- /dev/null
+++ b/tests/rustdoc/primitive-link.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i64.html"]' 'i64'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html"]' 'std::primitive::i32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.str.html"]' 'std::primitive::str'
+
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
+
+/// It contains [`u32`] and [i64].
+/// It also links to [std::primitive::i32], [std::primitive::str],
+/// and [`std::primitive::i32::MAX`].
+pub struct Foo;
diff --git a/tests/rustdoc/primitive-reexport.rs b/tests/rustdoc/primitive-reexport.rs
new file mode 100644
index 000000000..10a8a47db
--- /dev/null
+++ b/tests/rustdoc/primitive-reexport.rs
@@ -0,0 +1,28 @@
+// aux-build: primitive-reexport.rs
+// compile-flags:--extern foo --edition 2018
+
+#![crate_name = "bar"]
+
+// @has bar/p/index.html
+// @has - '//code' 'pub use bool;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//code' 'pub use char as my_char;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub mod p {
+ pub use foo::bar::*;
+}
+
+// @has bar/baz/index.html
+// @has - '//code' 'pub use bool;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//code' 'pub use char as my_char;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub use foo::bar as baz;
+
+// @has bar/index.html
+// @has - '//code' 'pub use str;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.str.html"]' 'str'
+// @has - '//code' 'pub use i32 as my_i32;'
+// @has - '//code/a[@href="{{channel}}/std/primitive.i32.html"]' 'i32'
+pub use str;
+pub use i32 as my_i32;
diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive-reference.rs
new file mode 100644
index 000000000..c3a5eb6d3
--- /dev/null
+++ b/tests/rustdoc/primitive-reference.rs
@@ -0,0 +1,37 @@
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+// @has foo/index.html
+// @has - '//h2[@id="primitives"]' 'Primitive Types'
+// @has - '//a[@href="primitive.reference.html"]' 'reference'
+// @has - '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
+// @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
+// @has foo/primitive.reference.html
+// @has - '//a[@class="primitive"]' 'reference'
+// @has - '//h1' 'Primitive Type reference'
+// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+
+// There should be only one implementation listed.
+// @count - '//*[@class="impl has-srclink"]' 1
+// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \
+// 'impl<A, B> Foo<&A> for &B'
+#[doc(primitive = "reference")]
+/// this is a test!
+mod reference {}
+
+pub struct Bar;
+
+// This implementation should **not** show up.
+impl<T> From<&T> for Bar {
+ fn from(s: &T) -> Self {
+ Bar
+ }
+}
+
+pub trait Foo<T> {
+ fn stuff(&self, other: &T) {}
+}
+
+// This implementation should show up.
+impl<A, B> Foo<&A> for &B {}
diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs
new file mode 100644
index 000000000..779224146
--- /dev/null
+++ b/tests/rustdoc/primitive-slice-auto-trait.rs
@@ -0,0 +1,14 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
+// @has - '//h1' 'Primitive Type slice'
+// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T]where T: Sync'
+#[doc(primitive = "slice")]
+/// this is a test!
+mod slice_prim {}
diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs
new file mode 100644
index 000000000..4344d24f9
--- /dev/null
+++ b/tests/rustdoc/primitive-tuple-auto-trait.rs
@@ -0,0 +1,22 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple'
+// @has - '//h1' 'Primitive Type tuple'
+// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Sync'
+#[doc(primitive = "tuple")]
+/// this is a test!
+///
+// Hardcoded anchor to header written in library/core/src/primitive_docs.rs
+// @has - '//h2[@id="trait-implementations-1"]' 'Trait implementations'
+/// # Trait implementations
+///
+/// This header is hard-coded in the HTML format linking for `#[doc(fake_variadics)]`.
+/// To make sure it gets linked correctly, we need to make sure the hardcoded anchor
+/// in the code matches what rustdoc generates for the header.
+mod tuple_prim {}
diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs
new file mode 100644
index 000000000..db7cfd60c
--- /dev/null
+++ b/tests/rustdoc/primitive-tuple-variadic.rs
@@ -0,0 +1,18 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+pub trait Foo {}
+
+// @has foo/trait.Foo.html
+// @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
+#[doc(fake_variadic)]
+impl<T> Foo for (T,) {}
+
+pub trait Bar {}
+
+// @has foo/trait.Bar.html
+// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
+#[doc(fake_variadic)]
+impl<U: Foo> Bar for (U,) {}
diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs
new file mode 100644
index 000000000..61850e246
--- /dev/null
+++ b/tests/rustdoc/primitive-unit-auto-trait.rs
@@ -0,0 +1,14 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit'
+// @has - '//h1' 'Primitive Type unit'
+// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for ()'
+#[doc(primitive = "unit")]
+/// this is a test!
+mod unit_prim {}
diff --git a/tests/rustdoc/primitive.rs b/tests/rustdoc/primitive.rs
new file mode 100644
index 000000000..516c7c0c6
--- /dev/null
+++ b/tests/rustdoc/primitive.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+// @has foo/index.html '//h2[@id="primitives"]' 'Primitive Types'
+// @has foo/index.html '//a[@href="primitive.i32.html"]' 'i32'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
+// @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32'
+// @has foo/primitive.i32.html '//h1' 'Primitive Type i32'
+// @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has foo/index.html '//a/@href' '../foo/index.html'
+// @!has foo/index.html '//span' '🔒'
+#[doc(primitive = "i32")]
+/// this is a test!
+mod i32{}
+
+// @has foo/primitive.bool.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
+#[doc(primitive = "bool")]
+/// hello
+mod bool {}
diff --git a/tests/rustdoc/primitive/no_std.rs b/tests/rustdoc/primitive/no_std.rs
new file mode 100644
index 000000000..f0f70cb6c
--- /dev/null
+++ b/tests/rustdoc/primitive/no_std.rs
@@ -0,0 +1,16 @@
+#![no_std]
+#![deny(warnings)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link'
+/// Link to [primitive link][u8]
+pub fn foo() -> u8 {}
+
+// Test that all primitives can be linked to.
+/// [isize] [i8] [i16] [i32] [i64] [i128]
+/// [usize] [u8] [u16] [u32] [u64] [u128]
+/// [f32] [f64]
+/// [char] [bool] [str] [slice] [array] [tuple] [unit]
+/// [pointer] [reference] [fn] [never]
+pub fn bar() {}
diff --git a/tests/rustdoc/primitive/primitive-generic-impl.rs b/tests/rustdoc/primitive/primitive-generic-impl.rs
new file mode 100644
index 000000000..7b336b398
--- /dev/null
+++ b/tests/rustdoc/primitive/primitive-generic-impl.rs
@@ -0,0 +1,8 @@
+#![feature(rustdoc_internals)]
+#![crate_name = "foo"]
+
+// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl<T> ToString for T'
+
+#[doc(primitive = "i32")]
+/// Some useless docs, wouhou!
+mod i32 {}
diff --git a/tests/rustdoc/private-type-alias.rs b/tests/rustdoc/private-type-alias.rs
new file mode 100644
index 000000000..ec7385404
--- /dev/null
+++ b/tests/rustdoc/private-type-alias.rs
@@ -0,0 +1,31 @@
+type MyResultPriv<T> = Result<T, u16>;
+pub type MyResultPub<T> = Result<T, u64>;
+
+// @has private_type_alias/fn.get_result_priv.html '//pre' 'Result<u8, u16>'
+pub fn get_result_priv() -> MyResultPriv<u8> {
+ panic!();
+}
+
+// @has private_type_alias/fn.get_result_pub.html '//pre' 'MyResultPub<u32>'
+pub fn get_result_pub() -> MyResultPub<u32> {
+ panic!();
+}
+
+pub type PubRecursive = u16;
+type PrivRecursive3 = u8;
+type PrivRecursive2 = PubRecursive;
+type PrivRecursive1 = PrivRecursive3;
+
+// PrivRecursive1 is expanded twice and stops at u8
+// PrivRecursive2 is expanded once and stops at public type alias PubRecursive
+// @has private_type_alias/fn.get_result_recursive.html '//pre' '(u8, PubRecursive)'
+pub fn get_result_recursive() -> (PrivRecursive1, PrivRecursive2) {
+ panic!();
+}
+
+type MyLifetimePriv<'a> = &'a isize;
+
+// @has private_type_alias/fn.get_lifetime_priv.html '//pre' "&'static isize"
+pub fn get_lifetime_priv() -> MyLifetimePriv<'static> {
+ panic!();
+}
diff --git a/tests/rustdoc/proc-macro.rs b/tests/rustdoc/proc-macro.rs
new file mode 100644
index 000000000..10acb7ac4
--- /dev/null
+++ b/tests/rustdoc/proc-macro.rs
@@ -0,0 +1,72 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro --document-private-items
+
+#![crate_type="proc-macro"]
+#![crate_name="some_macros"]
+
+// @has some_macros/index.html
+// @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
+
+//! include a link to [some_proc_macro!] to make sure it works.
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// @has some_macros/index.html
+// @has - '//h2' 'Macros'
+// @has - '//h2' 'Attribute Macros'
+// @has - '//h2' 'Derive Macros'
+// @!has - '//h2' 'Functions'
+
+// @has some_macros/all.html
+// @has - '//a[@href="macro.some_proc_macro.html"]' 'some_proc_macro'
+// @has - '//a[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
+// @has - '//a[@href="derive.SomeDerive.html"]' 'SomeDerive'
+// @!has - '//a/@href' 'fn.some_proc_macro.html'
+// @!has - '//a/@href' 'fn.some_proc_attr.html'
+// @!has - '//a/@href' 'fn.some_derive.html'
+
+// @has some_macros/index.html '//a/@href' 'macro.some_proc_macro.html'
+// @!has - '//a/@href' 'fn.some_proc_macro.html'
+// @has some_macros/macro.some_proc_macro.html
+// @!has some_macros/fn.some_proc_macro.html
+/// a proc-macro that swallows its input and does nothing.
+#[proc_macro]
+pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+// @has some_macros/index.html '//a/@href' 'attr.some_proc_attr.html'
+// @!has - '//a/@href' 'fn.some_proc_attr.html'
+// @has some_macros/attr.some_proc_attr.html
+// @!has some_macros/fn.some_proc_attr.html
+/// a proc-macro attribute that passes its item through verbatim.
+#[proc_macro_attribute]
+pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ item
+}
+
+// @has some_macros/index.html '//a/@href' 'derive.SomeDerive.html'
+// @!has - '//a/@href' 'fn.some_derive.html'
+// @has some_macros/derive.SomeDerive.html
+// @!has some_macros/fn.some_derive.html
+/// a derive attribute that adds nothing to its input.
+#[proc_macro_derive(SomeDerive)]
+pub fn some_derive(_item: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+// @has some_macros/foo/index.html
+mod foo {
+ // @has - '//code' 'pub use some_proc_macro;'
+ // @has - '//a/@href' '../macro.some_proc_macro.html'
+ pub use some_proc_macro;
+ // @has - '//code' 'pub use some_proc_attr;'
+ // @has - '//a/@href' '../attr.some_proc_attr.html'
+ pub use some_proc_attr;
+ // @has - '//code' 'pub use some_derive;'
+ // @has - '//a/@href' '../derive.SomeDerive.html'
+ pub use some_derive;
+}
diff --git a/tests/rustdoc/process-termination.rs b/tests/rustdoc/process-termination.rs
new file mode 100644
index 000000000..32258792b
--- /dev/null
+++ b/tests/rustdoc/process-termination.rs
@@ -0,0 +1,24 @@
+// compile-flags:--test
+
+/// A check of using various process termination strategies
+///
+/// # Examples
+///
+/// ```rust
+/// assert!(true); // this returns `()`, all is well
+/// ```
+///
+/// You can also simply return `Ok(())`, but you'll need to disambiguate the
+/// type using turbofish, because we cannot infer the type:
+///
+/// ```rust
+/// Ok::<(), &'static str>(())
+/// ```
+///
+/// You can err with anything that implements `Debug`:
+///
+/// ```rust,should_panic
+/// Err("This is returned from `main`, leading to panic")?;
+/// Ok::<(), &'static str>(())
+/// ```
+pub fn check_process_termination() {}
diff --git a/tests/rustdoc/pub-extern-crate.rs b/tests/rustdoc/pub-extern-crate.rs
new file mode 100644
index 000000000..26747a4d1
--- /dev/null
+++ b/tests/rustdoc/pub-extern-crate.rs
@@ -0,0 +1,9 @@
+// aux-build:pub-extern-crate.rs
+
+// @has pub_extern_crate/index.html
+// @!has - '//code' 'pub extern crate inner'
+// @has - '//a/@href' 'inner/index.html'
+// @has pub_extern_crate/inner/index.html
+// @has pub_extern_crate/inner/struct.SomeStruct.html
+#[doc(inline)]
+pub extern crate inner;
diff --git a/tests/rustdoc/pub-method.rs b/tests/rustdoc/pub-method.rs
new file mode 100644
index 000000000..0dca3f672
--- /dev/null
+++ b/tests/rustdoc/pub-method.rs
@@ -0,0 +1,20 @@
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn bar() -> '
+/// foo
+pub fn bar() -> usize {
+ 2
+}
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="method has-srclink"]' 'pub fn new()'
+// @has - '//*[@class="method has-srclink"]' 'fn not_pub()'
+pub struct Foo(usize);
+
+impl Foo {
+ pub fn new() -> Foo { Foo(0) }
+ fn not_pub() {}
+}
diff --git a/tests/rustdoc/pub-use-extern-macros.rs b/tests/rustdoc/pub-use-extern-macros.rs
new file mode 100644
index 000000000..eefe6b4b0
--- /dev/null
+++ b/tests/rustdoc/pub-use-extern-macros.rs
@@ -0,0 +1,17 @@
+// aux-build:pub-use-extern-macros.rs
+
+extern crate macros;
+
+// @has pub_use_extern_macros/macro.bar.html
+// @!has pub_use_extern_macros/index.html '//code' 'pub use macros::bar;'
+pub use macros::bar;
+
+// @has pub_use_extern_macros/macro.baz.html
+// @!has pub_use_extern_macros/index.html '//code' 'pub use macros::baz;'
+#[doc(inline)]
+pub use macros::baz;
+
+// @!has pub_use_extern_macros/macro.quux.html
+// @!has pub_use_extern_macros/index.html '//code' 'pub use macros::quux;'
+#[doc(hidden)]
+pub use macros::quux;
diff --git a/tests/rustdoc/range-arg-pattern.rs b/tests/rustdoc/range-arg-pattern.rs
new file mode 100644
index 000000000..bdbcc47c9
--- /dev/null
+++ b/tests/rustdoc/range-arg-pattern.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
+pub fn f(0u8..=255: u8) {}
diff --git a/tests/rustdoc/raw-ident-eliminate-r-hashtag.rs b/tests/rustdoc/raw-ident-eliminate-r-hashtag.rs
new file mode 100644
index 000000000..7dbe63854
--- /dev/null
+++ b/tests/rustdoc/raw-ident-eliminate-r-hashtag.rs
@@ -0,0 +1,21 @@
+#![crate_type="lib"]
+
+pub mod internal {
+ // @has 'raw_ident_eliminate_r_hashtag/internal/struct.mod.html'
+ #[allow(non_camel_case_types)]
+ pub struct r#mod;
+
+ /// See [name], [other name]
+ ///
+ /// [name]: mod
+ /// [other name]: crate::internal::mod
+ // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="struct.mod.html"]' 'name'
+ // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="struct.mod.html"]' 'other name'
+ pub struct B;
+}
+
+/// See [name].
+///
+/// [name]: internal::mod
+// @has 'raw_ident_eliminate_r_hashtag/struct.A.html' '//*a[@href="internal/struct.mod.html"]' 'name'
+pub struct A;
diff --git a/tests/rustdoc/read-more-unneeded.rs b/tests/rustdoc/read-more-unneeded.rs
new file mode 100644
index 000000000..0303e4442
--- /dev/null
+++ b/tests/rustdoc/read-more-unneeded.rs
@@ -0,0 +1,34 @@
+// Regression test for https://github.com/rust-lang/rust/issues/105677.
+// This test ensures that the "Read more" link is only generated when
+// there is actually more documentation to read after the short summary.
+
+#![crate_name = "foo"]
+
+pub trait MyFrom {
+ /// # Hello
+ /// ## Yolo
+ /// more!
+ fn try_from1();
+ /// a
+ /// b
+ /// c
+ fn try_from2();
+ /// a
+ ///
+ /// b
+ ///
+ /// c
+ fn try_from3();
+}
+
+pub struct NonZero;
+
+// @has 'foo/struct.NonZero.html'
+impl MyFrom for NonZero {
+ // @matches - '//*[@class="docblock"]' '^Hello Read more$'
+ fn try_from1() {}
+ // @matches - '//*[@class="docblock"]' '^a\sb\sc$'
+ fn try_from2() {}
+ // @matches - '//*[@class="docblock"]' '^a Read more$'
+ fn try_from3() {}
+}
diff --git a/tests/rustdoc/recursion1.rs b/tests/rustdoc/recursion1.rs
new file mode 100644
index 000000000..edf7e440f
--- /dev/null
+++ b/tests/rustdoc/recursion1.rs
@@ -0,0 +1,13 @@
+#![crate_type = "lib"]
+
+mod m {
+ pub use self::a::Foo;
+
+ mod a {
+ pub struct Foo;
+ }
+
+ mod b {
+ pub use super::*;
+ }
+}
diff --git a/tests/rustdoc/recursion2.rs b/tests/rustdoc/recursion2.rs
new file mode 100644
index 000000000..edf7e440f
--- /dev/null
+++ b/tests/rustdoc/recursion2.rs
@@ -0,0 +1,13 @@
+#![crate_type = "lib"]
+
+mod m {
+ pub use self::a::Foo;
+
+ mod a {
+ pub struct Foo;
+ }
+
+ mod b {
+ pub use super::*;
+ }
+}
diff --git a/tests/rustdoc/recursion3.rs b/tests/rustdoc/recursion3.rs
new file mode 100644
index 000000000..e69b43016
--- /dev/null
+++ b/tests/rustdoc/recursion3.rs
@@ -0,0 +1,13 @@
+pub mod longhands {
+ pub use super::*;
+
+ pub use super::common_types::computed::compute_CSSColor as to_computed_value;
+
+ pub fn computed_as_specified() {}
+}
+
+pub mod common_types {
+ pub mod computed {
+ pub use super::super::longhands::computed_as_specified as compute_CSSColor;
+ }
+}
diff --git a/tests/rustdoc/recursive-deref-sidebar.rs b/tests/rustdoc/recursive-deref-sidebar.rs
new file mode 100644
index 000000000..619f40eff
--- /dev/null
+++ b/tests/rustdoc/recursive-deref-sidebar.rs
@@ -0,0 +1,22 @@
+use std::ops::Deref;
+
+pub struct A {}
+impl A { pub fn foo_a(&self) {} }
+
+pub struct B {}
+impl B { pub fn foo_b(&self) {} }
+
+pub struct C {}
+impl C { pub fn foo_c(&self) {} }
+
+// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_b'
+impl Deref for A {
+ type Target = B;
+ fn deref(&self) -> &B { todo!() }
+}
+
+// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_c'
+impl Deref for B {
+ type Target = C;
+ fn deref(&self) -> &C { todo!() }
+}
diff --git a/tests/rustdoc/recursive-deref.rs b/tests/rustdoc/recursive-deref.rs
new file mode 100644
index 000000000..aa38485c4
--- /dev/null
+++ b/tests/rustdoc/recursive-deref.rs
@@ -0,0 +1,120 @@
+use std::ops::Deref;
+
+// Cyclic deref with the parent (which is not the top parent).
+pub struct A;
+pub struct B;
+pub struct C;
+
+impl C {
+ pub fn c(&self) {}
+}
+
+// @has recursive_deref/struct.A.html '//h3[@class="code-header"]' 'impl Deref for A'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
+impl Deref for A {
+ type Target = B;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.B.html '//h3[@class="code-header"]' 'impl Deref for B'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
+impl Deref for B {
+ type Target = C;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.C.html '//h3[@class="code-header"]' 'impl Deref for C'
+impl Deref for C {
+ type Target = B;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// Cyclic deref with the grand-parent (which is not the top parent).
+pub struct D;
+pub struct E;
+pub struct F;
+pub struct G;
+
+impl G {
+ // There is no "self" parameter so it shouldn't be listed!
+ pub fn g() {}
+}
+
+// @has recursive_deref/struct.D.html '//h3[@class="code-header"]' 'impl Deref for D'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]' ''
+impl Deref for D {
+ type Target = E;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.E.html '//h3[@class="code-header"]' 'impl Deref for E'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]' ''
+impl Deref for E {
+ type Target = F;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.F.html '//h3[@class="code-header"]' 'impl Deref for F'
+// We also check that `G::g` method isn't rendered because there is no `self` argument.
+// @!has '-' '//*[@id="deref-methods-G"]' ''
+impl Deref for F {
+ type Target = G;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.G.html '//h3[@class="code-header"]' 'impl Deref for G'
+impl Deref for G {
+ type Target = E;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// Cyclic deref with top parent.
+pub struct H;
+pub struct I;
+
+impl I {
+ // There is no "self" parameter so it shouldn't be listed!
+ pub fn i() {}
+}
+
+// @has recursive_deref/struct.H.html '//h3[@class="code-header"]' 'impl Deref for H'
+// @!has '-' '//*[@id="deref-methods-I"]' ''
+impl Deref for H {
+ type Target = I;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.I.html '//h3[@class="code-header"]' 'impl Deref for I'
+impl Deref for I {
+ type Target = H;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
diff --git a/tests/rustdoc/redirect-const.rs b/tests/rustdoc/redirect-const.rs
new file mode 100644
index 000000000..453da8387
--- /dev/null
+++ b/tests/rustdoc/redirect-const.rs
@@ -0,0 +1,13 @@
+#![crate_name="foo"]
+
+pub use hidden::STATIC_FOO;
+pub use hidden::CONST_FOO;
+
+mod hidden {
+ // @has foo/hidden/static.STATIC_FOO.html
+ // @has - '//p/a' '../../foo/static.STATIC_FOO.html'
+ pub static STATIC_FOO: u64 = 0;
+ // @has foo/hidden/constant.CONST_FOO.html
+ // @has - '//p/a' '../../foo/constant.CONST_FOO.html'
+ pub const CONST_FOO: u64 = 0;
+}
diff --git a/tests/rustdoc/redirect-map-empty.rs b/tests/rustdoc/redirect-map-empty.rs
new file mode 100644
index 000000000..e9d021e0f
--- /dev/null
+++ b/tests/rustdoc/redirect-map-empty.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z unstable-options --generate-redirect-map
+
+#![crate_name = "foo"]
+
+// @!has foo/redirect-map.json
+pub struct Foo;
diff --git a/tests/rustdoc/redirect-map.rs b/tests/rustdoc/redirect-map.rs
new file mode 100644
index 000000000..b7f16b64e
--- /dev/null
+++ b/tests/rustdoc/redirect-map.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z unstable-options --generate-redirect-map
+
+#![crate_name = "foo"]
+
+// @!has foo/private/struct.Quz.html
+// @!has foo/hidden/struct.Bar.html
+// @has foo/redirect-map.json
+pub use private::Quz;
+pub use hidden::Bar;
+
+mod private {
+ pub struct Quz;
+}
+
+#[doc(hidden)]
+pub mod hidden {
+ pub struct Bar;
+}
+
+#[macro_export]
+macro_rules! foo {
+ () => {}
+}
diff --git a/tests/rustdoc/redirect-rename.rs b/tests/rustdoc/redirect-rename.rs
new file mode 100644
index 000000000..504c0687c
--- /dev/null
+++ b/tests/rustdoc/redirect-rename.rs
@@ -0,0 +1,34 @@
+#![crate_name = "foo"]
+
+mod hidden {
+ // @has foo/hidden/struct.Foo.html
+ // @has - '//p/a' '../../foo/struct.FooBar.html'
+ pub struct Foo {}
+ pub union U { a: usize }
+ pub enum Empty {}
+ pub const C: usize = 1;
+ pub static S: usize = 1;
+
+ // @has foo/hidden/bar/index.html
+ // @has - '//p/a' '../../foo/baz/index.html'
+ pub mod bar {
+ // @has foo/hidden/bar/struct.Thing.html
+ // @has - '//p/a' '../../foo/baz/struct.Thing.html'
+ pub struct Thing {}
+ }
+}
+
+// @has foo/struct.FooBar.html
+pub use hidden::Foo as FooBar;
+// @has foo/union.FooU.html
+pub use hidden::U as FooU;
+// @has foo/enum.FooEmpty.html
+pub use hidden::Empty as FooEmpty;
+// @has foo/constant.FooC.html
+pub use hidden::C as FooC;
+// @has foo/static.FooS.html
+pub use hidden::S as FooS;
+
+// @has foo/baz/index.html
+// @has foo/baz/struct.Thing.html
+pub use hidden::bar as baz;
diff --git a/tests/rustdoc/redirect.rs b/tests/rustdoc/redirect.rs
new file mode 100644
index 000000000..e3a14c7a7
--- /dev/null
+++ b/tests/rustdoc/redirect.rs
@@ -0,0 +1,39 @@
+// aux-build:reexp-stripped.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate reexp_stripped;
+
+pub trait Foo {}
+
+// @has redirect/index.html
+// @has - '//code' 'pub use reexp_stripped::Bar'
+// @has - '//code/a' 'Bar'
+// @has reexp_stripped/hidden/struct.Bar.html
+// @has - '//p/a' '../../reexp_stripped/struct.Bar.html'
+// @has 'reexp_stripped/struct.Bar.html'
+#[doc(no_inline)]
+pub use reexp_stripped::Bar;
+impl Foo for Bar {}
+
+// @has redirect/index.html
+// @has - '//code' 'pub use reexp_stripped::Quz'
+// @has - '//code/a' 'Quz'
+// @has reexp_stripped/private/struct.Quz.html
+// @has - '//p/a' '../../reexp_stripped/struct.Quz.html'
+// @has 'reexp_stripped/struct.Quz.html'
+#[doc(no_inline)]
+pub use reexp_stripped::Quz;
+impl Foo for Quz {}
+
+mod private_no_inline {
+ pub struct Qux;
+ impl ::Foo for Qux {}
+}
+
+// @has redirect/index.html
+// @has - '//code' 'pub use private_no_inline::Qux'
+// @!has - '//a' 'Qux'
+// @!has redirect/struct.Qux.html
+#[doc(no_inline)]
+pub use private_no_inline::Qux;
diff --git a/tests/rustdoc/reexport-check.rs b/tests/rustdoc/reexport-check.rs
new file mode 100644
index 000000000..db1f90c69
--- /dev/null
+++ b/tests/rustdoc/reexport-check.rs
@@ -0,0 +1,18 @@
+// aux-build:reexport-check.rs
+#![crate_name = "foo"]
+
+extern crate reexport_check;
+
+// @!has 'foo/index.html' '//code' 'pub use self::i32;'
+// @has 'foo/index.html' '//div[@class="item-left deprecated module-item"]' 'i32'
+// @has 'foo/i32/index.html'
+#[allow(deprecated, deprecated_in_future)]
+pub use std::i32;
+// @!has 'foo/index.html' '//code' 'pub use self::string::String;'
+// @has 'foo/index.html' '//div[@class="item-left module-item"]' 'String'
+pub use std::string::String;
+
+// @has 'foo/index.html' '//div[@class="item-right docblock-short"]' 'Docs in original'
+// this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment
+#[doc(inline)]
+pub use reexport_check::S;
diff --git a/tests/rustdoc/reexport-dep-foreign-fn.rs b/tests/rustdoc/reexport-dep-foreign-fn.rs
new file mode 100644
index 000000000..6694c91d1
--- /dev/null
+++ b/tests/rustdoc/reexport-dep-foreign-fn.rs
@@ -0,0 +1,12 @@
+// aux-build:all-item-types.rs
+
+// This test is to ensure there is no problem on handling foreign functions
+// coming from a dependency.
+
+#![crate_name = "foo"]
+
+extern crate all_item_types;
+
+// @has 'foo/fn.foo_ffn.html'
+// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+pub use all_item_types::foo_ffn;
diff --git a/tests/rustdoc/reexport-doc-hidden.rs b/tests/rustdoc/reexport-doc-hidden.rs
new file mode 100644
index 000000000..3ea5fde72
--- /dev/null
+++ b/tests/rustdoc/reexport-doc-hidden.rs
@@ -0,0 +1,26 @@
+// Part of <https://github.com/rust-lang/rust/issues/59368>.
+// This test ensures that reexporting a `doc(hidden)` item will
+// still show the reexport.
+
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub type Type = u32;
+
+// @has 'foo/index.html'
+// @has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;'
+pub use crate::Type as Type2;
+
+// @count - '//*[@id="reexport.Type3"]' 0
+#[doc(hidden)]
+pub use crate::Type as Type3;
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! foo {
+ () => {};
+}
+
+// This is a bug: https://github.com/rust-lang/rust/issues/59368
+// @!has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+pub use crate::foo as Macro;
diff --git a/tests/rustdoc/reexport-doc.rs b/tests/rustdoc/reexport-doc.rs
new file mode 100644
index 000000000..df2c889b4
--- /dev/null
+++ b/tests/rustdoc/reexport-doc.rs
@@ -0,0 +1,8 @@
+// aux-build:reexport-doc-aux.rs
+
+extern crate reexport_doc_aux as dep;
+
+// @has 'reexport_doc/struct.Foo.html'
+// @count - '//p' 'These are the docs for Foo.' 1
+/// These are the docs for Foo.
+pub use dep::Foo;
diff --git a/tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs b/tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs
new file mode 100644
index 000000000..a79d05904
--- /dev/null
+++ b/tests/rustdoc/reexport-stability-tags-deprecated-and-portability.rs
@@ -0,0 +1,48 @@
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+pub mod tag {
+ #[deprecated(since = "0.1.8", note = "Use bar() instead")]
+ pub trait Deprecated {}
+
+ #[doc(cfg(feature = "sync"))]
+ pub trait Portability {}
+
+ #[deprecated(since = "0.1.8", note = "Use bar() instead")]
+ #[doc(cfg(feature = "sync"))]
+ pub trait Both {}
+
+ pub trait None {}
+}
+
+// @has foo/mod1/index.html
+pub mod mod1 {
+ // @has - '//code' 'pub use tag::Deprecated;'
+ // @has - '//span' 'Deprecated'
+ // @!has - '//span' 'sync'
+ pub use tag::Deprecated;
+}
+
+// @has foo/mod2/index.html
+pub mod mod2 {
+ // @has - '//code' 'pub use tag::Portability;'
+ // @!has - '//span' 'Deprecated'
+ // @has - '//span' 'sync'
+ pub use tag::Portability;
+}
+
+// @has foo/mod3/index.html
+pub mod mod3 {
+ // @has - '//code' 'pub use tag::Both;'
+ // @has - '//span' 'Deprecated'
+ // @has - '//span' 'sync'
+ pub use tag::Both;
+}
+
+// @has foo/mod4/index.html
+pub mod mod4 {
+ // @has - '//code' 'pub use tag::None;'
+ // @!has - '//span' 'Deprecated'
+ // @!has - '//span' 'sync'
+ pub use tag::None;
+}
diff --git a/tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs b/tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs
new file mode 100644
index 000000000..ff8a910f5
--- /dev/null
+++ b/tests/rustdoc/reexport-stability-tags-unstable-and-portability.rs
@@ -0,0 +1,61 @@
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod tag {
+ #[unstable(feature = "humans", issue = "none")]
+ pub trait Unstable {}
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(cfg(feature = "sync"))]
+ pub trait Portability {}
+
+ #[unstable(feature = "humans", issue = "none")]
+ #[doc(cfg(feature = "sync"))]
+ pub trait Both {}
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait None {}
+}
+
+// @has foo/mod1/index.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod mod1 {
+ // @has - '//code' 'pub use tag::Unstable;'
+ // @has - '//span' 'Experimental'
+ // @!has - '//span' 'sync'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub use tag::Unstable;
+}
+
+// @has foo/mod2/index.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod mod2 {
+ // @has - '//code' 'pub use tag::Portability;'
+ // @!has - '//span' 'Experimental'
+ // @has - '//span' 'sync'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub use tag::Portability;
+}
+
+// @has foo/mod3/index.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod mod3 {
+ // @has - '//code' 'pub use tag::Both;'
+ // @has - '//span' 'Experimental'
+ // @has - '//span' 'sync'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub use tag::Both;
+}
+
+// @has foo/mod4/index.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod mod4 {
+ // @has - '//code' 'pub use tag::None;'
+ // @!has - '//span' 'Experimental'
+ // @!has - '//span' 'sync'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub use tag::None;
+}
diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs
new file mode 100644
index 000000000..35c90ba5d
--- /dev/null
+++ b/tests/rustdoc/reexports-priv.rs
@@ -0,0 +1,135 @@
+// aux-build: reexports.rs
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+pub use reexports::addr_of;
+// @!has 'foo/macro.addr_of_crate.html'
+pub(crate) use reexports::addr_of_crate;
+// @!has 'foo/macro.addr_of_self.html'
+pub(self) use reexports::addr_of_self;
+// @!has 'foo/macro.addr_of_local.html'
+use reexports::addr_of_local;
+
+// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @!has 'foo/struct.FooCrate.html'
+pub(crate) use reexports::FooCrate;
+// @!has 'foo/struct.FooSelf.html'
+pub(self) use reexports::FooSelf;
+// @!has 'foo/struct.FooLocal.html'
+use reexports::FooLocal;
+
+// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @!has 'foo/enum.BarCrate.html'
+pub(crate) use reexports::BarCrate;
+// @!has 'foo/enum.BarSelf.html'
+pub(self) use reexports::BarSelf;
+// @!has 'foo/enum.BarLocal.html'
+use reexports::BarLocal;
+
+// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+pub use reexports::foo;
+// @!has 'foo/fn.foo_crate.html'
+pub(crate) use reexports::foo_crate;
+// @!has 'foo/fn.foo_self.html'
+pub(self) use reexports::foo_self;
+// @!has 'foo/fn.foo_local.html'
+use reexports::foo_local;
+
+// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+pub use reexports::Type;
+// @!has 'foo/type.TypeCrate.html'
+pub(crate) use reexports::TypeCrate;
+// @!has 'foo/type.TypeSelf.html'
+pub(self) use reexports::TypeSelf;
+// @!has 'foo/type.TypeLocal.html'
+use reexports::TypeLocal;
+
+// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @!has 'foo/union.UnionCrate.html'
+pub(crate) use reexports::UnionCrate;
+// @!has 'foo/union.UnionSelf.html'
+pub(self) use reexports::UnionSelf;
+// @!has 'foo/union.UnionLocal.html'
+use reexports::UnionLocal;
+
+pub mod outer {
+ pub mod inner {
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ pub use reexports::addr_of;
+ // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+ pub(crate) use reexports::addr_of_crate;
+ // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+ pub(super) use reexports::addr_of_super;
+ // @!has 'foo/outer/inner/macro.addr_of_self.html'
+ pub(self) use reexports::addr_of_self;
+ // @!has 'foo/outer/inner/macro.addr_of_local.html'
+ use reexports::addr_of_local;
+
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ pub use reexports::Foo;
+ // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
+ pub(crate) use reexports::FooCrate;
+ // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
+ pub(super) use reexports::FooSuper;
+ // @!has 'foo/outer/inner/struct.FooSelf.html'
+ pub(self) use reexports::FooSelf;
+ // @!has 'foo/outer/inner/struct.FooLocal.html'
+ use reexports::FooLocal;
+
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ pub use reexports::Bar;
+ // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
+ pub(crate) use reexports::BarCrate;
+ // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
+ pub(super) use reexports::BarSuper;
+ // @!has 'foo/outer/inner/enum.BarSelf.html'
+ pub(self) use reexports::BarSelf;
+ // @!has 'foo/outer/inner/enum.BarLocal.html'
+ use reexports::BarLocal;
+
+ // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ pub use reexports::foo;
+ // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
+ pub(crate) use reexports::foo_crate;
+ // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) fn foo_super()'
+ pub(super) use::reexports::foo_super;
+ // @!has 'foo/outer/inner/fn.foo_self.html'
+ pub(self) use reexports::foo_self;
+ // @!has 'foo/outer/inner/fn.foo_local.html'
+ use reexports::foo_local;
+
+ // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ pub use reexports::Type;
+ // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
+ pub(crate) use reexports::TypeCrate;
+ // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
+ pub(super) use reexports::TypeSuper;
+ // @!has 'foo/outer/inner/type.TypeSelf.html'
+ pub(self) use reexports::TypeSelf;
+ // @!has 'foo/outer/inner/type.TypeLocal.html'
+ use reexports::TypeLocal;
+
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ pub use reexports::Union;
+ // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
+ pub(crate) use reexports::UnionCrate;
+ // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="item-decl"]' 'pub(in outer) union UnionSuper {'
+ pub(super) use reexports::UnionSuper;
+ // @!has 'foo/outer/inner/union.UnionSelf.html'
+ pub(self) use reexports::UnionSelf;
+ // @!has 'foo/outer/inner/union.UnionLocal.html'
+ use reexports::UnionLocal;
+ }
+}
+
+mod re_re_exports {
+ // @!has 'foo/re_re_exports/union.Union.html'
+ use crate::reexports::Union;
+}
diff --git a/tests/rustdoc/reexports.rs b/tests/rustdoc/reexports.rs
new file mode 100644
index 000000000..65d305c6d
--- /dev/null
+++ b/tests/rustdoc/reexports.rs
@@ -0,0 +1,129 @@
+// aux-build: reexports.rs
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+pub use reexports::addr_of;
+// @!has 'foo/macro.addr_of_crate.html'
+pub(crate) use reexports::addr_of_crate;
+// @!has 'foo/macro.addr_of_self.html'
+pub(self) use reexports::addr_of_self;
+// @!has 'foo/macro.addr_of_local.html'
+use reexports::addr_of_local;
+
+// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @!has 'foo/struct.FooCrate.html'
+pub(crate) use reexports::FooCrate;
+// @!has 'foo/struct.FooSelf.html'
+pub(self) use reexports::FooSelf;
+// @!has 'foo/struct.FooLocal.html'
+use reexports::FooLocal;
+
+// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @!has 'foo/enum.BarCrate.html'
+pub(crate) use reexports::BarCrate;
+// @!has 'foo/enum.BarSelf.html'
+pub(self) use reexports::BarSelf;
+// @!has 'foo/enum.BarLocal.html'
+use reexports::BarLocal;
+
+// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+pub use reexports::foo;
+// @!has 'foo/fn.foo_crate.html'
+pub(crate) use reexports::foo_crate;
+// @!has 'foo/fn.foo_self.html'
+pub(self) use reexports::foo_self;
+// @!has 'foo/fn.foo_local.html'
+use reexports::foo_local;
+
+// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+pub use reexports::Type;
+// @!has 'foo/type.TypeCrate.html'
+pub(crate) use reexports::TypeCrate;
+// @!has 'foo/type.TypeSelf.html'
+pub(self) use reexports::TypeSelf;
+// @!has 'foo/type.TypeLocal.html'
+use reexports::TypeLocal;
+
+// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @!has 'foo/union.UnionCrate.html'
+pub(crate) use reexports::UnionCrate;
+// @!has 'foo/union.UnionSelf.html'
+pub(self) use reexports::UnionSelf;
+// @!has 'foo/union.UnionLocal.html'
+use reexports::UnionLocal;
+
+pub mod outer {
+ pub mod inner {
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ pub use reexports::addr_of;
+ // @!has 'foo/outer/inner/macro.addr_of_crate.html'
+ pub(crate) use reexports::addr_of_crate;
+ // @!has 'foo/outer/inner/macro.addr_of_super.html'
+ pub(super) use reexports::addr_of_super;
+ // @!has 'foo/outer/inner/macro.addr_of_self.html'
+ pub(self) use reexports::addr_of_self;
+ // @!has 'foo/outer/inner/macro.addr_of_local.html'
+ use reexports::addr_of_local;
+
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ pub use reexports::Foo;
+ // @!has 'foo/outer/inner/struct.FooCrate.html'
+ pub(crate) use reexports::FooCrate;
+ // @!has 'foo/outer/inner/struct.FooSuper.html'
+ pub(super) use reexports::FooSuper;
+ // @!has 'foo/outer/inner/struct.FooSelf.html'
+ pub(self) use reexports::FooSelf;
+ // @!has 'foo/outer/inner/struct.FooLocal.html'
+ use reexports::FooLocal;
+
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ pub use reexports::Bar;
+ // @!has 'foo/outer/inner/enum.BarCrate.html'
+ pub(crate) use reexports::BarCrate;
+ // @!has 'foo/outer/inner/enum.BarSuper.html'
+ pub(super) use reexports::BarSuper;
+ // @!has 'foo/outer/inner/enum.BarSelf.html'
+ pub(self) use reexports::BarSelf;
+ // @!has 'foo/outer/inner/enum.BarLocal.html'
+ use reexports::BarLocal;
+
+ // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ pub use reexports::foo;
+ // @!has 'foo/outer/inner/fn.foo_crate.html'
+ pub(crate) use reexports::foo_crate;
+ // @!has 'foo/outer/inner/fn.foo_super.html'
+ pub(super) use::reexports::foo_super;
+ // @!has 'foo/outer/inner/fn.foo_self.html'
+ pub(self) use reexports::foo_self;
+ // @!has 'foo/outer/inner/fn.foo_local.html'
+ use reexports::foo_local;
+
+ // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ pub use reexports::Type;
+ // @!has 'foo/outer/inner/type.TypeCrate.html'
+ pub(crate) use reexports::TypeCrate;
+ // @!has 'foo/outer/inner/type.TypeSuper.html'
+ pub(super) use reexports::TypeSuper;
+ // @!has 'foo/outer/inner/type.TypeSelf.html'
+ pub(self) use reexports::TypeSelf;
+ // @!has 'foo/outer/inner/type.TypeLocal.html'
+ use reexports::TypeLocal;
+
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ pub use reexports::Union;
+ // @!has 'foo/outer/inner/union.UnionCrate.html'
+ pub(crate) use reexports::UnionCrate;
+ // @!has 'foo/outer/inner/union.UnionSuper.html'
+ pub(super) use reexports::UnionSuper;
+ // @!has 'foo/outer/inner/union.UnionSelf.html'
+ pub(self) use reexports::UnionSelf;
+ // @!has 'foo/outer/inner/union.UnionLocal.html'
+ use reexports::UnionLocal;
+ }
+}
diff --git a/tests/rustdoc/remove-duplicates.rs b/tests/rustdoc/remove-duplicates.rs
new file mode 100644
index 000000000..759bf84db
--- /dev/null
+++ b/tests/rustdoc/remove-duplicates.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+mod foo {
+ pub use bar::*;
+ pub mod bar {
+ pub trait Foo {
+ fn foo();
+ }
+ }
+}
+
+// @count foo/index.html '//*[@class="trait"]' 1
+pub use foo::bar::*;
+pub use foo::*;
diff --git a/tests/rustdoc/remove-url-from-headings.rs b/tests/rustdoc/remove-url-from-headings.rs
new file mode 100644
index 000000000..599c429a6
--- /dev/null
+++ b/tests/rustdoc/remove-url-from-headings.rs
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @!has - '//a[@href="http://a.a"]' ''
+// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
+// @has - '//a[@href="#another-one-urg"]' 'Another one urg'
+
+/// fooo
+///
+/// # Implementing [stuff](http://a.a "title") somewhere
+///
+/// hello
+///
+/// # Another [one][two] urg
+///
+/// [two]: http://a.a
+pub fn foo() {}
diff --git a/tests/rustdoc/return-impl-trait.rs b/tests/rustdoc/return-impl-trait.rs
new file mode 100644
index 000000000..1ccf5ac46
--- /dev/null
+++ b/tests/rustdoc/return-impl-trait.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait Backend {}
+
+impl Backend for () {}
+
+pub struct Module<T>(T);
+
+pub type BackendImpl = impl Backend;
+
+// @has return_impl_trait/fn.make_module.html
+/// Documentation
+pub fn make_module() -> Module<BackendImpl> {
+ Module(())
+}
diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs
new file mode 100644
index 000000000..a229a4e29
--- /dev/null
+++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs
@@ -0,0 +1,70 @@
+// Test that we do not currently display `~const` in rustdoc
+// as that syntax is currently provisional; `~const Destruct` has
+// no effect on stable code so it should be hidden as well.
+//
+// To future blessers: make sure that `const_trait_impl` is
+// stabilized when changing `@!has` to `@has`, and please do
+// not remove this test.
+#![feature(const_trait_impl)]
+#![crate_name = "foo"]
+
+use std::marker::Destruct;
+
+pub struct S<T>(T);
+
+// @!has foo/trait.Tr.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' '~const'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' ': Clone'
+#[const_trait]
+pub trait Tr<T> {
+ // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
+ // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+ // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+ // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+ fn a<A: ~const Clone + ~const Destruct>()
+ where
+ Option<A>: ~const Clone + ~const Destruct,
+ {
+ }
+}
+
+// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]' ''
+// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]' '~const'
+// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Clone'
+// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const'
+// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+impl<T: ~const Clone + ~const Destruct> const Tr<T> for T
+where
+ Option<T>: ~const Clone + ~const Destruct,
+{
+ fn a<A: ~const Clone + ~const Destruct>()
+ where
+ Option<A>: ~const Clone + ~const Destruct,
+ {
+ }
+}
+
+// @!has foo/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' '~const'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' ': Clone'
+pub const fn foo<F: ~const Clone + ~const Destruct>()
+where
+ Option<F>: ~const Clone + ~const Destruct,
+{
+ F::a()
+}
+
+impl<T> S<T> {
+ // @!has foo/struct.S.html '//section[@id="method.foo"]/h4[@class="code-header"]' '~const'
+ // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+ // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+ // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+ pub const fn foo<B, C: ~const Clone + ~const Destruct>()
+ where
+ B: ~const Clone + ~const Destruct,
+ {
+ B::a()
+ }
+}
diff --git a/tests/rustdoc/rustc-incoherent-impls.rs b/tests/rustdoc/rustc-incoherent-impls.rs
new file mode 100644
index 000000000..3fdefbecc
--- /dev/null
+++ b/tests/rustdoc/rustc-incoherent-impls.rs
@@ -0,0 +1,28 @@
+// aux-build:incoherent-impl-types.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+#![feature(rustc_attrs)]
+
+extern crate incoherent_impl_types;
+
+// The only way this actually shows up is if the type gets inlined.
+#[doc(inline)]
+pub use incoherent_impl_types::FooTrait;
+
+// @has foo/trait.FooTrait.html
+// @count - '//section[@id="method.do_something"]' 1
+impl dyn FooTrait {
+ #[rustc_allow_incoherent_impl]
+ pub fn do_something() {}
+}
+
+#[doc(inline)]
+pub use incoherent_impl_types::FooStruct;
+
+// @has foo/struct.FooStruct.html
+// @count - '//section[@id="method.do_something"]' 1
+impl FooStruct {
+ #[rustc_allow_incoherent_impl]
+ pub fn do_something() {}
+}
diff --git a/tests/rustdoc/rustc-macro-crate.rs b/tests/rustdoc/rustc-macro-crate.rs
new file mode 100644
index 000000000..dd5edc984
--- /dev/null
+++ b/tests/rustdoc/rustc-macro-crate.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn foo(input: TokenStream) -> TokenStream {
+ input
+}
diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs
new file mode 100644
index 000000000..0b65bf1df
--- /dev/null
+++ b/tests/rustdoc/safe-intrinsic.rs
@@ -0,0 +1,22 @@
+#![feature(intrinsics)]
+#![feature(no_core)]
+#![feature(rustc_attrs)]
+
+#![no_core]
+#![crate_name = "foo"]
+
+extern "rust-intrinsic" {
+ // @has 'foo/fn.abort.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+ #[rustc_safe_intrinsic]
+ pub fn abort() -> !;
+ // @has 'foo/fn.unreachable.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ pub fn unreachable() -> !;
+}
+
+extern "C" {
+ // @has 'foo/fn.needs_drop.html'
+ // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ pub fn needs_drop() -> !;
+}
diff --git a/tests/rustdoc/same-crate-hidden-impl-parameter.rs b/tests/rustdoc/same-crate-hidden-impl-parameter.rs
new file mode 100644
index 000000000..d55393af8
--- /dev/null
+++ b/tests/rustdoc/same-crate-hidden-impl-parameter.rs
@@ -0,0 +1,36 @@
+// test for `doc(hidden)` with impl parameters in the same crate.
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub enum HiddenType {}
+
+#[doc(hidden)]
+pub trait HiddenTrait {}
+
+pub enum MyLibType {}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From<HiddenType> for MyLibType'
+impl From<HiddenType> for MyLibType {
+ fn from(it: HiddenType) -> MyLibType {
+ match it {}
+ }
+}
+
+pub struct T<T>(T);
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From<T<T<T<T<HiddenType>>>>> for MyLibType'
+impl From<T<T<T<T<HiddenType>>>>> for MyLibType {
+ fn from(it: T<T<T<T<HiddenType>>>>) -> MyLibType {
+ todo!()
+ }
+}
+
+// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType'
+impl HiddenTrait for MyLibType {}
+
+// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From<MyLibType> for T<T<T<T<HiddenType>>>>'
+impl From<MyLibType> for T<T<T<T<HiddenType>>>> {
+ fn from(it: MyLibType) -> T<T<T<T<HiddenType>>>> {
+ match it {}
+ }
+}
diff --git a/tests/rustdoc/sanitizer-option.rs b/tests/rustdoc/sanitizer-option.rs
new file mode 100644
index 000000000..1abba468f
--- /dev/null
+++ b/tests/rustdoc/sanitizer-option.rs
@@ -0,0 +1,18 @@
+// needs-sanitizer-support
+// needs-sanitizer-address
+// compile-flags: --test -Z sanitizer=address
+//
+// #43031: Verify that rustdoc passes `-Z` options to rustc. Use an extern
+// function that is provided by the sanitizer runtime, if flag is not passed
+// correctly, then linking will fail.
+
+/// ```
+/// extern "C" {
+/// fn __sanitizer_print_stack_trace();
+/// }
+///
+/// fn main() {
+/// unsafe { __sanitizer_print_stack_trace() };
+/// }
+/// ```
+pub fn z_flag_is_passed_to_rustc() {}
diff --git a/tests/rustdoc/search-index-summaries.rs b/tests/rustdoc/search-index-summaries.rs
new file mode 100644
index 000000000..efd366405
--- /dev/null
+++ b/tests/rustdoc/search-index-summaries.rs
@@ -0,0 +1,10 @@
+#![crate_name = "foo"]
+
+// @hasraw 'search-index.js' 'Foo short link.'
+// @!hasraw - 'www.example.com'
+// @!hasraw - 'More Foo.'
+
+/// Foo short [link](https://www.example.com/).
+///
+/// More Foo.
+pub struct Foo;
diff --git a/tests/rustdoc/search-index.rs b/tests/rustdoc/search-index.rs
new file mode 100644
index 000000000..d1d05eb88
--- /dev/null
+++ b/tests/rustdoc/search-index.rs
@@ -0,0 +1,26 @@
+#![crate_name = "rustdoc_test"]
+
+use std::ops::Deref;
+
+// @hasraw search-index.js Foo
+pub use private::Foo;
+
+mod private {
+ pub struct Foo;
+ impl Foo {
+ pub fn test_method() {} // @hasraw - test_method
+ fn priv_method() {} // @!hasraw - priv_method
+ }
+
+ pub trait PrivateTrait {
+ fn trait_method(&self) {} // @!hasraw - priv_method
+ }
+}
+
+pub struct Bar;
+
+impl Deref for Bar {
+ // @!hasraw search-index.js Target
+ type Target = Bar;
+ fn deref(&self) -> &Bar { self }
+}
diff --git a/tests/rustdoc/short-docblock-codeblock.rs b/tests/rustdoc/short-docblock-codeblock.rs
new file mode 100644
index 000000000..3c5fa7b36
--- /dev/null
+++ b/tests/rustdoc/short-docblock-codeblock.rs
@@ -0,0 +1,10 @@
+#![crate_name = "foo"]
+
+// @count foo/index.html '//*[@class="item-right docblock-short"]' 0
+
+/// ```
+/// let x = 12;
+/// ```
+///
+/// Some text.
+pub fn foo() {}
diff --git a/tests/rustdoc/short-docblock.rs b/tests/rustdoc/short-docblock.rs
new file mode 100644
index 000000000..1a8a689be
--- /dev/null
+++ b/tests/rustdoc/short-docblock.rs
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]' 'fooo'
+// @!has foo/index.html '//*[@class="item-right docblock-short"]/h1' 'fooo'
+// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo'
+
+/// # fooo
+///
+/// foo
+pub fn foo() {}
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]' 'mooood'
+// @!has foo/index.html '//*[@class="item-right docblock-short"]/h2' 'mooood'
+// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood'
+
+/// ## mooood
+///
+/// foo mod
+pub mod foo {}
+
+// @has foo/index.html '//*[@class="item-right docblock-short"]/a[@href=\
+// "https://nougat.world"]/code' 'nougat'
+
+/// [`nougat`](https://nougat.world)
+pub struct Bar;
diff --git a/tests/rustdoc/short-line.md b/tests/rustdoc/short-line.md
new file mode 100644
index 000000000..eff713baa
--- /dev/null
+++ b/tests/rustdoc/short-line.md
@@ -0,0 +1,2 @@
+inc2
+x
diff --git a/tests/rustdoc/show-const-contents.rs b/tests/rustdoc/show-const-contents.rs
new file mode 100644
index 000000000..69e742ee7
--- /dev/null
+++ b/tests/rustdoc/show-const-contents.rs
@@ -0,0 +1,68 @@
+// Test that the contents of constants are displayed as part of the
+// documentation.
+
+// @hasraw show_const_contents/constant.CONST_S.html 'show this'
+// @!hasraw show_const_contents/constant.CONST_S.html '; //'
+pub const CONST_S: &'static str = "show this";
+
+// @hasraw show_const_contents/constant.CONST_I32.html '= 42;'
+// @!hasraw show_const_contents/constant.CONST_I32.html '; //'
+pub const CONST_I32: i32 = 42;
+
+// @hasraw show_const_contents/constant.CONST_I32_HEX.html '= 0x42;'
+// @!hasraw show_const_contents/constant.CONST_I32_HEX.html '; //'
+pub const CONST_I32_HEX: i32 = 0x42;
+
+// @hasraw show_const_contents/constant.CONST_NEG_I32.html '= -42;'
+// @!hasraw show_const_contents/constant.CONST_NEG_I32.html '; //'
+pub const CONST_NEG_I32: i32 = -42;
+
+// @hasraw show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '= 42i32;'
+// @!hasraw show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32'
+pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32;
+
+// @hasraw show_const_contents/constant.CONST_CALC_I32.html '= _; // 43i32'
+pub const CONST_CALC_I32: i32 = 42 + 1;
+
+// @!hasraw show_const_contents/constant.CONST_REF_I32.html '= &42;'
+// @!hasraw show_const_contents/constant.CONST_REF_I32.html '; //'
+pub const CONST_REF_I32: &'static i32 = &42;
+
+// @hasraw show_const_contents/constant.CONST_I32_MAX.html '= i32::MAX; // 2_147_483_647i32'
+pub const CONST_I32_MAX: i32 = i32::MAX;
+
+// @!hasraw show_const_contents/constant.UNIT.html '= ();'
+// @!hasraw show_const_contents/constant.UNIT.html '; //'
+pub const UNIT: () = ();
+
+pub struct MyType(i32);
+
+// @!hasraw show_const_contents/constant.MY_TYPE.html '= MyType(42);'
+// @!hasraw show_const_contents/constant.MY_TYPE.html '; //'
+pub const MY_TYPE: MyType = MyType(42);
+
+pub struct MyTypeWithStr(&'static str);
+
+// @!hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html '= MyTypeWithStr("show this");'
+// @!hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html '; //'
+pub const MY_TYPE_WITH_STR: MyTypeWithStr = MyTypeWithStr("show this");
+
+// @hasraw show_const_contents/constant.PI.html '= 3.14159265358979323846264338327950288f32;'
+// @hasraw show_const_contents/constant.PI.html '; // 3.14159274f32'
+pub use std::f32::consts::PI;
+
+// @hasraw show_const_contents/constant.MAX.html '= i32::MAX; // 2_147_483_647i32'
+#[allow(deprecated, deprecated_in_future)]
+pub use std::i32::MAX;
+
+macro_rules! int_module {
+ ($T:ident) => (
+ pub const MIN: $T = $T::MIN;
+ )
+}
+
+// @hasraw show_const_contents/constant.MIN.html '= i16::MIN; // -32_768i16'
+int_module!(i16);
+
+// @has show_const_contents/constant.ESCAPE.html //pre '= r#"<script>alert("ESCAPE");</script>"#;'
+pub const ESCAPE: &str = r#"<script>alert("ESCAPE");</script>"#;
diff --git a/tests/rustdoc/sidebar-all-page.rs b/tests/rustdoc/sidebar-all-page.rs
new file mode 100644
index 000000000..e74b981de
--- /dev/null
+++ b/tests/rustdoc/sidebar-all-page.rs
@@ -0,0 +1,35 @@
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+// @has 'foo/all.html'
+// @has - '//*[@class="sidebar-elems"]//li' 'Structs'
+// @has - '//*[@class="sidebar-elems"]//li' 'Enums'
+// @has - '//*[@class="sidebar-elems"]//li' 'Unions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Functions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Traits'
+// @has - '//*[@class="sidebar-elems"]//li' 'Macros'
+// @has - '//*[@class="sidebar-elems"]//li' 'Type Definitions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Constants'
+// @has - '//*[@class="sidebar-elems"]//li' 'Statics'
+// @has - '//*[@class="sidebar-elems"]//li' 'Primitive Types'
+
+pub struct Foo;
+pub enum Enum {
+ A,
+}
+pub union Bar {
+ a: u8,
+ b: u16,
+}
+pub fn foo() {}
+pub trait Trait {}
+#[macro_export]
+macro_rules! foo {
+ () => {}
+}
+pub type Type = u8;
+pub const FOO: u8 = 0;
+pub static BAR: u8 = 0;
+#[doc(primitive = "u8")]
+mod u8 {}
diff --git a/tests/rustdoc/sidebar-items.rs b/tests/rustdoc/sidebar-items.rs
new file mode 100644
index 000000000..6f7afa59b
--- /dev/null
+++ b/tests/rustdoc/sidebar-items.rs
@@ -0,0 +1,56 @@
+#![feature(associated_type_defaults)]
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-methods"]' 'Required Methods'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'bar'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-methods"]' 'Provided Methods'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'foo'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-consts"]' 'Required Associated Constants'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'FOO'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-consts"]' 'Provided Associated Constants'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'BAR'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-types"]' 'Required Associated Types'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'Output'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'Extra'
+pub trait Foo {
+ const FOO: usize;
+ const BAR: u32 = 0;
+ type Extra: Copy = ();
+ type Output: ?Sized;
+
+ fn foo() {}
+ fn bar() -> Self::Output;
+}
+
+// @has foo/struct.Bar.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u'
+// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
+pub struct Bar {
+ pub f: u32,
+ pub u: u32,
+ waza: u32,
+}
+
+// @has foo/enum.En.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'Foo'
+// @has - '//*[@class="sidebar-elems"]//section//a' 'Bar'
+pub enum En {
+ Foo,
+ Bar,
+}
+
+// @has foo/union.MyUnion.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2'
+// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
+pub union MyUnion {
+ pub f1: u32,
+ pub f2: f32,
+ waza: u32,
+}
diff --git a/tests/rustdoc/sidebar-link-generation.rs b/tests/rustdoc/sidebar-link-generation.rs
new file mode 100644
index 000000000..7858f35a2
--- /dev/null
+++ b/tests/rustdoc/sidebar-link-generation.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.SomeStruct.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.some_fn-1"]' \
+// "some_fn"
+pub struct SomeStruct<T> { _inner: T }
+
+impl SomeStruct<()> {
+ pub fn some_fn(&self) {}
+}
+
+impl SomeStruct<usize> {
+ pub fn some_fn(&self) {}
+}
diff --git a/tests/rustdoc/sidebar-links-to-foreign-impl.rs b/tests/rustdoc/sidebar-links-to-foreign-impl.rs
new file mode 100644
index 000000000..11e946948
--- /dev/null
+++ b/tests/rustdoc/sidebar-links-to-foreign-impl.rs
@@ -0,0 +1,16 @@
+// issue #56018: "Implementations on Foreign Types" sidebar items should link to specific impls
+
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
+// @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32'
+// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
+// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header"]' "impl<'a> Foo for &'a str"
+pub trait Foo {}
+
+impl Foo for u32 {}
+
+impl<'a> Foo for &'a str {}
diff --git a/tests/rustdoc/sized_trait.rs b/tests/rustdoc/sized_trait.rs
new file mode 100644
index 000000000..feef4de8d
--- /dev/null
+++ b/tests/rustdoc/sized_trait.rs
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Bar.html
+// @!has - '//*[@id="impl-Sized"]' ''
+pub struct Bar {
+ a: u16,
+}
+
+// @has foo/struct.Foo.html
+// @!has - '//*[@id="impl-Sized"]' ''
+pub struct Foo<T: ?Sized>(T);
+
+// @has foo/struct.Unsized.html
+// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header"]' 'impl !Sized for Unsized'
+pub struct Unsized {
+ data: [u8],
+}
diff --git a/tests/rustdoc/slice-links.link_box_generic.html b/tests/rustdoc/slice-links.link_box_generic.html
new file mode 100644
index 000000000..38aaf2080
--- /dev/null
+++ b/tests/rustdoc/slice-links.link_box_generic.html
@@ -0,0 +1 @@
+<code>pub fn delta&lt;T&gt;() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;<a class="primitive" href="{{channel}}/core/primitive.slice.html">[T]</a>&gt;</code> \ No newline at end of file
diff --git a/tests/rustdoc/slice-links.link_box_u32.html b/tests/rustdoc/slice-links.link_box_u32.html
new file mode 100644
index 000000000..7bec7582d
--- /dev/null
+++ b/tests/rustdoc/slice-links.link_box_u32.html
@@ -0,0 +1 @@
+<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>]&gt;</code> \ No newline at end of file
diff --git a/tests/rustdoc/slice-links.link_slice_generic.html b/tests/rustdoc/slice-links.link_slice_generic.html
new file mode 100644
index 000000000..1d0f2bf75
--- /dev/null
+++ b/tests/rustdoc/slice-links.link_slice_generic.html
@@ -0,0 +1 @@
+<code>pub fn beta&lt;T&gt;() -&gt; &amp;'static <a class="primitive" href="{{channel}}/core/primitive.slice.html">[T]</a></code> \ No newline at end of file
diff --git a/tests/rustdoc/slice-links.link_slice_u32.html b/tests/rustdoc/slice-links.link_slice_u32.html
new file mode 100644
index 000000000..c86d38304
--- /dev/null
+++ b/tests/rustdoc/slice-links.link_slice_u32.html
@@ -0,0 +1 @@
+<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>]</code> \ No newline at end of file
diff --git a/tests/rustdoc/slice-links.rs b/tests/rustdoc/slice-links.rs
new file mode 100644
index 000000000..67137fdca
--- /dev/null
+++ b/tests/rustdoc/slice-links.rs
@@ -0,0 +1,28 @@
+#![crate_name = "foo"]
+#![no_std]
+
+pub struct MyBox<T: ?Sized>(*const T);
+
+// @has 'foo/fn.alpha.html'
+// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn alpha() -> &'static [u32] {
+ loop {}
+}
+
+// @has 'foo/fn.beta.html'
+// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn beta<T>() -> &'static [T] {
+ loop {}
+}
+
+// @has 'foo/fn.gamma.html'
+// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn gamma() -> MyBox<[u32]> {
+ loop {}
+}
+
+// @has 'foo/fn.delta.html'
+// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn delta<T>() -> MyBox<[T]> {
+ loop {}
+}
diff --git a/tests/rustdoc/smart-punct.rs b/tests/rustdoc/smart-punct.rs
new file mode 100644
index 000000000..7ae5bd699
--- /dev/null
+++ b/tests/rustdoc/smart-punct.rs
@@ -0,0 +1,28 @@
+#![crate_name = "foo"]
+
+//! This is the "start" of the 'document'! How'd you know that "it's" the start?
+//!
+//! # Header with "smart punct'"
+//!
+//! [link with "smart punct'" -- yessiree!][]
+//!
+//! [link with "smart punct'" -- yessiree!]: https://www.rust-lang.org
+//!
+//! # Code should not be smart-punct'd
+//!
+//! `this inline code -- it shouldn't have "smart punct"`
+//!
+//! ```
+//! let x = "don't smart-punct me -- please!";
+//! ```
+//!
+//! ```text
+//! I say "don't smart-punct me -- please!"
+//! ```
+
+// @has "foo/index.html" "//p" "This is the “start” of the ‘document’! How’d you know that “it’s” the start?"
+// @has "foo/index.html" "//h2" "Header with “smart punct’”"
+// @has "foo/index.html" '//a[@href="https://www.rust-lang.org"]' "link with “smart punct’” – yessiree!"
+// @has "foo/index.html" '//code' "this inline code -- it shouldn't have \"smart punct\""
+// @has "foo/index.html" '//pre' "let x = \"don't smart-punct me -- please!\";"
+// @has "foo/index.html" '//pre' "I say \"don't smart-punct me -- please!\""
diff --git a/tests/rustdoc/smoke.rs b/tests/rustdoc/smoke.rs
new file mode 100644
index 000000000..c1ed3a0c9
--- /dev/null
+++ b/tests/rustdoc/smoke.rs
@@ -0,0 +1,25 @@
+// @has smoke/index.html
+
+//! Very docs
+
+// @has smoke/bar/index.html
+pub mod bar {
+
+ /// So correct
+ // @has smoke/bar/baz/index.html
+ pub mod baz {
+ /// Much detail
+ // @has smoke/bar/baz/fn.baz.html
+ pub fn baz() { }
+ }
+
+ /// *wow*
+ // @has smoke/bar/trait.Doge.html
+ pub trait Doge { fn dummy(&self) { } }
+
+ // @has smoke/bar/struct.Foo.html
+ pub struct Foo { x: isize, y: usize }
+
+ // @has smoke/bar/fn.prawns.html
+ pub fn prawns((a, b): (isize, usize), Foo { x, y }: Foo) { }
+}
diff --git a/tests/rustdoc/sort-modules-by-appearance.rs b/tests/rustdoc/sort-modules-by-appearance.rs
new file mode 100644
index 000000000..b5cc8bc83
--- /dev/null
+++ b/tests/rustdoc/sort-modules-by-appearance.rs
@@ -0,0 +1,13 @@
+// Tests the rustdoc --sort-modules-by-appearance option, that allows module declarations to appear
+// in the order they are declared in the source code, rather than only alphabetically.
+
+// compile-flags: -Z unstable-options --sort-modules-by-appearance
+
+pub mod module_b {}
+
+pub mod module_c {}
+
+pub mod module_a {}
+
+// @matchesraw 'sort_modules_by_appearance/index.html' '(?s)module_b.*module_c.*module_a'
+// @matchesraw 'sort_modules_by_appearance/sidebar-items.js' '"module_b".*"module_c".*"module_a"'
diff --git a/tests/rustdoc/source-file.rs b/tests/rustdoc/source-file.rs
new file mode 100644
index 000000000..4e1664790
--- /dev/null
+++ b/tests/rustdoc/source-file.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @hasraw source-files.js source-file.rs
+
+pub struct Foo;
diff --git a/tests/rustdoc/source-version-separator.rs b/tests/rustdoc/source-version-separator.rs
new file mode 100644
index 000000000..14580373b
--- /dev/null
+++ b/tests/rustdoc/source-version-separator.rs
@@ -0,0 +1,30 @@
+#![stable(feature = "bar", since = "1.0")]
+#![crate_name = "foo"]
+#![feature(staged_api)]
+
+// @has foo/trait.Bar.html
+// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
+#[stable(feature = "bar", since = "1.0")]
+pub trait Bar {
+ // @has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0 · source'
+ #[stable(feature = "foobar", since = "3.0")]
+ fn foo();
+}
+
+// @has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0 · source'
+
+// @has foo/struct.Foo.html
+// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
+#[stable(feature = "baz", since = "1.0")]
+pub struct Foo;
+
+impl Foo {
+ // @has - '//*[@id="method.foofoo"]/*[@class="rightside"]' '3.0 · source'
+ #[stable(feature = "foobar", since = "3.0")]
+ pub fn foofoo() {}
+}
+
+#[stable(feature = "yolo", since = "4.0")]
+impl Bar for Foo {
+ fn foo() {}
+}
diff --git a/tests/rustdoc/spotlight-from-dependency.odd.html b/tests/rustdoc/spotlight-from-dependency.odd.html
new file mode 100644
index 000000000..5f54b7522
--- /dev/null
+++ b/tests/rustdoc/spotlight-from-dependency.odd.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Odd":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\"&gt;Odd&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html\" title=\"trait core::iter::traits::iterator::Iterator\"&gt;Iterator&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\"&gt;Odd&lt;/a&gt;&lt;/span&gt;&lt;span class=\"where fmt-newline\"&gt; type &lt;a href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item\" class=\"associatedtype\"&gt;Item&lt;/a&gt; = &lt;a class=\"primitive\" href=\"{{channel}}/std/primitive.usize.html\"&gt;usize&lt;/a&gt;;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/spotlight-from-dependency.rs b/tests/rustdoc/spotlight-from-dependency.rs
new file mode 100644
index 000000000..090ad187d
--- /dev/null
+++ b/tests/rustdoc/spotlight-from-dependency.rs
@@ -0,0 +1,25 @@
+#![crate_name = "foo"]
+
+use std::iter::Iterator;
+
+// @has foo/struct.Odd.html
+// @has - '//*[@id="method.new"]//a[@class="notable-traits"]/@data-ty' 'Odd'
+// @snapshot odd - '//script[@id="notable-traits-data"]'
+pub struct Odd {
+ current: usize,
+}
+
+impl Odd {
+ pub fn new() -> Odd {
+ Odd { current: 1 }
+ }
+}
+
+impl Iterator for Odd {
+ type Item = usize;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.current += 2;
+ Some(self.current - 2)
+ }
+}
diff --git a/tests/rustdoc/src-links-auto-impls.rs b/tests/rustdoc/src-links-auto-impls.rs
new file mode 100644
index 000000000..953563833
--- /dev/null
+++ b/tests/rustdoc/src-links-auto-impls.rs
@@ -0,0 +1,12 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Unsized.html
+// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized'
+// @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="srclink"]' 'source'
+// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized'
+// @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source'
+// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header"]' 'impl<T> Any for T'
+// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink rightside"]' 'source'
+pub struct Unsized {
+ data: [u8],
+}
diff --git a/tests/rustdoc/src-links-external.rs b/tests/rustdoc/src-links-external.rs
new file mode 100644
index 000000000..8012e4422
--- /dev/null
+++ b/tests/rustdoc/src-links-external.rs
@@ -0,0 +1,13 @@
+// aux-build:src-links-external.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate src_links_external;
+
+// @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#1'
+#[doc(inline)]
+pub use src_links_external as bar;
+
+// @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#1'
diff --git a/tests/rustdoc/src-links.rs b/tests/rustdoc/src-links.rs
new file mode 100644
index 000000000..7a6c733d4
--- /dev/null
+++ b/tests/rustdoc/src-links.rs
@@ -0,0 +1,51 @@
+#![crate_name = "foo"]
+
+//! Dox
+// @has src/foo/src-links.rs.html
+// @has foo/index.html '//a/@href' '../src/foo/src-links.rs.html'
+
+#[path = "src-links/mod.rs"]
+pub mod qux;
+
+// @has src/foo/src-links.rs.html
+// @has foo/fizz/index.html '//a/@href' '../src/foo/src-links/fizz.rs.html'
+#[path = "src-links/../src-links/fizz.rs"]
+pub mod fizz;
+
+// @has foo/bar/index.html '//a/@href' '../../src/foo/src-links.rs.html'
+pub mod bar {
+
+ /// Dox
+ // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/src-links.rs.html'
+ pub mod baz {
+ /// Dox
+ // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/src-links.rs.html'
+ pub fn baz() { }
+ }
+
+ /// Dox
+ // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/src-links.rs.html'
+ pub trait Foobar { fn dummy(&self) { } }
+
+ // @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/src-links.rs.html'
+ pub struct Foo { x: i32, y: u32 }
+
+ // @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/src-links.rs.html'
+ pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+// @has foo/fn.modfn.html '//a/@href' '../src/foo/src-links.rs.html'
+pub fn modfn() { }
+
+// same hierarchy as above, but just for the submodule
+
+// @has src/foo/src-links/mod.rs.html
+// @has foo/qux/index.html '//a/@href' '../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/src-links/mod.rs.html'
+// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/src-links/mod.rs.html'
diff --git a/tests/rustdoc/src-links/compiletest-ignore-dir b/tests/rustdoc/src-links/compiletest-ignore-dir
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/rustdoc/src-links/compiletest-ignore-dir
diff --git a/tests/rustdoc/src-links/fizz.rs b/tests/rustdoc/src-links/fizz.rs
new file mode 100644
index 000000000..d2b76b1ce
--- /dev/null
+++ b/tests/rustdoc/src-links/fizz.rs
@@ -0,0 +1 @@
+pub struct Buzz;
diff --git a/tests/rustdoc/src-links/mod.rs b/tests/rustdoc/src-links/mod.rs
new file mode 100644
index 000000000..27b239681
--- /dev/null
+++ b/tests/rustdoc/src-links/mod.rs
@@ -0,0 +1,19 @@
+//! Dox
+pub mod bar {
+
+ /// Dox
+ pub mod baz {
+ /// Dox
+ pub fn baz() { }
+ }
+
+ /// Dox
+ pub trait Foobar { fn dummy(&self) { } }
+
+ pub struct Foo { x: i32, y: u32 }
+
+ pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+pub fn modfn() { }
diff --git a/tests/rustdoc/stability.rs b/tests/rustdoc/stability.rs
new file mode 100644
index 000000000..90be2050d
--- /dev/null
+++ b/tests/rustdoc/stability.rs
@@ -0,0 +1,12 @@
+#![feature(staged_api)]
+
+#![unstable(feature = "test", issue = "none")]
+
+pub struct Unstable {
+ // @has stability/struct.Unstable.html \
+ // '//span[@class="item-info"]//div[@class="stab unstable"]' \
+ // 'This is a nightly-only experimental API'
+ // @count stability/struct.Unstable.html '//span[@class="stab unstable"]' 0
+ pub foo: u32,
+ pub bar: u32,
+}
diff --git a/tests/rustdoc/static-root-path.rs b/tests/rustdoc/static-root-path.rs
new file mode 100644
index 000000000..86928b0fb
--- /dev/null
+++ b/tests/rustdoc/static-root-path.rs
@@ -0,0 +1,18 @@
+// compile-flags:-Z unstable-options --static-root-path /cache/
+
+// @has static_root_path/struct.SomeStruct.html
+// @matchesraw - '"/cache/main-'
+// @!matchesraw - '"\.\./main'
+// @matchesraw - 'data-root-path="\.\./"'
+// @!matchesraw - '"/cache/search-index\.js"'
+pub struct SomeStruct;
+
+// @has src/static_root_path/static-root-path.rs.html
+// @matchesraw - '"/cache/source-script-'
+// @!matchesraw - '"\.\./\.\./source-script'
+// @matchesraw - '"\.\./\.\./source-files.js"'
+// @!matchesraw - '"/cache/source-files\.js"'
+
+// @has settings.html
+// @matchesraw - '/cache/settings-'
+// @!matchesraw - '\../settings'
diff --git a/tests/rustdoc/static.rs b/tests/rustdoc/static.rs
new file mode 100644
index 000000000..90dafd8b3
--- /dev/null
+++ b/tests/rustdoc/static.rs
@@ -0,0 +1,12 @@
+// compile-flags: --document-private-items
+
+#![crate_type = "lib"]
+
+// @has static/static.FOO.html '//pre' 'static FOO: usize'
+static FOO: usize = 1;
+
+// @has static/static.BAR.html '//pre' 'pub static BAR: usize'
+pub static BAR: usize = 1;
+
+// @has static/static.BAZ.html '//pre' 'pub static mut BAZ: usize'
+pub static mut BAZ: usize = 1;
diff --git a/tests/rustdoc/strip-block-doc-comments-stars.docblock.html b/tests/rustdoc/strip-block-doc-comments-stars.docblock.html
new file mode 100644
index 000000000..22b0b5dc4
--- /dev/null
+++ b/tests/rustdoc/strip-block-doc-comments-stars.docblock.html
@@ -0,0 +1,2 @@
+<div class="docblock"><p>a</p>
+</div> \ No newline at end of file
diff --git a/tests/rustdoc/strip-block-doc-comments-stars.rs b/tests/rustdoc/strip-block-doc-comments-stars.rs
new file mode 100644
index 000000000..ca4c93f92
--- /dev/null
+++ b/tests/rustdoc/strip-block-doc-comments-stars.rs
@@ -0,0 +1,11 @@
+#![crate_name = "foo"]
+
+// The goal of this test is to ensure that it won't be generated as a list because
+// block doc comments can have their lines starting with a star.
+
+// @has foo/fn.foo.html
+// @snapshot docblock - '//*[@class="toggle top-doc"]//*[@class="docblock"]'
+/**
+ * a
+ */
+pub fn foo() {}
diff --git a/tests/rustdoc/strip-enum-variant.no-not-shown.html b/tests/rustdoc/strip-enum-variant.no-not-shown.html
new file mode 100644
index 000000000..782198956
--- /dev/null
+++ b/tests/rustdoc/strip-enum-variant.no-not-shown.html
@@ -0,0 +1 @@
+<ul class="block"><li><a href="#variant.Shown">Shown</a></li></ul> \ No newline at end of file
diff --git a/tests/rustdoc/strip-enum-variant.rs b/tests/rustdoc/strip-enum-variant.rs
new file mode 100644
index 000000000..8753a7dc6
--- /dev/null
+++ b/tests/rustdoc/strip-enum-variant.rs
@@ -0,0 +1,11 @@
+// @has strip_enum_variant/enum.MyThing.html
+// @has - '//code' 'Shown'
+// @!has - '//code' 'NotShown'
+// @has - '//code' '// some variants omitted'
+// Also check that `NotShown` isn't displayed in the sidebar.
+// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]'
+pub enum MyThing {
+ Shown,
+ #[doc(hidden)]
+ NotShown,
+}
diff --git a/tests/rustdoc/struct-arg-pattern.rs b/tests/rustdoc/struct-arg-pattern.rs
new file mode 100644
index 000000000..3bfb43a0b
--- /dev/null
+++ b/tests/rustdoc/struct-arg-pattern.rs
@@ -0,0 +1,10 @@
+#![crate_name = "foo"]
+
+struct BodyId {
+ hir_id: usize,
+}
+
+// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn body_owner(_: BodyId)'
+pub fn body_owner(BodyId { hir_id }: BodyId) {
+ // ...
+}
diff --git a/tests/rustdoc/struct-field.rs b/tests/rustdoc/struct-field.rs
new file mode 100644
index 000000000..998683bdd
--- /dev/null
+++ b/tests/rustdoc/struct-field.rs
@@ -0,0 +1,22 @@
+#![crate_name = "foo"]
+
+
+// @has foo/index.html '//*[@class="docblock"]/p/a[@href="struct.Foo.html#structfield.bar"]' 'Foo::bar'
+// @has foo/index.html '//*[@class="docblock"]/p/a[@href="union.Bar.html#structfield.foo"]' 'Bar::foo'
+// @has foo/index.html '//*[@class="docblock"]/p/a[@href="enum.Uniooon.html#variant.X"]' 'Uniooon::X'
+
+//! Test with [Foo::bar], [Bar::foo], [Uniooon::X]
+
+pub struct Foo {
+ pub bar: usize,
+}
+
+pub union Bar {
+ pub foo: u32,
+}
+
+pub enum Uniooon {
+ F,
+ X,
+ Y,
+}
diff --git a/tests/rustdoc/struct-implementations-title.rs b/tests/rustdoc/struct-implementations-title.rs
new file mode 100644
index 000000000..5468796f6
--- /dev/null
+++ b/tests/rustdoc/struct-implementations-title.rs
@@ -0,0 +1,9 @@
+#![crate_name = "foo"]
+
+pub struct Struc;
+
+// @has foo/struct.Struc.html
+// @has - '//*[@id="main-content"]/h2[@id="implementations"]' "Implementations"
+impl Struc {
+ pub const S: u64 = 0;
+}
diff --git a/tests/rustdoc/structfields.rs b/tests/rustdoc/structfields.rs
new file mode 100644
index 000000000..7e1cada4b
--- /dev/null
+++ b/tests/rustdoc/structfields.rs
@@ -0,0 +1,44 @@
+// @has structfields/struct.Foo.html
+pub struct Foo {
+ // @has - //pre "pub a: ()"
+ pub a: (),
+ // @has - //pre "/* private fields */"
+ // @!has - //pre "b: ()"
+ b: (),
+ // @!has - //pre "c: usize"
+ #[doc(hidden)]
+ c: usize,
+ // @has - //pre "pub d: usize"
+ pub d: usize,
+}
+
+// @has structfields/struct.Bar.html
+pub struct Bar {
+ // @has - //pre "pub a: ()"
+ pub a: (),
+ // @!has - //pre "/* private fields */"
+}
+
+// @has structfields/enum.Qux.html
+pub enum Qux {
+ Quz {
+ // @has - //pre "a: ()"
+ a: (),
+ // @!has - //pre "b: ()"
+ #[doc(hidden)]
+ b: (),
+ // @has - //pre "c: usize"
+ c: usize,
+ // @has - //pre "/* private fields */"
+ },
+}
+
+// @has structfields/struct.Baz.html //pre "pub struct Baz { /* private fields */ }"
+pub struct Baz {
+ x: u8,
+ #[doc(hidden)]
+ pub y: u8,
+}
+
+// @has structfields/struct.Quux.html //pre "pub struct Quux {}"
+pub struct Quux {}
diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs
new file mode 100644
index 000000000..7c6a38865
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/basic.rs
@@ -0,0 +1,8 @@
+// @has basic/struct.Foo.html
+// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
+// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
+// @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
+pub struct Foo<T> {
+ field: T,
+}
diff --git a/tests/rustdoc/synthetic_auto/complex.rs b/tests/rustdoc/synthetic_auto/complex.rs
new file mode 100644
index 000000000..43393c21f
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/complex.rs
@@ -0,0 +1,42 @@
+mod foo {
+ pub trait MyTrait<'a> {
+ type MyItem: ?Sized;
+ }
+
+ pub struct Inner<'a, Q, R: ?Sized> {
+ field: Q,
+ field3: &'a u8,
+ my_foo: Foo<Q>,
+ field2: R,
+ }
+
+ pub struct Outer<'a, T, K: ?Sized> {
+ my_inner: Inner<'a, T, K>,
+ }
+
+ pub struct Foo<T> {
+ myfield: T,
+ }
+}
+
+// @has complex/struct.NotOuter.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \
+// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
+
+pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
+
+unsafe impl<T> Send for Foo<T>
+where
+ T: NotMyTrait<'static>,
+{
+}
+
+unsafe impl<'a, Q, R: ?Sized> Send for NotInner<'a, Q, R>
+where
+ Q: NotMyTrait<'a>,
+ <Q as NotMyTrait<'a>>::MyItem: Copy,
+ R: for<'b> Fn((&'b bool, &'a u8)) -> &'b i8,
+ Foo<Q>: Send,
+{
+}
diff --git a/tests/rustdoc/synthetic_auto/crate-local.rs b/tests/rustdoc/synthetic_auto/crate-local.rs
new file mode 100644
index 000000000..ed01f63f9
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/crate-local.rs
@@ -0,0 +1,9 @@
+#![feature(auto_traits)]
+
+pub auto trait Banana {}
+
+// @has crate_local/struct.Peach.html
+// @has - '//h3[@class="code-header"]' 'impl Banana for Peach'
+// @has - '//h3[@class="code-header"]' 'impl Send for Peach'
+// @has - '//h3[@class="code-header"]' 'impl Sync for Peach'
+pub struct Peach;
diff --git a/tests/rustdoc/synthetic_auto/issue-72213-projection-lifetime.rs b/tests/rustdoc/synthetic_auto/issue-72213-projection-lifetime.rs
new file mode 100644
index 000000000..6f66b8e55
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/issue-72213-projection-lifetime.rs
@@ -0,0 +1,25 @@
+// Regression test for issue #72213
+// Tests that we don't ICE when we have projection predicates
+// in our initial ParamEnv
+
+pub struct Lines<'a, L>
+where
+ L: Iterator<Item = &'a ()>,
+{
+ words: std::iter::Peekable<Words<'a, L>>,
+}
+
+pub struct Words<'a, L> {
+ _m: std::marker::PhantomData<&'a L>,
+}
+
+impl<'a, L> Iterator for Words<'a, L>
+where
+ L: Iterator<Item = &'a ()>,
+{
+ type Item = ();
+
+ fn next(&mut self) -> Option<Self::Item> {
+ unimplemented!()
+ }
+}
diff --git a/tests/rustdoc/synthetic_auto/lifetimes.rs b/tests/rustdoc/synthetic_auto/lifetimes.rs
new file mode 100644
index 000000000..33170a844
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/lifetimes.rs
@@ -0,0 +1,19 @@
+pub struct Inner<'a, T: 'a> {
+ field: &'a T,
+}
+
+unsafe impl<'a, T> Send for Inner<'a, T>
+where
+ 'a: 'static,
+ T: for<'b> Fn(&'b bool) -> &'a u8,
+{}
+
+// @has lifetimes/struct.Foo.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
+//
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'c, K> Sync for Foo<'c, K>where K: Sync"
+pub struct Foo<'c, K: 'c> {
+ inner_field: Inner<'c, K>,
+}
diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs
new file mode 100644
index 000000000..77c04ad2a
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/manual.rs
@@ -0,0 +1,14 @@
+// @has manual/struct.Foo.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// 'impl<T> Sync for Foo<T>where T: Sync'
+//
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// 'impl<T> Send for Foo<T>'
+//
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 4
+pub struct Foo<T> {
+ field: T,
+}
+
+unsafe impl<T> Send for Foo<T> {}
diff --git a/tests/rustdoc/synthetic_auto/negative.rs b/tests/rustdoc/synthetic_auto/negative.rs
new file mode 100644
index 000000000..2c2c848a5
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/negative.rs
@@ -0,0 +1,13 @@
+pub struct Inner<T: Copy> {
+ field: *mut T,
+}
+
+// @has negative/struct.Outer.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Send for Outer<T>"
+//
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> !Sync for Outer<T>"
+pub struct Outer<T: Copy> {
+ inner_field: Inner<T>,
+}
diff --git a/tests/rustdoc/synthetic_auto/nested.rs b/tests/rustdoc/synthetic_auto/nested.rs
new file mode 100644
index 000000000..423bf115a
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/nested.rs
@@ -0,0 +1,19 @@
+pub struct Inner<T> {
+ field: T,
+}
+
+unsafe impl<T> Send for Inner<T>
+where
+ T: Copy,
+{
+}
+
+// @has nested/struct.Foo.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// 'impl<T> Send for Foo<T>where T: Copy'
+//
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// 'impl<T> Sync for Foo<T>where T: Sync'
+pub struct Foo<T> {
+ inner_field: Inner<T>,
+}
diff --git a/tests/rustdoc/synthetic_auto/no-redundancy.rs b/tests/rustdoc/synthetic_auto/no-redundancy.rs
new file mode 100644
index 000000000..59f336233
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/no-redundancy.rs
@@ -0,0 +1,16 @@
+pub struct Inner<T> {
+ field: T,
+}
+
+unsafe impl<T> Send for Inner<T>
+where
+ T: Copy + Send,
+{
+}
+
+// @has no_redundancy/struct.Outer.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> Send for Outer<T>where T: Send + Copy"
+pub struct Outer<T> {
+ inner_field: Inner<T>,
+}
diff --git a/tests/rustdoc/synthetic_auto/overflow.rs b/tests/rustdoc/synthetic_auto/overflow.rs
new file mode 100644
index 000000000..35a487c76
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/overflow.rs
@@ -0,0 +1,35 @@
+// Tests that we don't fail with an overflow error for certain
+// strange types
+// See https://github.com/rust-lang/rust/pull/72936#issuecomment-643676915
+
+pub trait Interner {
+ type InternedType;
+}
+
+struct RustInterner<'tcx> {
+ foo: &'tcx ()
+}
+
+impl<'tcx> Interner for RustInterner<'tcx> {
+ type InternedType = Box<TyData<Self>>;
+}
+
+enum TyData<I: Interner> {
+ FnDef(I::InternedType)
+}
+
+struct VariableKind<I: Interner>(I::InternedType);
+
+// @has overflow/struct.BoundVarsCollector.html
+// @has - '//h3[@class="code-header"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
+pub struct BoundVarsCollector<'tcx> {
+ val: VariableKind<RustInterner<'tcx>>
+}
+
+fn is_send<T: Send>() {}
+
+struct MyInterner<'tcx> {
+ val: &'tcx ()
+}
+
+fn main() {}
diff --git a/tests/rustdoc/synthetic_auto/project.rs b/tests/rustdoc/synthetic_auto/project.rs
new file mode 100644
index 000000000..558ff2add
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/project.rs
@@ -0,0 +1,34 @@
+pub struct Inner<'a, T: 'a> {
+ field: &'a T,
+}
+
+trait MyTrait {
+ type MyItem;
+}
+
+trait OtherTrait {}
+
+unsafe impl<'a, T> Send for Inner<'a, T>
+where
+ 'a: 'static,
+ T: MyTrait<MyItem = bool>,
+{
+}
+unsafe impl<'a, T> Sync for Inner<'a, T>
+where
+ 'a: 'static,
+ T: MyTrait,
+ <T as MyTrait>::MyItem: OtherTrait,
+{
+}
+
+// @has project/struct.Foo.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static"
+//
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
+// 'c: 'static,"
+pub struct Foo<'c, K: 'c> {
+ inner_field: Inner<'c, K>,
+}
diff --git a/tests/rustdoc/synthetic_auto/self-referential.rs b/tests/rustdoc/synthetic_auto/self-referential.rs
new file mode 100644
index 000000000..c6ae96de7
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/self-referential.rs
@@ -0,0 +1,29 @@
+// Some unusual code minimized from
+// https://github.com/sile/handy_async/tree/7b619b762c06544fc67792c8ff8ebc24a88fdb98
+
+pub trait Pattern {
+ type Value;
+}
+
+pub struct Constrain<A, B = A, C = A>(A, B, C);
+
+impl<A, B, C> Pattern for Constrain<A, B, C>
+ where A: Pattern,
+ B: Pattern<Value = A::Value>,
+ C: Pattern<Value = A::Value>,
+{
+ type Value = A::Value;
+}
+
+pub struct Wrapper<T>(T);
+
+impl<T> Pattern for Wrapper<T> {
+ type Value = T;
+}
+
+
+// @has self_referential/struct.WriteAndThen.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<P1> Send for WriteAndThen<P1>where <P1 as Pattern>::Value: Send"
+pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
+ where P1: Pattern;
diff --git a/tests/rustdoc/synthetic_auto/static-region.rs b/tests/rustdoc/synthetic_auto/static-region.rs
new file mode 100644
index 000000000..1a76cb919
--- /dev/null
+++ b/tests/rustdoc/synthetic_auto/static-region.rs
@@ -0,0 +1,10 @@
+pub trait OwnedTrait<'a> {
+ type Reader;
+}
+
+// @has static_region/struct.Owned.html
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<T> Send for Owned<T>where <T as OwnedTrait<'static>>::Reader: Send"
+pub struct Owned<T> where T: OwnedTrait<'static> {
+ marker: <T as OwnedTrait<'static>>::Reader,
+}
diff --git a/tests/rustdoc/tab_title.rs b/tests/rustdoc/tab_title.rs
new file mode 100644
index 000000000..0cc4f147e
--- /dev/null
+++ b/tests/rustdoc/tab_title.rs
@@ -0,0 +1,44 @@
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// tests for the html <title> element
+
+// @has foo/index.html '//head/title' 'foo - Rust'
+
+// @has foo/fn.widget_count.html '//head/title' 'widget_count in foo - Rust'
+/// blah
+pub fn widget_count() {}
+
+// @has foo/struct.Widget.html '//head/title' 'Widget in foo - Rust'
+pub struct Widget;
+
+// @has foo/constant.ANSWER.html '//head/title' 'ANSWER in foo - Rust'
+pub const ANSWER: u8 = 42;
+
+// @has foo/blah/index.html '//head/title' 'foo::blah - Rust'
+pub mod blah {
+ // @has foo/blah/struct.Widget.html '//head/title' 'Widget in foo::blah - Rust'
+ pub struct Widget;
+
+ // @has foo/blah/trait.Awesome.html '//head/title' 'Awesome in foo::blah - Rust'
+ pub trait Awesome {}
+
+ // @has foo/blah/fn.make_widget.html '//head/title' 'make_widget in foo::blah - Rust'
+ pub fn make_widget() {}
+
+ // @has foo/macro.cool_macro.html '//head/title' 'cool_macro in foo - Rust'
+ #[macro_export]
+ macro_rules! cool_macro {
+ ($t:tt) => { $t }
+ }
+}
+
+// @has foo/keyword.continue.html '//head/title' 'continue - Rust'
+#[doc(keyword = "continue")]
+mod continue_keyword {}
+
+// @has foo/primitive.u8.html '//head/title' 'u8 - Rust'
+// @!has - '//head/title' 'foo'
+#[doc(primitive = "u8")]
+/// `u8` docs
+mod u8 {}
diff --git a/tests/rustdoc/table-in-docblock.rs b/tests/rustdoc/table-in-docblock.rs
new file mode 100644
index 000000000..194f49f16
--- /dev/null
+++ b/tests/rustdoc/table-in-docblock.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @count - '//*[@class="docblock"]/div/table' 2
+// @!has - '//*[@class="docblock"]/table' ''
+/// | hello | hello2 |
+/// | ----- | ------ |
+/// | data | data2 |
+pub struct Foo;
+
+impl Foo {
+ /// | hello | hello2 |
+ /// | ----- | ------ |
+ /// | data | data2 |
+ pub fn foo(&self) {}
+}
diff --git a/tests/rustdoc/task-lists.rs b/tests/rustdoc/task-lists.rs
new file mode 100644
index 000000000..c2e7dd60f
--- /dev/null
+++ b/tests/rustdoc/task-lists.rs
@@ -0,0 +1,13 @@
+// ignore-tidy-linelength
+// FIXME: this doesn't test as much as I'd like; ideally it would have these query too:
+ // has task_lists/index.html '//li/input[@type="checkbox" and disabled]/following-sibling::text()' 'a'
+ // has task_lists/index.html '//li/input[@type="checkbox"]/following-sibling::text()' 'b'
+// Unfortunately that requires LXML, because the built-in xml module doesn't support all of xpath.
+
+// @has task_lists/index.html '//ul/li/input[@type="checkbox"]' ''
+// @has task_lists/index.html '//ul/li/input[@disabled]' ''
+// @has task_lists/index.html '//ul/li' 'a'
+// @has task_lists/index.html '//ul/li' 'b'
+//! This tests 'task list' support, a common markdown extension.
+//! - [ ] a
+//! - [x] b
diff --git a/tests/rustdoc/test-lists.rs b/tests/rustdoc/test-lists.rs
new file mode 100644
index 000000000..6a510b9ac
--- /dev/null
+++ b/tests/rustdoc/test-lists.rs
@@ -0,0 +1,26 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - //ol/li "list"
+// @has - //ol/li/ol/li "fooooo"
+// @has - //ol/li/ol/li "x"
+// @has - //ol/li "foo"
+/// 1. list
+/// 1. fooooo
+/// 2. x
+/// 2. foo
+pub fn f() {}
+
+// @has foo/fn.foo2.html
+// @has - //ul/li "normal list"
+// @has - //ul/li/ul/li "sub list"
+// @has - //ul/li/ul/li "new elem still same elem and again same elem!"
+// @has - //ul/li "new big elem"
+/// * normal list
+/// * sub list
+/// * new elem
+/// still same elem
+///
+/// and again same elem!
+/// * new big elem
+pub fn foo2() {}
diff --git a/tests/rustdoc/test-parens.rs b/tests/rustdoc/test-parens.rs
new file mode 100644
index 000000000..f5fdb1f52
--- /dev/null
+++ b/tests/rustdoc/test-parens.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(dyn ToString + 'static)"
+pub fn foo(_: &(ToString + 'static)) {}
diff --git a/tests/rustdoc/test-strikethrough.rs b/tests/rustdoc/test-strikethrough.rs
new file mode 100644
index 000000000..c7855729a
--- /dev/null
+++ b/tests/rustdoc/test-strikethrough.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - //del "Y"
+/// ~~Y~~
+pub fn f() {}
diff --git a/tests/rustdoc/test_option_check/bar.rs b/tests/rustdoc/test_option_check/bar.rs
new file mode 100644
index 000000000..50a182cf7
--- /dev/null
+++ b/tests/rustdoc/test_option_check/bar.rs
@@ -0,0 +1,9 @@
+// compile-flags: --test
+// check-test-line-numbers-match
+
+/// This looks like another awesome test!
+///
+/// ```
+/// println!("foo?");
+/// ```
+pub fn foooo() {}
diff --git a/tests/rustdoc/test_option_check/test.rs b/tests/rustdoc/test_option_check/test.rs
new file mode 100644
index 000000000..964e8e37e
--- /dev/null
+++ b/tests/rustdoc/test_option_check/test.rs
@@ -0,0 +1,18 @@
+// compile-flags: --test
+// check-test-line-numbers-match
+
+pub mod bar;
+
+/// This is a Foo;
+///
+/// ```
+/// println!("baaaaaar");
+/// ```
+pub struct Foo;
+
+/// This is a Bar;
+///
+/// ```
+/// println!("fooooo");
+/// ```
+pub struct Bar;
diff --git a/tests/rustdoc/thread-local-src.rs b/tests/rustdoc/thread-local-src.rs
new file mode 100644
index 000000000..6de35e323
--- /dev/null
+++ b/tests/rustdoc/thread-local-src.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//a[@href="../src/foo/thread-local-src.rs.html#1-6"]' 'source'
+
+// @has foo/constant.FOO.html '//a[@href="../src/foo/thread-local-src.rs.html#6"]' 'source'
+thread_local!(pub static FOO: bool = false);
diff --git a/tests/rustdoc/titles.rs b/tests/rustdoc/titles.rs
new file mode 100644
index 000000000..69e8b856b
--- /dev/null
+++ b/tests/rustdoc/titles.rs
@@ -0,0 +1,56 @@
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// @matches 'foo/index.html' '//h1' 'Crate foo'
+// @matches 'foo/index.html' '//h2[@class="location"]' 'Crate foo'
+
+// @matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
+// @matches 'foo/foo_mod/index.html' '//h2[@class="location"]' 'Module foo_mod'
+pub mod foo_mod {
+ pub struct __Thing {}
+}
+
+extern "C" {
+ // @matches 'foo/fn.foo_ffn.html' '//h1' 'Function foo::foo_ffn'
+ pub fn foo_ffn();
+}
+
+// @matches 'foo/fn.foo_fn.html' '//h1' 'Function foo::foo_fn'
+pub fn foo_fn() {}
+
+// @matches 'foo/trait.FooTrait.html' '//h1' 'Trait foo::FooTrait'
+// @matches 'foo/trait.FooTrait.html' '//h2[@class="location"]' 'FooTrait'
+pub trait FooTrait {}
+
+// @matches 'foo/struct.FooStruct.html' '//h1' 'Struct foo::FooStruct'
+// @matches 'foo/struct.FooStruct.html' '//h2[@class="location"]' 'FooStruct'
+pub struct FooStruct;
+
+// @matches 'foo/enum.FooEnum.html' '//h1' 'Enum foo::FooEnum'
+// @matches 'foo/enum.FooEnum.html' '//h2[@class="location"]' 'FooEnum'
+pub enum FooEnum {}
+
+// @matches 'foo/type.FooType.html' '//h1' 'Type Definition foo::FooType'
+// @matches 'foo/type.FooType.html' '//h2[@class="location"]' 'FooType'
+pub type FooType = FooStruct;
+
+// @matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo::foo_macro'
+#[macro_export]
+macro_rules! foo_macro {
+ () => {};
+}
+
+// @matches 'foo/primitive.bool.html' '//h1' 'Primitive Type bool'
+#[doc(primitive = "bool")]
+mod bool {}
+
+// @matches 'foo/static.FOO_STATIC.html' '//h1' 'Static foo::FOO_STATIC'
+pub static FOO_STATIC: FooStruct = FooStruct;
+
+extern "C" {
+ // @matches 'foo/static.FOO_FSTATIC.html' '//h1' 'Static foo::FOO_FSTATIC'
+ pub static FOO_FSTATIC: FooStruct;
+}
+
+// @matches 'foo/constant.FOO_CONSTANT.html' '//h1' 'Constant foo::FOO_CONSTANT'
+pub const FOO_CONSTANT: FooStruct = FooStruct;
diff --git a/tests/rustdoc/toggle-item-contents.rs b/tests/rustdoc/toggle-item-contents.rs
new file mode 100644
index 000000000..5d34ec09b
--- /dev/null
+++ b/tests/rustdoc/toggle-item-contents.rs
@@ -0,0 +1,185 @@
+#![allow(unused)]
+
+// @has 'toggle_item_contents/struct.PubStruct.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
+pub struct PubStruct {
+ pub a: usize,
+ pub b: usize,
+}
+
+// @has 'toggle_item_contents/struct.BigPubStruct.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields'
+pub struct BigPubStruct {
+ pub a: usize,
+ pub b: usize,
+ pub c: usize,
+ pub d: usize,
+ pub e: usize,
+ pub f: usize,
+ pub g: usize,
+ pub h: usize,
+ pub i: usize,
+ pub j: usize,
+ pub k: usize,
+ pub l: usize,
+ pub m: usize,
+}
+
+// @has 'toggle_item_contents/union.BigUnion.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields'
+pub union BigUnion {
+ pub a: usize,
+ pub b: usize,
+ pub c: usize,
+ pub d: usize,
+ pub e: usize,
+ pub f: usize,
+ pub g: usize,
+ pub h: usize,
+ pub i: usize,
+ pub j: usize,
+ pub k: usize,
+ pub l: usize,
+ pub m: usize,
+}
+
+// @has 'toggle_item_contents/union.Union.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
+pub union Union {
+ pub a: usize,
+ pub b: usize,
+ pub c: usize,
+}
+
+// @has 'toggle_item_contents/struct.PrivStruct.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
+// @has - '//div[@class="item-decl"]' '/* private fields */'
+pub struct PrivStruct {
+ a: usize,
+ b: usize,
+}
+
+// @has 'toggle_item_contents/enum.Enum.html'
+// @!has - '//details[@class="toggle type-contents-toggle"]' ''
+pub enum Enum {
+ A, B, C,
+ D {
+ a: u8,
+ b: u8
+ }
+}
+
+// @has 'toggle_item_contents/enum.EnumStructVariant.html'
+// @!has - '//details[@class="toggle type-contents-toggle"]' ''
+pub enum EnumStructVariant {
+ A, B, C,
+ D {
+ a: u8,
+ }
+}
+
+// @has 'toggle_item_contents/enum.LargeEnum.html'
+// @count - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+pub enum LargeEnum {
+ A, B, C, D, E, F(u8), G, H, I, J, K, L, M
+}
+
+// @has 'toggle_item_contents/trait.Trait.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
+pub trait Trait {
+ type A;
+ #[must_use]
+ fn foo();
+ fn bar();
+}
+
+// @has 'toggle_item_contents/trait.GinormousTrait.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 16 associated items'
+pub trait GinormousTrait {
+ type A;
+ type B;
+ type C;
+ type D;
+ type E;
+ type F;
+ type G;
+ type H;
+ type I;
+ type J;
+ type K;
+ type L;
+ type M;
+ const N: usize = 1;
+ #[must_use]
+ fn foo();
+ fn bar();
+}
+
+// @has 'toggle_item_contents/trait.HugeTrait.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods'
+pub trait HugeTrait {
+ type A;
+ const M: usize = 1;
+ const N: usize = 1;
+ const O: usize = 1;
+ const P: usize = 1;
+ const Q: usize = 1;
+ const R: usize = 1;
+ const S: usize = 1;
+ const T: usize = 1;
+ const U: usize = 1;
+ const V: usize = 1;
+ const W: usize = 1;
+ const X: usize = 1;
+ #[must_use]
+ fn foo();
+ fn bar();
+}
+
+// @has 'toggle_item_contents/trait.GiganticTrait.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method'
+pub trait GiganticTrait {
+ type A;
+ type B;
+ type C;
+ type D;
+ type E;
+ type F;
+ type G;
+ type H;
+ type I;
+ type J;
+ type K;
+ type L;
+ const M: usize = 1;
+ #[must_use]
+ fn foo();
+}
+
+// @has 'toggle_item_contents/trait.BigTrait.html'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 14 methods'
+pub trait BigTrait {
+ type A;
+ #[must_use]
+ fn foo();
+ fn bar();
+ fn baz();
+ fn quux();
+ fn frob();
+ fn greeble();
+ fn blap();
+ fn whoop();
+ fn pow();
+ fn bang();
+ fn oomph();
+ fn argh();
+ fn wap();
+ fn ouch();
+}
diff --git a/tests/rustdoc/toggle-method.rs b/tests/rustdoc/toggle-method.rs
new file mode 100644
index 000000000..ebc316ca8
--- /dev/null
+++ b/tests/rustdoc/toggle-method.rs
@@ -0,0 +1,18 @@
+#![crate_name = "foo"]
+
+// Struct methods with documentation should be wrapped in a <details> toggle with an appropriate
+// summary. Struct methods with no documentation should not be wrapped.
+//
+// @has foo/struct.Foo.html
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+pub struct Foo {
+}
+
+impl Foo {
+ pub fn not_documented() {}
+
+ /// is_documented is documented
+ pub fn is_documented() {}
+}
diff --git a/tests/rustdoc/toggle-trait-fn.rs b/tests/rustdoc/toggle-trait-fn.rs
new file mode 100644
index 000000000..686a174fc
--- /dev/null
+++ b/tests/rustdoc/toggle-trait-fn.rs
@@ -0,0 +1,30 @@
+#![crate_name = "foo"]
+
+// Trait methods with documentation should be wrapped in a <details> toggle with an appropriate
+// summary. Trait methods with no documentation should not be wrapped.
+//
+// @has foo/trait.Foo.html
+// @has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item2'
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
+pub trait Foo {
+ /// is documented
+ type Item;
+
+ type Item2;
+
+ fn not_documented();
+
+ /// is_documented is documented
+ fn is_documented();
+
+ fn not_documented_optional() {}
+
+ /// is_documented_optional is documented
+ fn is_documented_optional() {}
+}
diff --git a/tests/rustdoc/trait-alias-mention.rs b/tests/rustdoc/trait-alias-mention.rs
new file mode 100644
index 000000000..6da0dc687
--- /dev/null
+++ b/tests/rustdoc/trait-alias-mention.rs
@@ -0,0 +1,10 @@
+// aux-build:trait-alias-mention.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+extern crate trait_alias_mention;
+
+// @has foo/fn.mention_alias_in_bounds.html '//a[@href="../trait_alias_mention/traitalias.SomeAlias.html"]' 'SomeAlias'
+pub fn mention_alias_in_bounds<T: trait_alias_mention::SomeAlias>() {
+}
diff --git a/tests/rustdoc/trait-impl-items-links-and-anchors.rs b/tests/rustdoc/trait-impl-items-links-and-anchors.rs
new file mode 100644
index 000000000..a125fa036
--- /dev/null
+++ b/tests/rustdoc/trait-impl-items-links-and-anchors.rs
@@ -0,0 +1,65 @@
+pub trait MyTrait {
+ type Assoc;
+ const VALUE: u32 = 12;
+ fn trait_function(&self);
+ fn defaulted(&self) {}
+ fn defaulted_override(&self) {}
+}
+
+impl MyTrait for String {
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedtype.Assoc-1"]//a[@class="associatedtype"]/@href' #associatedtype.Assoc
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1
+ type Assoc = ();
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1
+ const VALUE: u32 = 5;
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.trait_function"]//a[@class="fn"]/@href' #tymethod.trait_function
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
+ fn trait_function(&self) {}
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.defaulted_override-1"]//a[@class="fn"]/@href' #method.defaulted_override
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1
+ fn defaulted_override(&self) {}
+}
+
+impl MyTrait for Vec<u8> {
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedtype.Assoc-2"]//a[@class="associatedtype"]/@href' #associatedtype.Assoc
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2
+ type Assoc = ();
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2
+ const VALUE: u32 = 5;
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.trait_function"]//a[@class="fn"]/@href' #tymethod.trait_function
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1
+ fn trait_function(&self) {}
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.defaulted_override-2"]//a[@class="fn"]/@href' #method.defaulted_override
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2
+ fn defaulted_override(&self) {}
+}
+
+impl MyTrait for MyStruct {
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="associatedtype.Assoc"]//a[@class="associatedtype"]/@href' trait.MyTrait.html#associatedtype.Assoc
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc
+ type Assoc = bool;
+ // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//*[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE
+ const VALUE: u32 = 20;
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.trait_function"]//a[@class="fn"]/@href' trait.MyTrait.html#tymethod.trait_function
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
+ fn trait_function(&self) {}
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.defaulted_override"]//a[@class="fn"]/@href' trait.MyTrait.html#method.defaulted_override
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override
+ fn defaulted_override(&self) {}
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.defaulted"]//a[@class="fn"]/@href' trait.MyTrait.html#method.defaulted
+ // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//*[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted
+}
+
+pub struct MyStruct;
+
+// We check that associated items with default values aren't generated in the implementors list.
+impl MyTrait for (u8, u8) {
+ // @!has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-4"]' ''
+ type Assoc = bool;
+ fn trait_function(&self) {}
+}
diff --git a/tests/rustdoc/trait-impl.rs b/tests/rustdoc/trait-impl.rs
new file mode 100644
index 000000000..9cf3226f7
--- /dev/null
+++ b/tests/rustdoc/trait-impl.rs
@@ -0,0 +1,45 @@
+pub trait Trait {
+ /// Some long docs here.
+ ///
+ /// These docs are long enough that a link will be added to the end.
+ fn a();
+
+ /// These docs contain a [reference link].
+ ///
+ /// [reference link]: https://example.com
+ fn b();
+
+ /// ```
+ /// This code block should not be in the output, but a Read more link should be generated
+ /// ```
+ fn c();
+
+ /// Escaped formatting a\*b\*c\* works
+ fn d();
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+ // @has trait_impl/struct.Struct.html '//*[@id="method.a"]/../../div[@class="docblock"]' 'Some long docs'
+ // @!has - '//*[@id="method.a"]/../../div[@class="docblock"]' 'link will be added'
+ // @has - '//*[@id="method.a"]/../../div[@class="docblock"]/a' 'Read more'
+ // @has - '//*[@id="method.a"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.a'
+ fn a() {}
+
+ // @has - '//*[@id="method.b"]/../../div[@class="docblock"]' 'These docs contain'
+ // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'reference link'
+ // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'https://example.com'
+ fn b() {}
+
+ // @!has - '//*[@id="method.c"]/../../div[@class="docblock"]' 'code block'
+ // @has - '//*[@id="method.c"]/../../div[@class="docblock"]/a' 'Read more'
+ // @has - '//*[@id="method.c"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.c'
+ fn c() {}
+
+ // @has - '//*[@id="method.d"]/../../div[@class="docblock"]' 'Escaped formatting a*b*c* works'
+ // @!has - '//*[@id="method.d"]/../../div[@class="docblock"]/em' ''
+ fn d() {}
+
+ // @has - '//*[@id="impl-Trait-for-Struct"]/h3//a/@href' 'trait.Trait.html'
+}
diff --git a/tests/rustdoc/trait-self-link.rs b/tests/rustdoc/trait-self-link.rs
new file mode 100644
index 000000000..e311dadff
--- /dev/null
+++ b/tests/rustdoc/trait-self-link.rs
@@ -0,0 +1,6 @@
+// @has trait_self_link/trait.Foo.html //a/@href trait.Foo.html
+pub trait Foo {}
+
+pub struct Bar;
+
+impl Foo for Bar {}
diff --git a/tests/rustdoc/trait-src-link.rs b/tests/rustdoc/trait-src-link.rs
new file mode 100644
index 000000000..a6367efba
--- /dev/null
+++ b/tests/rustdoc/trait-src-link.rs
@@ -0,0 +1,26 @@
+#![crate_name = "quix"]
+pub trait Foo {
+ // @has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#4"]' 'source'
+ fn required();
+
+ // @has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'source'
+ fn provided() {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {
+ // @has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#14"]' 'source'
+ fn required() {}
+ // @has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'source'
+}
+
+pub struct Baz;
+
+impl Foo for Baz {
+ // @has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#22"]' 'source'
+ fn required() {}
+
+ // @has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#25"]' 'source'
+ fn provided() {}
+}
diff --git a/tests/rustdoc/trait-visibility.rs b/tests/rustdoc/trait-visibility.rs
new file mode 100644
index 000000000..8ba3ee03a
--- /dev/null
+++ b/tests/rustdoc/trait-visibility.rs
@@ -0,0 +1,8 @@
+// aux-build:trait-visibility.rs
+
+#![crate_name = "foo"]
+
+extern crate trait_visibility;
+
+// @has foo/trait.Bar.html '//a[@href="#tymethod.foo"]/..' "fn foo()"
+pub use trait_visibility::Bar;
diff --git a/tests/rustdoc/trait_alias.rs b/tests/rustdoc/trait_alias.rs
new file mode 100644
index 000000000..791c099cc
--- /dev/null
+++ b/tests/rustdoc/trait_alias.rs
@@ -0,0 +1,26 @@
+#![feature(trait_alias)]
+
+#![crate_name = "foo"]
+
+use std::fmt::Debug;
+
+// @has foo/all.html '//a[@href="traitalias.CopyAlias.html"]' 'CopyAlias'
+// @has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
+// @has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo'
+
+// @has foo/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases'
+// @has foo/index.html '//a[@class="traitalias"]' 'CopyAlias'
+// @has foo/index.html '//a[@class="traitalias"]' 'Alias2'
+// @has foo/index.html '//a[@class="traitalias"]' 'Foo'
+
+// @has foo/traitalias.CopyAlias.html
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
+pub trait CopyAlias = Copy;
+// @has foo/traitalias.Alias2.html
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+pub trait Alias2 = Copy + Debug;
+// @has foo/traitalias.Foo.html
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
+pub trait Foo<T> = Into<T> + Debug;
+// @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
+pub fn bar<T>() where T: Alias2 {}
diff --git a/tests/rustdoc/traits-in-bodies-private.rs b/tests/rustdoc/traits-in-bodies-private.rs
new file mode 100644
index 000000000..96b7c4f9d
--- /dev/null
+++ b/tests/rustdoc/traits-in-bodies-private.rs
@@ -0,0 +1,13 @@
+// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items
+// and a trait was defined in non-module scope
+
+// compile-flags:--document-private-items
+
+// @has traits_in_bodies_private/struct.SomeStruct.html
+// @!has - '//code' 'impl HiddenTrait for SomeStruct'
+pub struct SomeStruct;
+
+fn __implementation_details() {
+ trait HiddenTrait {}
+ impl HiddenTrait for SomeStruct {}
+}
diff --git a/tests/rustdoc/traits-in-bodies.rs b/tests/rustdoc/traits-in-bodies.rs
new file mode 100644
index 000000000..a65dd7a54
--- /dev/null
+++ b/tests/rustdoc/traits-in-bodies.rs
@@ -0,0 +1,52 @@
+//prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it
+//didn't see that `SomeStruct` implemented `Clone`
+
+pub struct Bounded<T: Clone>(T);
+
+// @has traits_in_bodies/struct.SomeStruct.html
+// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct'
+pub struct SomeStruct;
+
+fn asdf() -> Bounded<SomeStruct> {
+ impl Clone for SomeStruct {
+ fn clone(&self) -> SomeStruct {
+ SomeStruct
+ }
+ }
+
+ Bounded(SomeStruct)
+}
+
+// @has traits_in_bodies/struct.Point.html
+// @has - '//h3[@class="code-header"]' 'impl Copy for Point'
+#[derive(Clone)]
+pub struct Point {
+ x: i32,
+ y: i32,
+}
+
+const _FOO: () = {
+ impl Copy for Point {}
+ ()
+};
+
+// @has traits_in_bodies/struct.Inception.html
+// @has - '//h3[@class="code-header"]' 'impl Clone for Inception'
+pub struct Inception;
+
+static _BAR: usize = {
+ trait HiddenTrait {
+ fn hidden_fn(&self) {
+ for _ in 0..5 {
+ impl Clone for Inception {
+ fn clone(&self) -> Self {
+ // we need to go deeper
+ Inception
+ }
+ }
+ }
+ }
+ }
+
+ 5
+};
diff --git a/tests/rustdoc/tuple-struct-fields-doc.rs b/tests/rustdoc/tuple-struct-fields-doc.rs
new file mode 100644
index 000000000..d72c10f2b
--- /dev/null
+++ b/tests/rustdoc/tuple-struct-fields-doc.rs
@@ -0,0 +1,50 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//h2[@id="fields"]' 'Tuple Fields'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Tuple Fields'
+// @has - '//*[@id="structfield.0"]' '0: u32'
+// @has - '//*[@id="main-content"]/div[@class="docblock"]' 'hello'
+// @!has - '//*[@id="structfield.1"]' ''
+// @has - '//*[@id="structfield.2"]' '2: char'
+// @has - '//*[@id="structfield.3"]' '3: i8'
+// @has - '//*[@id="main-content"]/div[@class="docblock"]' 'not hello'
+pub struct Foo(
+ /// hello
+ pub u32,
+ char,
+ pub char,
+ /// not hello
+ pub i8,
+);
+
+// @has foo/enum.Bar.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'BarVariant(String),'
+// @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$'
+// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
+// @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
+// @matches - '//*[@id="variant.FooVariant.fields"]/h4' '^Fields$'
+// @has - '//*[@id="variant.BazVariant.fields"]//*[@class="docblock"]' 'dox'
+// @has - '//*[@id="variant.OtherVariant.fields"]//*[@class="docblock"]' 'dox'
+// @!matches - '//*[@id="variant.QuuxVariant.fields"]/h4' '^Tuple Fields$'
+pub enum Bar {
+ BarVariant(
+ /// Hello docs
+ String
+ ),
+ FooVariant {
+ /// hello
+ x: u32,
+ },
+ BazVariant(
+ String,
+ /// dox
+ u32,
+ ),
+ OtherVariant(
+ /// dox
+ String,
+ u32,
+ ),
+ QuuxVariant(String),
+}
diff --git a/tests/rustdoc/tuples.link1_i32.html b/tests/rustdoc/tuples.link1_i32.html
new file mode 100644
index 000000000..4efde28ed
--- /dev/null
+++ b/tests/rustdoc/tuples.link1_i32.html
@@ -0,0 +1 @@
+<code>pub fn tuple1(x: (<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>,)) -&gt; (<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>,)</code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.link1_t.html b/tests/rustdoc/tuples.link1_t.html
new file mode 100644
index 000000000..1cbaec057
--- /dev/null
+++ b/tests/rustdoc/tuples.link1_t.html
@@ -0,0 +1 @@
+<code>pub fn tuple1_t&lt;T&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T,)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T,)</a></code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.link2_i32.html b/tests/rustdoc/tuples.link2_i32.html
new file mode 100644
index 000000000..77c8d81b8
--- /dev/null
+++ b/tests/rustdoc/tuples.link2_i32.html
@@ -0,0 +1 @@
+<code>pub fn tuple2(x: (<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>, <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>)) -&gt; (<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>, <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>)</code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.link2_t.html b/tests/rustdoc/tuples.link2_t.html
new file mode 100644
index 000000000..2477aa6be
--- /dev/null
+++ b/tests/rustdoc/tuples.link2_t.html
@@ -0,0 +1 @@
+<code>pub fn tuple2_t&lt;T&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a></code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.link2_tu.html b/tests/rustdoc/tuples.link2_tu.html
new file mode 100644
index 000000000..b02f8dd8d
--- /dev/null
+++ b/tests/rustdoc/tuples.link2_tu.html
@@ -0,0 +1 @@
+<code>pub fn tuple2_tu&lt;T, U&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, U)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, U)</a></code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.link_unit.html b/tests/rustdoc/tuples.link_unit.html
new file mode 100644
index 000000000..839990e15
--- /dev/null
+++ b/tests/rustdoc/tuples.link_unit.html
@@ -0,0 +1 @@
+<code>pub fn tuple0(x: <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>)</code> \ No newline at end of file
diff --git a/tests/rustdoc/tuples.rs b/tests/rustdoc/tuples.rs
new file mode 100644
index 000000000..e716de8b5
--- /dev/null
+++ b/tests/rustdoc/tuples.rs
@@ -0,0 +1,20 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.tuple0.html //pre 'pub fn tuple0(x: ())'
+// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple0(x: ()) -> () { x }
+// @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
+// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple1(x: (i32,)) -> (i32,) { x }
+// @has foo/fn.tuple2.html //pre 'pub fn tuple2(x: (i32, i32)) -> (i32, i32)'
+// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple2(x: (i32, i32)) -> (i32, i32) { x }
+// @has foo/fn.tuple1_t.html //pre 'pub fn tuple1_t<T>(x: (T,)) -> (T,)'
+// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple1_t<T>(x: (T,)) -> (T,) { x }
+// @has foo/fn.tuple2_t.html //pre 'pub fn tuple2_t<T>(x: (T, T)) -> (T, T)'
+// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple2_t<T>(x: (T, T)) -> (T, T) { x }
+// @has foo/fn.tuple2_tu.html //pre 'pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U)'
+// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U) { x }
diff --git a/tests/rustdoc/type-layout-flag-required.rs b/tests/rustdoc/type-layout-flag-required.rs
new file mode 100644
index 000000000..6bb5e10f8
--- /dev/null
+++ b/tests/rustdoc/type-layout-flag-required.rs
@@ -0,0 +1,4 @@
+// Tests that `--show-type-layout` is required in order to show layout info.
+
+// @!hasraw type_layout_flag_required/struct.Foo.html 'Size: '
+pub struct Foo(usize);
diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs
new file mode 100644
index 000000000..5e0a0411a
--- /dev/null
+++ b/tests/rustdoc/type-layout.rs
@@ -0,0 +1,85 @@
+// compile-flags: --show-type-layout -Z unstable-options
+
+// @hasraw type_layout/struct.Foo.html 'Size: '
+// @hasraw - ' bytes'
+// @has - '//*[@id="layout"]/a[@href="#layout"]' ''
+pub struct Foo {
+ pub a: usize,
+ b: Vec<String>,
+}
+
+// @hasraw type_layout/enum.Bar.html 'Size: '
+// @hasraw - ' bytes'
+pub enum Bar<'a> {
+ A(String),
+ B(&'a str, (std::collections::HashMap<String, usize>, Foo)),
+}
+
+// @hasraw type_layout/union.Baz.html 'Size: '
+// @hasraw - ' bytes'
+pub union Baz {
+ a: &'static str,
+ b: usize,
+ c: &'static [u8],
+}
+
+// @hasraw type_layout/struct.X.html 'Size: '
+// @hasraw - ' bytes'
+pub struct X(usize);
+
+// @hasraw type_layout/struct.Y.html 'Size: '
+// @hasraw - '1 byte'
+// @!hasraw - ' bytes'
+pub struct Y(u8);
+
+// @hasraw type_layout/struct.Z.html 'Size: '
+// @hasraw - '0 bytes'
+pub struct Z;
+
+// We can't compute layout for generic types.
+// @hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters'
+// @!hasraw - 'Size: '
+pub struct Generic<T>(T);
+
+// We *can*, however, compute layout for types that are only generic over lifetimes,
+// because lifetimes are a type-system construct.
+// @hasraw type_layout/struct.GenericLifetimes.html 'Size: '
+// @hasraw - ' bytes'
+pub struct GenericLifetimes<'a>(&'a str);
+
+// @hasraw type_layout/struct.Unsized.html 'Size: '
+// @hasraw - '(unsized)'
+pub struct Unsized([u8]);
+
+// @hasraw type_layout/type.TypeAlias.html 'Size: '
+// @hasraw - ' bytes'
+pub type TypeAlias = X;
+
+// @hasraw type_layout/type.GenericTypeAlias.html 'Size: '
+// @hasraw - '8 bytes'
+pub type GenericTypeAlias = (Generic<(u32, ())>, Generic<u32>);
+
+// Regression test for the rustdoc equivalent of #85103.
+// @hasraw type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.'
+pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>;
+
+// @!hasraw type_layout/trait.MyTrait.html 'Size: '
+pub trait MyTrait {}
+
+// @hasraw type_layout/enum.Variants.html 'Size: '
+// @hasraw - '2 bytes'
+// @hasraw - '<code>A</code>: 0 bytes'
+// @hasraw - '<code>B</code>: 1 byte'
+pub enum Variants {
+ A,
+ B(u8),
+}
+
+// @hasraw type_layout/enum.WithNiche.html 'Size: '
+// @has - //p '4 bytes'
+// @hasraw - '<code>None</code>: 0 bytes'
+// @hasraw - '<code>Some</code>: 4 bytes'
+pub enum WithNiche {
+ None,
+ Some(std::num::NonZeroU32),
+}
diff --git a/tests/rustdoc/typedef.rs b/tests/rustdoc/typedef.rs
new file mode 100644
index 000000000..d5dfa9484
--- /dev/null
+++ b/tests/rustdoc/typedef.rs
@@ -0,0 +1,25 @@
+pub trait MyTrait {
+ fn method_on_mytrait() {}
+}
+
+pub struct MyStruct;
+
+impl MyStruct {
+ pub fn method_on_mystruct() {}
+}
+
+// @has typedef/type.MyAlias.html
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyAlias'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias'
+// @hasraw - 'Alias docstring'
+// @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias'
+// @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
+// @has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations'
+/// Alias docstring
+pub type MyAlias = MyStruct;
+
+impl MyAlias {
+ pub fn method_on_myalias() {}
+}
+
+impl MyTrait for MyAlias {}
diff --git a/tests/rustdoc/unindent.md b/tests/rustdoc/unindent.md
new file mode 100644
index 000000000..8e4e7a25a
--- /dev/null
+++ b/tests/rustdoc/unindent.md
@@ -0,0 +1 @@
+Just some text.
diff --git a/tests/rustdoc/unindent.rs b/tests/rustdoc/unindent.rs
new file mode 100644
index 000000000..372af5f46
--- /dev/null
+++ b/tests/rustdoc/unindent.rs
@@ -0,0 +1,62 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Example.html
+// @matches - '//pre[@class="rust rust-example-rendered"]' \
+// '(?m)let example = Example::new\(\)\n \.first\(\)\n \.second\(\)\n \.build\(\);\Z'
+/// ```rust
+/// let example = Example::new()
+/// .first()
+#[cfg_attr(not(feature = "one"), doc = " .second()")]
+/// .build();
+/// ```
+pub struct Example;
+
+// @has foo/struct.F.html
+// @matches - '//pre[@class="rust rust-example-rendered"]' \
+// '(?m)let example = Example::new\(\)\n \.first\(\)\n \.another\(\)\n \.build\(\);\Z'
+///```rust
+///let example = Example::new()
+/// .first()
+#[cfg_attr(not(feature = "one"), doc = " .another()")]
+/// .build();
+/// ```
+pub struct F;
+
+// @has foo/struct.G.html
+// @matches - '//pre[@class="rust rust-example-rendered"]' \
+// '(?m)let example = Example::new\(\)\n\.first\(\)\n \.another\(\)\n\.build\(\);\Z'
+///```rust
+///let example = Example::new()
+///.first()
+#[cfg_attr(not(feature = "one"), doc = " .another()")]
+///.build();
+///```
+pub struct G;
+
+// @has foo/struct.H.html
+// @has - '//div[@class="docblock"]/p' 'no whitespace lol'
+///no whitespace
+#[doc = " lol"]
+pub struct H;
+
+// @has foo/struct.I.html
+// @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!\Z'
+/// 4 whitespaces!
+#[doc = "something"]
+pub struct I;
+
+// @has foo/struct.J.html
+// @matches - '//div[@class="docblock"]/p' '(?m)a\nno whitespace\nJust some text.\Z'
+///a
+///no whitespace
+#[doc = include_str!("unindent.md")]
+pub struct J;
+
+// @has foo/struct.K.html
+// @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!\Z'
+///a
+///
+/// 4 whitespaces!
+///
+#[doc = include_str!("unindent.md")]
+pub struct K;
diff --git a/tests/rustdoc/union.rs b/tests/rustdoc/union.rs
new file mode 100644
index 000000000..5a788eb1b
--- /dev/null
+++ b/tests/rustdoc/union.rs
@@ -0,0 +1,8 @@
+// @has union/union.U.html
+pub union U {
+ // @has - //pre "pub a: u8"
+ pub a: u8,
+ // @has - //pre "/* private fields */"
+ // @!has - //pre "b: u16"
+ b: u16,
+}
diff --git a/tests/rustdoc/unit-return.rs b/tests/rustdoc/unit-return.rs
new file mode 100644
index 000000000..353cd1c47
--- /dev/null
+++ b/tests/rustdoc/unit-return.rs
@@ -0,0 +1,17 @@
+// aux-build:unit-return.rs
+
+#![crate_name = "foo"]
+
+extern crate unit_return;
+
+// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
+pub fn f0<F: FnMut(u8) + Clone>(f: F) {}
+
+// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
+pub fn f1<F: FnMut(u16) -> () + Clone>(f: F) {}
+
+// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
+pub use unit_return::f2;
+
+// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
+pub use unit_return::f3;
diff --git a/tests/rustdoc/universal-impl-trait.rs b/tests/rustdoc/universal-impl-trait.rs
new file mode 100644
index 000000000..f5eabda59
--- /dev/null
+++ b/tests/rustdoc/universal-impl-trait.rs
@@ -0,0 +1,55 @@
+#![crate_name = "foo"]
+
+use std::io::Read;
+use std::borrow::Borrow;
+
+// @has foo/fn.foo.html
+// @has - //pre 'foo('
+// @matchesraw - '_x: impl <a class="trait" href="[^"]+/trait\.Clone\.html"'
+// @matchesraw - '_z: .+impl.+trait\.Copy\.html.+, impl.+trait\.Clone\.html'
+pub fn foo(_x: impl Clone, _y: i32, _z: (impl Copy, impl Clone)) {
+}
+
+pub trait Trait {
+ // @has foo/trait.Trait.html
+ // @hasraw - 'method</a>('
+ // @matchesraw - '_x: impl <a class="trait" href="[^"]+/trait\.Debug\.html"'
+ fn method(&self, _x: impl std::fmt::Debug) {
+ }
+}
+
+pub struct S<T>(T);
+
+impl<T> S<T> {
+ // @has foo/struct.S.html
+ // @hasraw - 'bar</a>('
+ // @matchesraw - '_bar: impl <a class="trait" href="[^"]+/trait\.Copy\.html"'
+ pub fn bar(_bar: impl Copy) {
+ }
+
+ // @hasraw - 'baz</a>('
+ // @matchesraw - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html'
+ pub fn baz(_baz: S<impl Clone>) {
+ }
+
+ // @hasraw - 'qux</a>('
+ // @matchesraw - 'trait\.Read\.html'
+ pub fn qux(_qux: impl IntoIterator<Item = S<impl Read>>) {
+ }
+}
+
+// @hasraw - 'method</a>('
+// @matchesraw - '_x: impl <a class="trait" href="[^"]+/trait\.Debug\.html"'
+impl<T> Trait for S<T> {}
+
+// @has foo/fn.much_universe.html
+// @matchesraw - 'T:.+Borrow.+impl .+trait\.Trait\.html'
+// @matchesraw - 'U:.+IntoIterator.+= impl.+Iterator\.html.+= impl.+Clone\.html'
+// @matchesraw - '_: impl .+trait\.Read\.html.+ \+ .+trait\.Clone\.html'
+pub fn much_universe<
+ T: Borrow<impl Trait>,
+ U: IntoIterator<Item = impl Iterator<Item = impl Clone>>,
+>(
+ _: impl Read + Clone,
+) {
+}
diff --git a/tests/rustdoc/unneeded-trait-implementations-title.rs b/tests/rustdoc/unneeded-trait-implementations-title.rs
new file mode 100644
index 000000000..e1bcfd3b9
--- /dev/null
+++ b/tests/rustdoc/unneeded-trait-implementations-title.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+pub struct Bar;
+
+// @count foo/struct.Bar.html '//*[@id="implementations"]' 0
diff --git a/tests/rustdoc/use-attr.rs b/tests/rustdoc/use-attr.rs
new file mode 100644
index 000000000..996b7bba6
--- /dev/null
+++ b/tests/rustdoc/use-attr.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+// ICE when rustdoc encountered a use statement of a non-macro attribute (see #58054)
+
+// @has use_attr/index.html
+// @has - '//code' 'pub use proc_macro_attribute'
+pub use proc_macro_attribute;
+use proc_macro_derive;
diff --git a/tests/rustdoc/useless_lifetime_bound.rs b/tests/rustdoc/useless_lifetime_bound.rs
new file mode 100644
index 000000000..f530d8a65
--- /dev/null
+++ b/tests/rustdoc/useless_lifetime_bound.rs
@@ -0,0 +1,13 @@
+use std::marker::PhantomData;
+
+// @has useless_lifetime_bound/struct.Scope.html
+// @!has - '//*[@class="rust struct"]' "'env: 'env"
+pub struct Scope<'env> {
+ _marker: PhantomData<&'env mut &'env ()>,
+}
+
+// @has useless_lifetime_bound/struct.Scope.html
+// @!has - '//*[@class="rust struct"]' "T: 'a + 'a"
+pub struct SomeStruct<'a, T: 'a> {
+ _marker: PhantomData<&'a T>,
+}
diff --git a/tests/rustdoc/variadic.rs b/tests/rustdoc/variadic.rs
new file mode 100644
index 000000000..bd8f1775b
--- /dev/null
+++ b/tests/rustdoc/variadic.rs
@@ -0,0 +1,4 @@
+extern "C" {
+ // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, ...)'
+ pub fn foo(x: i32, ...);
+}
diff --git a/tests/rustdoc/version-separator-without-source.rs b/tests/rustdoc/version-separator-without-source.rs
new file mode 100644
index 000000000..04ea46a7f
--- /dev/null
+++ b/tests/rustdoc/version-separator-without-source.rs
@@ -0,0 +1,23 @@
+#![doc(html_no_source)]
+#![feature(staged_api)]
+#![stable(feature = "bar", since = "1.0")]
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · '
+// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
+#[stable(feature = "bar", since = "1.0")]
+pub fn foo() {}
+
+// @has foo/struct.Bar.html
+// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · '
+// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
+#[stable(feature = "bar", since = "1.0")]
+pub struct Bar;
+
+impl Bar {
+ // @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0'
+ // @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0 ·'
+ #[stable(feature = "foobar", since = "2.0")]
+ pub fn bar() {}
+}
diff --git a/tests/rustdoc/viewpath-rename.rs b/tests/rustdoc/viewpath-rename.rs
new file mode 100644
index 000000000..546127637
--- /dev/null
+++ b/tests/rustdoc/viewpath-rename.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+pub mod io {
+ pub trait Reader { fn dummy(&self) { } }
+}
+
+pub enum Maybe<A> {
+ Just(A),
+ Nothing
+}
+
+// @has foo/prelude/index.html
+pub mod prelude {
+ // @has foo/prelude/index.html '//code' 'pub use io as FooIo;'
+ // @has foo/prelude/index.html '//code' 'pub use io::Reader as FooReader;'
+ #[doc(no_inline)] pub use io::{self as FooIo, Reader as FooReader};
+ // @has foo/prelude/index.html '//code' 'pub use Maybe;'
+ // @has foo/prelude/index.html '//code' 'pub use Maybe::Just as MaybeJust;'
+ // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;'
+ #[doc(no_inline)] pub use Maybe::{self, Just as MaybeJust, Nothing};
+}
diff --git a/tests/rustdoc/viewpath-self.rs b/tests/rustdoc/viewpath-self.rs
new file mode 100644
index 000000000..a6b659295
--- /dev/null
+++ b/tests/rustdoc/viewpath-self.rs
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+pub mod io {
+ pub trait Reader { fn dummy(&self) { } }
+}
+
+pub enum Maybe<A> {
+ Just(A),
+ Nothing
+}
+
+// @has foo/prelude/index.html
+pub mod prelude {
+ // @has foo/prelude/index.html '//code' 'pub use io;'
+ // @has foo/prelude/index.html '//code' 'pub use io::Reader;'
+ #[doc(no_inline)] pub use io::{self, Reader};
+ // @has foo/prelude/index.html '//code' 'pub use Maybe;'
+ // @has foo/prelude/index.html '//code' 'pub use Maybe::Just;'
+ // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;'
+ #[doc(no_inline)] pub use Maybe::{self, Just, Nothing};
+}
diff --git a/tests/rustdoc/visibility.rs b/tests/rustdoc/visibility.rs
new file mode 100644
index 000000000..4099b54f0
--- /dev/null
+++ b/tests/rustdoc/visibility.rs
@@ -0,0 +1,105 @@
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @!has 'foo/index.html' '//a[@href="struct.FooPublic.html"]/..' 'FooPublic 🔒'
+// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic'
+pub struct FooPublic;
+// @has 'foo/index.html' '//a[@href="struct.FooJustCrate.html"]/..' 'FooJustCrate 🔒'
+// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate'
+pub(crate) struct FooJustCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooPubCrate.html"]/..' 'FooPubCrate 🔒'
+// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate'
+pub(crate) struct FooPubCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooSelf.html"]/..' 'FooSelf 🔒'
+// @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf'
+pub(self) struct FooSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooInSelf.html"]/..' 'FooInSelf 🔒'
+// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
+pub(in self) struct FooInSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooPriv.html"]/..' 'FooPriv 🔒'
+// @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv'
+struct FooPriv;
+
+// @!has 'foo/index.html' '//a[@href="pub_mod/index.html"]/..' 'pub_mod 🔒'
+pub mod pub_mod {}
+
+// @has 'foo/index.html' '//a[@href="pub_crate_mod/index.html"]/..' 'pub_crate_mod 🔒'
+pub(crate) mod pub_crate_mod {}
+
+// @has 'foo/index.html' '//a[@href="a/index.html"]/..' 'a 🔒'
+mod a {
+ // @has 'foo/a/index.html' '//a[@href="struct.FooASuper.html"]/..' 'FooASuper 🔒'
+ // @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper'
+ pub(super) struct FooASuper;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAInSuper.html"]/..' 'FooAInSuper 🔒'
+ // @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper'
+ pub(in super) struct FooAInSuper;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAInA.html"]/..' 'FooAInA 🔒'
+ // @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA'
+ // @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub'
+ pub(in a) struct FooAInA;
+ // @has 'foo/a/index.html' '//a[@href="struct.FooAPriv.html"]/..' 'FooAPriv 🔒'
+ // @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv'
+ // @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub'
+ struct FooAPriv;
+
+ // @has 'foo/a/index.html' '//a[@href="b/index.html"]/..' 'b 🔒'
+ mod b {
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBSuper.html"]/..' 'FooBSuper 🔒'
+ // @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper'
+ pub(super) struct FooBSuper;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInSuperSuper.html"]/..' 'FooBInSuperSuper 🔒'
+ // @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper'
+ pub(in super::super) struct FooBInSuperSuper;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInAB.html"]/..' 'FooBInAB 🔒'
+ // @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB'
+ // @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub'
+ pub(in a::b) struct FooBInAB;
+ // @has 'foo/a/b/index.html' '//a[@href="struct.FooBPriv.html"]/..' 'FooBPriv 🔒'
+ // @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv'
+ // @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub'
+ struct FooBPriv;
+
+ // @!has 'foo/a/b/index.html' '//a[@href="struct.FooBPub.html"]/..' 'FooBPub 🔒'
+ // @has 'foo/a/b/struct.FooBPub.html' '//pre' 'pub struct FooBPub'
+ pub struct FooBPub;
+ }
+}
+
+// @has 'foo/trait.PubTrait.html' '//pre' 'pub trait PubTrait'
+//
+// @has 'foo/trait.PubTrait.html' '//pre' 'type Type;'
+// @!has 'foo/trait.PubTrait.html' '//pre' 'pub type Type;'
+//
+// @has 'foo/trait.PubTrait.html' '//pre' 'const CONST: usize;'
+// @!has 'foo/trait.PubTrait.html' '//pre' 'pub const CONST: usize;'
+//
+// @has 'foo/trait.PubTrait.html' '//pre' 'fn function();'
+// @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();'
+//
+// @!has 'foo/index.html' '//a[@href="trait.PubTrait.html"]/..' 'PubTrait 🔒'
+
+pub trait PubTrait {
+ type Type;
+ const CONST: usize;
+ fn function();
+}
+
+// @has 'foo/index.html' '//a[@href="trait.PrivTrait.html"]/..' 'PrivTrait 🔒'
+trait PrivTrait {}
+
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'type Type'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub type Type'
+//
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'const CONST: usize'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub const CONST: usize'
+//
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'fn function()'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub fn function()'
+
+impl PubTrait for FooPublic {
+ type Type = usize;
+ const CONST: usize = 0;
+ fn function() {}
+}
diff --git a/tests/rustdoc/where-clause-order.rs b/tests/rustdoc/where-clause-order.rs
new file mode 100644
index 000000000..b8502e10a
--- /dev/null
+++ b/tests/rustdoc/where-clause-order.rs
@@ -0,0 +1,19 @@
+#![crate_name = "foo"]
+
+pub trait SomeTrait<Rhs = Self>
+where
+ Rhs: ?Sized,
+{
+}
+
+// @has 'foo/trait.SomeTrait.html'
+// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
+impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
+where
+ A: PartialOrd<A> + PartialEq<A>,
+ B: PartialOrd<B> + PartialEq<B>,
+ C: PartialOrd<C> + PartialEq<C>,
+ D: PartialOrd<D> + PartialEq<D>,
+ E: PartialOrd<E> + PartialEq<E> + ?Sized,
+{
+}
diff --git a/tests/rustdoc/where-sized.rs b/tests/rustdoc/where-sized.rs
new file mode 100644
index 000000000..c0c085e6a
--- /dev/null
+++ b/tests/rustdoc/where-sized.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where X: ?Sized,'
+pub fn foo<X, Y: ?Sized>(_: &X) where X: ?Sized {}
diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html
new file mode 100644
index 000000000..f84cb3753
--- /dev/null
+++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html
@@ -0,0 +1 @@
+<div class="item-decl"><pre class="rust"><code>pub struct Simd&lt;T&gt;(_)<br /><span class="where">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
new file mode 100644
index 000000000..85b626674
--- /dev/null
+++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
@@ -0,0 +1,8 @@
+<div class="item-decl"><pre class="rust"><code>pub trait TraitWhere {
+ type <a href="#associatedtype.Item" class="associatedtype">Item</a>&lt;'a&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: 'a</span>;
+
+ fn <a href="#method.func" class="fn">func</a>(self)<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
+ { ... }
+<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -&gt; <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a>&lt;Self&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
+ { ... }
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs
new file mode 100644
index 000000000..3ac0c6872
--- /dev/null
+++ b/tests/rustdoc/where.rs
@@ -0,0 +1,62 @@
+#![crate_name = "foo"]
+
+use std::io::Lines;
+
+pub trait MyTrait { fn dummy(&self) { } }
+
+// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_)where A: MyTrait"
+pub struct Alpha<A>(A) where A: MyTrait;
+// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
+pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
+// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait"
+pub fn charlie<C>() where C: MyTrait {}
+
+pub struct Delta<D>(D);
+
+// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<D> Delta<D>where D: MyTrait"
+impl<D> Delta<D> where D: MyTrait {
+ pub fn delta() {}
+}
+
+pub struct Echo<E>(E);
+
+// @has 'foo/struct.Simd.html'
+// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]'
+pub struct Simd<T>([T; 1])
+where
+ T: MyTrait;
+
+// @has 'foo/trait.TraitWhere.html'
+// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]'
+pub trait TraitWhere {
+ type Item<'a> where Self: 'a;
+
+ fn func(self)
+ where
+ Self: Sized
+ {}
+
+ fn lines(self) -> Lines<Self>
+ where
+ Self: Sized,
+ { todo!() }
+}
+
+// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<E> MyTrait for Echo<E>where E: MyTrait"
+// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl<E> MyTrait for Echo<E>where E: MyTrait"
+impl<E> MyTrait for Echo<E>where E: MyTrait {}
+
+pub enum Foxtrot<F> { Foxtrot1(F) }
+
+// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
+// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
+// "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
+impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
+
+// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// "type Golf<T>where T: Clone, = (T, T)"
+pub type Golf<T> where T: Clone = (T, T);
diff --git a/tests/rustdoc/whitespace-after-where-clause.enum.html b/tests/rustdoc/whitespace-after-where-clause.enum.html
new file mode 100644
index 000000000..20bde549a
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.enum.html
@@ -0,0 +1,4 @@
+<div class="item-decl"><pre class="rust"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+ Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
+ Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.enum2.html b/tests/rustdoc/whitespace-after-where-clause.enum2.html
new file mode 100644
index 000000000..d9fc0c223
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.enum2.html
@@ -0,0 +1,4 @@
+<div class="item-decl"><pre class="rust"><code>pub enum Cow2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+ Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
+ Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.rs b/tests/rustdoc/whitespace-after-where-clause.rs
new file mode 100644
index 000000000..4b740b970
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.rs
@@ -0,0 +1,77 @@
+// This test ensures there is no whitespace before the first brace of
+// trait, enum, struct and union items when they have a where clause.
+
+#![crate_name = "foo"]
+
+// @has 'foo/trait.ToOwned.html'
+// @snapshot trait - '//*[@class="item-decl"]'
+pub trait ToOwned<T>
+where T: Clone
+{
+ type Owned;
+ fn to_owned(&self) -> Self::Owned;
+ fn whatever(&self) -> T;
+}
+
+// @has 'foo/trait.ToOwned2.html'
+// @snapshot trait2 - '//*[@class="item-decl"]'
+// There should be a whitespace before `{` in this case!
+pub trait ToOwned2<T: Clone> {
+ type Owned;
+ fn to_owned(&self) -> Self::Owned;
+ fn whatever(&self) -> T;
+}
+
+// @has 'foo/enum.Cow.html'
+// @snapshot enum - '//*[@class="item-decl"]'
+pub enum Cow<'a, B: ?Sized + 'a>
+where
+ B: ToOwned<Clone>,
+{
+ Borrowed(&'a B),
+ Whatever(u32),
+}
+
+// @has 'foo/enum.Cow2.html'
+// @snapshot enum2 - '//*[@class="item-decl"]'
+// There should be a whitespace before `{` in this case!
+pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
+ Borrowed(&'a B),
+ Whatever(u32),
+}
+
+// @has 'foo/struct.Struct.html'
+// @snapshot struct - '//*[@class="item-decl"]'
+pub struct Struct<'a, B: ?Sized + 'a>
+where
+ B: ToOwned<Clone>,
+{
+ pub a: &'a B,
+ pub b: u32,
+}
+
+// @has 'foo/struct.Struct2.html'
+// @snapshot struct2 - '//*[@class="item-decl"]'
+// There should be a whitespace before `{` in this case!
+pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
+ pub a: &'a B,
+ pub b: u32,
+}
+
+// @has 'foo/union.Union.html'
+// @snapshot union - '//*[@class="item-decl"]'
+pub union Union<'a, B: ?Sized + 'a>
+where
+ B: ToOwned<Clone>,
+{
+ a: &'a B,
+ b: u32,
+}
+
+// @has 'foo/union.Union2.html'
+// @snapshot union2 - '//*[@class="item-decl"]'
+// There should be a whitespace before `{` in this case!
+pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
+ a: &'a B,
+ b: u32,
+}
diff --git a/tests/rustdoc/whitespace-after-where-clause.struct.html b/tests/rustdoc/whitespace-after-where-clause.struct.html
new file mode 100644
index 000000000..f375265d7
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.struct.html
@@ -0,0 +1,4 @@
+<div class="item-decl"><pre class="rust"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+ pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
+ pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.struct2.html b/tests/rustdoc/whitespace-after-where-clause.struct2.html
new file mode 100644
index 000000000..1c59962eb
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.struct2.html
@@ -0,0 +1,4 @@
+<div class="item-decl"><pre class="rust"><code>pub struct Struct2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+ pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
+ pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html
new file mode 100644
index 000000000..a2df06e77
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.trait.html
@@ -0,0 +1,6 @@
+<div class="item-decl"><pre class="rust"><code>pub trait ToOwned&lt;T&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
+ type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+
+ fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
+<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.trait2.html b/tests/rustdoc/whitespace-after-where-clause.trait2.html
new file mode 100644
index 000000000..2bfd6f768
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.trait2.html
@@ -0,0 +1,6 @@
+<div class="item-decl"><pre class="rust"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
+ type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+
+ fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
+<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.union.html b/tests/rustdoc/whitespace-after-where-clause.union.html
new file mode 100644
index 000000000..066f8f87b
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.union.html
@@ -0,0 +1,3 @@
+<div class="item-decl"><pre class="rust"><code>pub union Union&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+ /* private fields */
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html
new file mode 100644
index 000000000..6b48c5dbd
--- /dev/null
+++ b/tests/rustdoc/whitespace-after-where-clause.union2.html
@@ -0,0 +1,3 @@
+<div class="item-decl"><pre class="rust"><code>pub union Union2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+ /* private fields */
+}</code></pre></div> \ No newline at end of file
diff --git a/tests/rustdoc/without-redirect.rs b/tests/rustdoc/without-redirect.rs
new file mode 100644
index 000000000..a076f8a3c
--- /dev/null
+++ b/tests/rustdoc/without-redirect.rs
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+
+// @has foo/macro.bar.html
+// @has foo/macro.bar!.html
+// @!has foo/bar.m.html
+#[macro_export]
+macro_rules! bar {
+ () => {}
+}
+
+// @has foo/struct.Bar.html
+// @!has foo/Bar.t.html
+pub struct Bar;
diff --git a/tests/rustdoc/wrapping.rs b/tests/rustdoc/wrapping.rs
new file mode 100644
index 000000000..178b8adc3
--- /dev/null
+++ b/tests/rustdoc/wrapping.rs
@@ -0,0 +1,5 @@
+use std::fmt::Debug;
+
+// @has 'wrapping/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo() -> impl Debug'
+// @count - '//div[@class="item-decl"]/pre[@class="rust"]/br' 0
+pub fn foo() -> impl Debug {}