about summary refs log tree commit diff
path: root/tests/rustdoc/macro
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-05 16:40:02 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-05 17:47:18 +0200
commitd1f4a0bcb60ab868c496ca72a28b48ac0a4128af (patch)
tree5f9dc3dd1df27f8d4a2f7f06950943cc4ab3cc5c /tests/rustdoc/macro
parenteee6c9753588fe1888d3ddb264f9516e7ac56997 (diff)
downloadrust-d1f4a0bcb60ab868c496ca72a28b48ac0a4128af.tar.gz
rust-d1f4a0bcb60ab868c496ca72a28b48ac0a4128af.zip
Created `tests/rustdoc/macro` subfolder to limit number of files at the top level
Diffstat (limited to 'tests/rustdoc/macro')
-rw-r--r--tests/rustdoc/macro/auxiliary/external-macro-src.rs15
-rw-r--r--tests/rustdoc/macro/auxiliary/issue-99221-aux.rs20
-rw-r--r--tests/rustdoc/macro/auxiliary/macro_pub_in_module.rs13
-rw-r--r--tests/rustdoc/macro/auxiliary/pub-use-extern-macros.rs21
-rw-r--r--tests/rustdoc/macro/compiler-derive-proc-macro.rs15
-rw-r--r--tests/rustdoc/macro/const-rendering-macros-33302.rs54
-rw-r--r--tests/rustdoc/macro/decl_macro.rs58
-rw-r--r--tests/rustdoc/macro/decl_macro_priv.rs14
-rw-r--r--tests/rustdoc/macro/doc-proc-macro.rs8
-rw-r--r--tests/rustdoc/macro/external-macro-src.rs12
-rw-r--r--tests/rustdoc/macro/macro-const-display-115295.rs41
-rw-r--r--tests/rustdoc/macro/macro-doc-comment-23812.rs39
-rw-r--r--tests/rustdoc/macro/macro-export-crate-root-108231.rs23
-rw-r--r--tests/rustdoc/macro/macro-generated-macro.macro_linebreak_pre.html6
-rw-r--r--tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html15
-rw-r--r--tests/rustdoc/macro/macro-generated-macro.rs39
-rw-r--r--tests/rustdoc/macro/macro-higher-kinded-function.rs21
-rw-r--r--tests/rustdoc/macro/macro-ice-16019.rs11
-rw-r--r--tests/rustdoc/macro/macro-in-async-block.rs9
-rw-r--r--tests/rustdoc/macro/macro-in-closure.rs16
-rw-r--r--tests/rustdoc/macro/macro-indirect-use.rs16
-rw-r--r--tests/rustdoc/macro/macro_pub_in_module.rs86
-rw-r--r--tests/rustdoc/macro/macro_rules-matchers.rs22
-rw-r--r--tests/rustdoc/macro/macros.rs24
-rw-r--r--tests/rustdoc/macro/multiple-macro-rules-w-same-name-99221.rs18
-rw-r--r--tests/rustdoc/macro/multiple-macro-rules-w-same-name-submodule-99221.rs20
-rw-r--r--tests/rustdoc/macro/proc-macro.rs72
-rw-r--r--tests/rustdoc/macro/pub-use-extern-macros.rs17
-rw-r--r--tests/rustdoc/macro/rustc-macro-crate.rs14
29 files changed, 739 insertions, 0 deletions
diff --git a/tests/rustdoc/macro/auxiliary/external-macro-src.rs b/tests/rustdoc/macro/auxiliary/external-macro-src.rs
new file mode 100644
index 00000000000..79df5dc98eb
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/auxiliary/issue-99221-aux.rs b/tests/rustdoc/macro/auxiliary/issue-99221-aux.rs
new file mode 100644
index 00000000000..e061e42b29d
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/auxiliary/macro_pub_in_module.rs b/tests/rustdoc/macro/auxiliary/macro_pub_in_module.rs
new file mode 100644
index 00000000000..81efa1db536
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/auxiliary/pub-use-extern-macros.rs b/tests/rustdoc/macro/auxiliary/pub-use-extern-macros.rs
new file mode 100644
index 00000000000..7934e07339a
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/compiler-derive-proc-macro.rs b/tests/rustdoc/macro/compiler-derive-proc-macro.rs
new file mode 100644
index 00000000000..e8dc5d7c6b7
--- /dev/null
+++ b/tests/rustdoc/macro/compiler-derive-proc-macro.rs
@@ -0,0 +1,15 @@
+// This test ensures that compiler builtin proc-macros are considered as such.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+// Each compiler builtin proc-macro has a trait equivalent so we should have
+// a trait section as well.
+//@ count - '//*[@id="main-content"]//*[@class="section-header"]' 2
+//@ has - '//*[@id="main-content"]//*[@class="section-header"]' 'Traits'
+//@ has - '//*[@id="main-content"]//*[@class="section-header"]' 'Derive Macros'
+
+// Now checking the correct file is generated as well.
+//@ has 'foo/derive.Clone.html'
+//@ !has 'foo/macro.Clone.html'
+pub use std::clone::Clone;
diff --git a/tests/rustdoc/macro/const-rendering-macros-33302.rs b/tests/rustdoc/macro/const-rendering-macros-33302.rs
new file mode 100644
index 00000000000..9fd45df08be
--- /dev/null
+++ b/tests/rustdoc/macro/const-rendering-macros-33302.rs
@@ -0,0 +1,54 @@
+// https://github.com/rust-lang/rust/issues/33302
+#![crate_name="issue_33302"]
+
+// 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 \
+        //        '//pre[@class="rust item-decl"]' 'pub const CST: i32'
+        pub const CST: i32 = ($n * $n);
+        //@ has issue_33302/static.ST.html \
+        //        '//pre[@class="rust item-decl"]' '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 \
+            //        '//pre[@class="rust item-decl"]' 'const D: i32'
+            //@ has - '//*[@id="associatedconstant.D"]' 'const D: i32'
+            const D: i32 = ($n * $n);
+        }
+
+        //@ has issue_33302/struct.S.html \
+        //        '//*[@class="impl"]' '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"]' '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"]' '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/macro/decl_macro.rs b/tests/rustdoc/macro/decl_macro.rs
new file mode 100644
index 00000000000..040859baffb
--- /dev/null
+++ b/tests/rustdoc/macro/decl_macro.rs
@@ -0,0 +1,58 @@
+//@ 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) {'
+            // Regression test for <https://github.com/rust-lang/rust/issues/83000>:
+            //@ has - '//pre[@class="rust item-decl"]//a[@class="mod"]/@href' '../../index.html'
+            pub(in a) macro by_example_vis_named {
+                ($foo:expr) => {}
+            }
+        }
+    }
+}
diff --git a/tests/rustdoc/macro/decl_macro_priv.rs b/tests/rustdoc/macro/decl_macro_priv.rs
new file mode 100644
index 00000000000..d87c8d22f2d
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/doc-proc-macro.rs b/tests/rustdoc/macro/doc-proc-macro.rs
new file mode 100644
index 00000000000..19172ffa41d
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/external-macro-src.rs b/tests/rustdoc/macro/external-macro-src.rs
new file mode 100644
index 00000000000..998687d93bd
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/macro-const-display-115295.rs b/tests/rustdoc/macro/macro-const-display-115295.rs
new file mode 100644
index 00000000000..445b47e0b24
--- /dev/null
+++ b/tests/rustdoc/macro/macro-const-display-115295.rs
@@ -0,0 +1,41 @@
+// https://github.com/rust-lang/rust/issues/115295
+#![crate_name = "foo"]
+
+//@ has foo/trait.Trait.html
+pub trait Trait<T> {}
+
+//@ has foo/struct.WithConst.html
+pub struct WithConst<const N: usize>;
+
+macro_rules! spans_from_macro {
+    () => {
+        impl WithConst<42> {
+            pub fn new() -> Self {
+                Self
+            }
+        }
+        impl Trait<WithConst<42>> for WithConst<42> {}
+        impl Trait<WithConst<43>> for WithConst<{ 43 }> {}
+        impl Trait<WithConst<{ 44 }>> for WithConst<44> {}
+        pub struct Other {
+            pub field: WithConst<42>,
+        }
+    };
+}
+
+//@ has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<41>> for WithConst<41>"
+impl Trait<WithConst<41>> for WithConst<41> {}
+
+//@ has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl WithConst<42>"
+//@ has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<42>> for WithConst<42>"
+//@ has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<43>> for WithConst<{ 43 }>"
+//@ has - '//*[@class="impl"]//h3[@class="code-header"]' \
+//     "impl Trait<WithConst<44>> for WithConst<44>"
+
+//@ has foo/struct.Other.html
+//@ has - //pre "pub field: WithConst<42>"
+spans_from_macro!();
diff --git a/tests/rustdoc/macro/macro-doc-comment-23812.rs b/tests/rustdoc/macro/macro-doc-comment-23812.rs
new file mode 100644
index 00000000000..03fda4a25b9
--- /dev/null
+++ b/tests/rustdoc/macro/macro-doc-comment-23812.rs
@@ -0,0 +1,39 @@
+// https://github.com/rust-lang/rust/issues/23812
+#![crate_name="issue_23812"]
+
+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/macro/macro-export-crate-root-108231.rs b/tests/rustdoc/macro/macro-export-crate-root-108231.rs
new file mode 100644
index 00000000000..0d3ad1b0571
--- /dev/null
+++ b/tests/rustdoc/macro/macro-export-crate-root-108231.rs
@@ -0,0 +1,23 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/108231>.
+// Macros with `#[macro_export]` attribute should be visible at the top level
+// even if they are inside a doc hidden item.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ count - '//*[@id="main-content"]//a[@class="macro"]' 1
+//@ has - '//*[@id="main-content"]//a[@class="macro"]' 'foo'
+
+#[doc(hidden)]
+pub mod __internal {
+    /// This one should be visible.
+    #[macro_export]
+    macro_rules! foo {
+        () => {};
+    }
+
+    /// This one should be hidden.
+    macro_rules! bar {
+        () => {};
+    }
+}
diff --git a/tests/rustdoc/macro/macro-generated-macro.macro_linebreak_pre.html b/tests/rustdoc/macro/macro-generated-macro.macro_linebreak_pre.html
new file mode 100644
index 00000000000..ce5d3a8461b
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro-generated-macro.macro_morestuff_pre.html b/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html
new file mode 100644
index 00000000000..28f15522a82
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro-generated-macro.rs b/tests/rustdoc/macro/macro-generated-macro.rs
new file mode 100644
index 00000000000..e77d0cf89e7
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro-higher-kinded-function.rs b/tests/rustdoc/macro/macro-higher-kinded-function.rs
new file mode 100644
index 00000000000..738ea8fb3f1
--- /dev/null
+++ b/tests/rustdoc/macro/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="rust item-decl"]//code' "pub a: for<'tcx> fn(TyCtxt<'tcx>, u8) -> i8,"
+//@ has - '//*[@class="rust 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/macro-ice-16019.rs b/tests/rustdoc/macro/macro-ice-16019.rs
new file mode 100644
index 00000000000..d0f82e0a314
--- /dev/null
+++ b/tests/rustdoc/macro/macro-ice-16019.rs
@@ -0,0 +1,11 @@
+// https://github.com/rust-lang/rust/issues/16019
+
+macro_rules! define_struct {
+    ($rounds:expr) => (
+        struct Struct {
+            sk: [u32; $rounds + 1]
+        }
+        )
+}
+
+define_struct!(2);
diff --git a/tests/rustdoc/macro/macro-in-async-block.rs b/tests/rustdoc/macro/macro-in-async-block.rs
new file mode 100644
index 00000000000..43822fb9c52
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro-in-closure.rs b/tests/rustdoc/macro/macro-in-closure.rs
new file mode 100644
index 00000000000..b4411d927e2
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro-indirect-use.rs b/tests/rustdoc/macro/macro-indirect-use.rs
new file mode 100644
index 00000000000..e410e96ae6a
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro_pub_in_module.rs b/tests/rustdoc/macro/macro_pub_in_module.rs
new file mode 100644
index 00000000000..2dce73c2cf2
--- /dev/null
+++ b/tests/rustdoc/macro/macro_pub_in_module.rs
@@ -0,0 +1,86 @@
+//@ 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/attr.test.html
+    //@ !has krate/macro.test.html
+    //@ !has krate/inner/macro.test.html
+    //@ !has krate/attr.test.html
+    #[rustc_builtin_macro]
+    pub macro test($item:item) {}
+
+    //@ has krate/inner/derive.Clone.html
+    //@ !has krate/inner/macro.Clone.html
+    //@ !has krate/macro.Clone.html
+    //@ !has krate/derive.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/macro_rules-matchers.rs b/tests/rustdoc/macro/macro_rules-matchers.rs
new file mode 100644
index 00000000000..2c9fb50539a
--- /dev/null
+++ b/tests/rustdoc/macro/macro_rules-matchers.rs
@@ -0,0 +1,22 @@
+// 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' '//pre' 'macro_rules! todo { \
+//      () => { ... }; \
+//      ($($arg:tt)+) => { ... }; \
+// }'
+pub use std::todo;
+
+mod mod1 {
+    //@ has 'foo/macro.macro1.html' '//pre' 'macro_rules! macro1 { \
+    //      () => { ... }; \
+    //      ($($arg:expr),+) => { ... }; \
+    // }'
+    #[macro_export]
+    macro_rules! macro1 {
+        () => {};
+        ($($arg:expr),+) => { stringify!($($arg),+) };
+    }
+}
diff --git a/tests/rustdoc/macro/macros.rs b/tests/rustdoc/macro/macros.rs
new file mode 100644
index 00000000000..d08babc25f8
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/multiple-macro-rules-w-same-name-99221.rs b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-99221.rs
new file mode 100644
index 00000000000..4a1798a8496
--- /dev/null
+++ b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-99221.rs
@@ -0,0 +1,18 @@
+//@ aux-build:issue-99221-aux.rs
+//@ build-aux-docs
+//@ ignore-cross-compile
+
+// https://github.com/rust-lang/rust/issues/99221
+#![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/macro/multiple-macro-rules-w-same-name-submodule-99221.rs b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-submodule-99221.rs
new file mode 100644
index 00000000000..bf59788073e
--- /dev/null
+++ b/tests/rustdoc/macro/multiple-macro-rules-w-same-name-submodule-99221.rs
@@ -0,0 +1,20 @@
+//@ aux-build:issue-99221-aux.rs
+//@ build-aux-docs
+//@ ignore-cross-compile
+
+// https://github.com/rust-lang/rust/issues/99221
+#![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/macro/proc-macro.rs b/tests/rustdoc/macro/proc-macro.rs
new file mode 100644
index 00000000000..a821f68ab93
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/pub-use-extern-macros.rs b/tests/rustdoc/macro/pub-use-extern-macros.rs
new file mode 100644
index 00000000000..2316e620343
--- /dev/null
+++ b/tests/rustdoc/macro/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/macro/rustc-macro-crate.rs b/tests/rustdoc/macro/rustc-macro-crate.rs
new file mode 100644
index 00000000000..f0443364bb2
--- /dev/null
+++ b/tests/rustdoc/macro/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
+}