diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2025-05-05 17:01:08 +0200 |
|---|---|---|
| committer | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2025-05-05 17:47:18 +0200 |
| commit | b84f4cc39e99f801dcd37125dffa67eb796c85b8 (patch) | |
| tree | 071def2349dabae166fd66b06ee9346aa825abb9 /tests/rustdoc/constant | |
| parent | be71d8b24f1aebe9c45279d95a76db8fa6a62574 (diff) | |
| download | rust-b84f4cc39e99f801dcd37125dffa67eb796c85b8.tar.gz rust-b84f4cc39e99f801dcd37125dffa67eb796c85b8.zip | |
Created `tests/rustdoc/impl` subfolder to limit number of files at the top level
Diffstat (limited to 'tests/rustdoc/constant')
22 files changed, 812 insertions, 0 deletions
diff --git a/tests/rustdoc/constant/assoc-consts-underscore.rs b/tests/rustdoc/constant/assoc-consts-underscore.rs new file mode 100644 index 00000000000..f48098094db --- /dev/null +++ b/tests/rustdoc/constant/assoc-consts-underscore.rs @@ -0,0 +1,30 @@ +pub struct Struct { + _private: (), +} + +pub trait Trait { + //@ has assoc_consts_underscore/trait.Trait.html '//pre[@class="rust item-decl"]' \ + // 'const REQUIRED: Struct;' + //@ !has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct = _' + //@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct' + const REQUIRED: Struct; + //@ has - '//pre[@class="rust item-decl"]' 'const OPTIONAL: Struct = _;' + //@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _' + const OPTIONAL: Struct = Struct { _private: () }; +} + +impl Trait for Struct { + //@ !has assoc_consts_underscore/struct.Struct.html '//*[@id="associatedconstant.REQUIRED"]' \ + // 'const REQUIRED: Struct = _' + //@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct' + const REQUIRED: Struct = Struct { _private: () }; + //@ !has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _' + //@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct' + const OPTIONAL: Struct = Struct { _private: () }; +} + +impl Struct { + //@ !has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct = _' + //@ has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct' + pub const INHERENT: Struct = Struct { _private: () }; +} diff --git a/tests/rustdoc/constant/assoc-consts-version.rs b/tests/rustdoc/constant/assoc-consts-version.rs new file mode 100644 index 00000000000..db4d759acab --- /dev/null +++ b/tests/rustdoc/constant/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/constant/assoc-consts.rs b/tests/rustdoc/constant/assoc-consts.rs new file mode 100644 index 00000000000..247b5b180a8 --- /dev/null +++ b/tests/rustdoc/constant/assoc-consts.rs @@ -0,0 +1,103 @@ +pub trait Foo { + //@ has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \ + // '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))" + 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/constant/associated-consts.rs b/tests/rustdoc/constant/associated-consts.rs new file mode 100644 index 00000000000..2a7269a89be --- /dev/null +++ b/tests/rustdoc/constant/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/constant/const-display.rs b/tests/rustdoc/constant/const-display.rs new file mode 100644 index 00000000000..bc4270c421d --- /dev/null +++ b/tests/rustdoc/constant/const-display.rs @@ -0,0 +1,92 @@ +#![crate_name = "foo"] + +#![stable(feature = "rust1", since = "1.0.0")] + +#![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.foo3.html' '//pre' 'pub const fn foo3() -> u32' +//@ !hasraw - '//span[@class="since"]' +#[unstable(feature = "humans", issue = "none")] +#[rustc_const_unstable(feature = "humans", issue = "none")] +pub const fn foo3() -> 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 } + +#[unstable( + feature = "humans", + reason = "who ever let humans program computers, we're apparently really bad at it", + issue = "none", +)] +pub mod unstable { + //@ has 'foo/unstable/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 } +} + +#[stable(feature = "rust1", since = "1.0.0")] +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 { + // Show non-const stabilities that are the same as the enclosing item. + //@ has 'foo/struct.Bar.html' '//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 } +} diff --git a/tests/rustdoc/constant/const-doc.rs b/tests/rustdoc/constant/const-doc.rs new file mode 100644 index 00000000000..f33083a267c --- /dev/null +++ b/tests/rustdoc/constant/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/constant/const-effect-param.rs b/tests/rustdoc/constant/const-effect-param.rs new file mode 100644 index 00000000000..cceb0adac30 --- /dev/null +++ b/tests/rustdoc/constant/const-effect-param.rs @@ -0,0 +1,14 @@ +// Check that we don't render host effect parameters & arguments. + +#![crate_name = "foo"] +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Tr { + fn f(); +} + +//@ has foo/fn.g.html +//@ has - '//pre[@class="rust item-decl"]' 'pub const fn g<T: Tr>()' +/// foo +pub const fn g<T: ~const Tr>() {} diff --git a/tests/rustdoc/constant/const-underscore.rs b/tests/rustdoc/constant/const-underscore.rs new file mode 100644 index 00000000000..fafc4b4e25c --- /dev/null +++ b/tests/rustdoc/constant/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/constant/const-value-display.rs b/tests/rustdoc/constant/const-value-display.rs new file mode 100644 index 00000000000..658978a3490 --- /dev/null +++ b/tests/rustdoc/constant/const-value-display.rs @@ -0,0 +1,9 @@ +#![crate_name = "foo"] + +//@ has 'foo/constant.HOUR_IN_SECONDS.html' +//@ has - '//*[@class="rust 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="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64' +pub const NEGATIVE: i64 = -60 * 60; diff --git a/tests/rustdoc/constant/const.rs b/tests/rustdoc/constant/const.rs new file mode 100644 index 00000000000..fe6a828505a --- /dev/null +++ b/tests/rustdoc/constant/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/constant/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc/constant/document-item-with-associated-const-in-where-clause.rs new file mode 100644 index 00000000000..c9408ef3360 --- /dev/null +++ b/tests/rustdoc/constant/document-item-with-associated-const-in-where-clause.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Enumerable { + const N: usize; +} + +#[derive(Clone)] +pub struct SymmetricGroup<S> +where + S: Enumerable, + [(); S::N]: Sized, +{ + _phantom: std::marker::PhantomData<S>, +} + +fn main() {} diff --git a/tests/rustdoc/constant/generic-const-items.rs b/tests/rustdoc/constant/generic-const-items.rs new file mode 100644 index 00000000000..31c300f2ff1 --- /dev/null +++ b/tests/rustdoc/constant/generic-const-items.rs @@ -0,0 +1,38 @@ +#![feature(generic_const_items)] +#![allow(incomplete_features)] + +//@ has 'generic_const_items/constant.K.html' +//@ has - '//*[@class="rust item-decl"]//code' \ +// "pub const K<'a, T: 'a + Copy, const N: usize>: Option<[T; N]> \ +// where \ +// String: From<T>;" +pub const K<'a, T: 'a + Copy, const N: usize>: Option<[T; N]> = None +where + String: From<T>; + +//@ has generic_const_items/trait.Trait.html +pub trait Trait<T: ?Sized> { + //@ has - '//*[@id="associatedconstant.C"]' \ + // "const C<'a>: &'a T \ + // where \ + // T: 'a + Eq" + const C<'a>: &'a T + where + T: 'a + Eq; +} + +pub struct Implementor; + +//@ has generic_const_items/struct.Implementor.html +//@ has - '//h3[@class="code-header"]' 'impl Trait<str> for Implementor' +impl Trait<str> for Implementor { + //@ has - '//*[@id="associatedconstant.C"]' \ + // "const C<'a>: &'a str = \"C\" \ + // where \ + // str: 'a" + const C<'a>: &'a str = "C" + // In real code we could've left off this bound but adding it explicitly allows us to test if + // we render where-clauses on associated consts inside impl blocks correctly. + where + str: 'a; +} diff --git a/tests/rustdoc/constant/generic_const_exprs.rs b/tests/rustdoc/constant/generic_const_exprs.rs new file mode 100644 index 00000000000..44f7bf5b24c --- /dev/null +++ b/tests/rustdoc/constant/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/constant/glob-shadowing-const.rs b/tests/rustdoc/constant/glob-shadowing-const.rs new file mode 100644 index 00000000000..fbc22dbccaa --- /dev/null +++ b/tests/rustdoc/constant/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 - '//dd' '1' +//@ !has - '//dd' '0' +fn main() { assert_eq!(X, 1); } diff --git a/tests/rustdoc/constant/hide-complex-unevaluated-const-arguments.rs b/tests/rustdoc/constant/hide-complex-unevaluated-const-arguments.rs new file mode 100644 index 00000000000..e94c1ea5c61 --- /dev/null +++ b/tests/rustdoc/constant/hide-complex-unevaluated-const-arguments.rs @@ -0,0 +1,91 @@ +// 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, adt_const_params, generic_const_items)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +//@ 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(/* ... */).do_something(Self::ABSTRACT * 1_000)] + where [(); Struct::new(/* ... */).do_something(Self::ABSTRACT * 1_000)]:; + + //@ has - '//*[@id="associatedconstant.VERBOSE"]' \ + // 'const VERBOSE: [u16; { _ }]' + const VERBOSE: [u16; compute("thing", 9 + 9) * Self::ABSTRACT] + where [(); 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 \ +// '//pre[@class="rust item-decl"]' \ +// 'pub trait Sub: Sup<{ _ }, { _ }> { }' +pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {} + +pub trait Sup<const N: usize, const S: Struct> {} + +#[derive(ConstParamTy, PartialEq, Eq)] +pub struct Struct { private: () } + +impl Struct { + const fn new() -> Self { Self { private: () } } + const fn do_something(self, x: usize) -> usize { + x + } +} +/* FIXME(const-trait): readd this +impl const std::ops::Add<usize> for Struct { + type Output = usize; + + fn add(self, _: usize) -> usize { 0 } +} +*/ diff --git a/tests/rustdoc/constant/hide-complex-unevaluated-consts.rs b/tests/rustdoc/constant/hide-complex-unevaluated-consts.rs new file mode 100644 index 00000000000..61ae8c801dd --- /dev/null +++ b/tests/rustdoc/constant/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/constant/ice-associated-const-equality-105952.rs b/tests/rustdoc/constant/ice-associated-const-equality-105952.rs new file mode 100644 index 00000000000..1bcdfac7342 --- /dev/null +++ b/tests/rustdoc/constant/ice-associated-const-equality-105952.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/105952 +#![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/constant/legacy-const-generic.rs b/tests/rustdoc/constant/legacy-const-generic.rs new file mode 100644 index 00000000000..41df535f3e0 --- /dev/null +++ b/tests/rustdoc/constant/legacy-const-generic.rs @@ -0,0 +1,16 @@ +#![crate_name = "foo"] +#![feature(rustc_attrs)] + +//@ has 'foo/fn.foo.html' +//@ has - '//pre[@class="rust item-decl"]' '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 - '//pre[@class="rust item-decl"]' '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/constant/link-assoc-const.rs b/tests/rustdoc/constant/link-assoc-const.rs new file mode 100644 index 00000000000..56b82fb2d39 --- /dev/null +++ b/tests/rustdoc/constant/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/constant/redirect-const.rs b/tests/rustdoc/constant/redirect-const.rs new file mode 100644 index 00000000000..e636a915f30 --- /dev/null +++ b/tests/rustdoc/constant/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/constant/rfc-2632-const-trait-impl.rs b/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs new file mode 100644 index 00000000000..8a86e3e5e97 --- /dev/null +++ b/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs @@ -0,0 +1,73 @@ +// 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. +// +// FIXME(const_trait_impl) add `const_trait` to `Fn` so we use `~const` +// FIXME(const_trait_impl) restore `const_trait` to `Destruct` +#![feature(const_trait_impl)] +#![crate_name = "foo"] + +use std::marker::Destruct; + +pub struct S<T>(T); + +//@ !has foo/trait.Tr.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const' +//@ has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' +//@ !has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '~const' +//@ has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Fn' +#[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"]' 'Fn' + //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' + //@ has - '//section[@id="method.a"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' + fn a<A: /* ~const */ Fn() /* + ~const Destruct */>() + where + Option<A>: /* ~const */ Fn() /* + ~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"]' 'Fn' +//@ !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"]/div[@class="where"]' ': Fn' +impl<T: /* ~const */ Fn() /* + ~const Destruct */> const Tr<T> for T +where + Option<T>: /* ~const */ Fn() /* + ~const Destruct */, +{ + fn a<A: /* ~const */ Fn() /* + ~const Destruct */>() + where + Option<A>: /* ~const */ Fn() /* + ~const Destruct */, + { + } +} + +//@ !has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const' +//@ has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' +//@ !has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' '~const' +//@ has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' ': Fn' +pub const fn foo<F: /* ~const */ Fn() /* + ~const Destruct */>() +where + Option<F>: /* ~const */ Fn() /* + ~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"]' 'Fn' + //@ !has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' + //@ has - '//section[@id="method.foo"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' + pub const fn foo<B, C: /* ~const */ Fn() /* + ~const Destruct */>() + where + B: /* ~const */ Fn() /* + ~const Destruct */, + { + B::a() + } +} diff --git a/tests/rustdoc/constant/show-const-contents.rs b/tests/rustdoc/constant/show-const-contents.rs new file mode 100644 index 00000000000..6d2701693ce --- /dev/null +++ b/tests/rustdoc/constant/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.14159265358979323846264338327950288_f32;' +//@ 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>"#; |
