diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/rustdoc | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-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')
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>() -> 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<T>() -> <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a><<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_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() -> <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a><[<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.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<T>() -> &'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() -> &'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 />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        buf: &mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; + + fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        bufs: &[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>> { ... } +}</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">{"&'static [SomeStruct]":"<h3>Notable traits for <code>&amp;[<a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\">SomeStruct</a>]</code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait_slice::SomeTrait\">SomeTrait</a> for &amp;[<a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\">SomeStruct</a>]</span>"}</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":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>"}</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":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</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<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</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><'_>" +pub fn test1(a: &u32) -> Ref { + Ref(a) +} + +// @has foo/fn.test2.html +// @matchesraw - "Ref</a><'_>" +pub fn test2(a: &u32) -> Ref<'_> { + Ref(a) +} + +// @has foo/fn.test3.html +// @matchesraw - "Ref</a><'_>" +pub fn test3(a: &u32) -> ARef { + Ref(a) +} + +// @has foo/fn.test4.html +// @matchesraw - "Ref</a><'_>" +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><'_>" +// @has foo/bar/fn.test6.html +// @matchesraw - "Ref</a><'_>" +#[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>(&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 - "<'_>" +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><Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>></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><T>: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a><Item = T></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>) -> <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>(&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> <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> <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> <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 & <stuff> & "things"' 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 - '{ () => { ... }; ($(' +// @has - '//span[@class="macro-nonterminal"]' '$' +// @has - '//span[@class="macro-nonterminal"]' 'arg' +// @hasraw - ':tt)+' +// @hasraw - ') => { ... }; }' +pub use std::todo; + +mod mod1 { + // @has 'foo/macro.macro1.html' + // @hasraw - 'macro_rules!' + // @hasraw - 'macro1' + // @hasraw - '{ () => { ... }; ($(' + // @has - '//span[@class="macro-nonterminal"]' '$' + // @has - '//span[@class="macro-nonterminal"]' 'arg' + // @hasraw - ':' + // @hasraw - 'expr' + // @hasraw - '),' + // @hasraw - '+' + // @hasraw - ') => { ... }; }' + #[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<T>() -> <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a><<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_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() -> <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a><[<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.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<T>() -> &'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() -> &'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":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\">Odd</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html\" title=\"trait core::iter::traits::iterator::Iterator\">Iterator</a> for <a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\">Odd</a></span><span class=\"where fmt-newline\"> type <a href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item\" class=\"associatedtype\">Item</a> = <a class=\"primitive\" href=\"{{channel}}/std/primitive.usize.html\">usize</a>;</span>"}</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>,)) -> (<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<T>(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T,)</a>) -> <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>)) -> (<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<T>(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>) -> <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<T, U>(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, U)</a>) -> <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<T>(_)<br /><span class="where">where<br />    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><'a><br />    <span class="where">where<br />        Self: 'a</span>; + + fn <a href="#method.func" class="fn">func</a>(self)<br />    <span class="where">where<br />        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) -> <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a><Self><br />    <span class="where">where<br />        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<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<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">&'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<'a, B: ?<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><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'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<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<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">&'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<'a, B: ?<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><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'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<T><span class="where fmt-newline">where<br />    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>(&self) -> 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>(&self) -> 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<T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> { + type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>; + + fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&self) -> 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>(&self) -> 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<'a, B><span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + ?<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<'a, B: ?<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><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + /* 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 {} |