diff --git a/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs new file mode 100644 index 0000000000000..97760cbf8fb58 --- /dev/null +++ b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs @@ -0,0 +1,24 @@ +// check-pass +// edition:2018 +#![feature(min_const_generics)] +trait ValidTrait {} + +/// This has docs +pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]> { + loop {} +} + +pub trait Trait<const N: usize> {} +impl Trait<1> for u8 {} +impl Trait<2> for u8 {} +impl<const N: usize> Trait<N> for [u8; N] {} + +/// This also has docs +pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> { + loop {} +} + +/// Document all the functions +pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> { + loop {} +} diff --git a/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs b/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs new file mode 100644 index 0000000000000..b8bd040f7a4b2 --- /dev/null +++ b/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs @@ -0,0 +1,18 @@ +// edition:2018 +#![feature(min_const_generics)] + +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/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs new file mode 100644 index 0000000000000..8dcba36600d26 --- /dev/null +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -0,0 +1,130 @@ +// edition:2018 +// aux-build: extern_crate.rs +#![feature(min_const_generics)] +#![crate_name = "foo"] + +extern crate extern_crate; +// @has foo/fn.extern_fn.html '//pre[@class="rust fn"]' \ +// 'pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]>' +pub use extern_crate::extern_fn; +// @has foo/struct.ExternTy.html '//pre[@class="rust struct"]' \ +// 'pub struct ExternTy<const N: usize> {' +pub use extern_crate::ExternTy; +// @has foo/type.TyAlias.html '//pre[@class="rust typedef"]' \ +// 'type TyAlias<const N: usize> = ExternTy<N>;' +pub use extern_crate::TyAlias; +// @has foo/trait.WTrait.html '//pre[@class="rust trait"]' \ +// 'pub trait WTrait<const N: usize, const M: usize>' +// @has - '//*[@class="rust trait"]' 'fn hey<const P: usize>() -> usize' +pub use extern_crate::WTrait; + +// @has foo/trait.Trait.html '//pre[@class="rust trait"]' \ +// 'pub trait Trait<const N: usize>' +// @has - '//*[@id="impl-Trait%3C1_usize%3E-for-u8"]//code' 'impl Trait<1_usize> for u8' +// @has - '//*[@id="impl-Trait%3C2_usize%3E-for-u8"]//code' 'impl Trait<2_usize> for u8' +// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//code' 'impl Trait<{1 + 2}> for u8' +// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//code' \ +// '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 '//pre[@class="rust struct"]' \ +// '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 '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)' +pub struct Bar<T, const N: usize>([T; N]); + +// @has foo/struct.Foo.html '//h3[@id="impl"]/code' '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 '//h3[@id="impl"]/code' '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 '//pre[@class="rust fn"]' \ +// '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 '//pre[@class="rust fn"]' \ +// '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 '//pre[@class="rust fn"]' \ +// 'pub async fn b_sink<const N: usize>(__arg0: impl Trait<N>)' +// FIXME(const_generics): This should be `_` not `__arg0`. +pub async fn b_sink<const N: usize>(_: impl Trait<N>) {} + +// @has foo/fn.concrete.html '//pre[@class="rust fn"]' \ +// 'pub fn concrete() -> [u8; 22]' +pub fn concrete() -> [u8; 3 + std::mem::size_of::<u64>() << 1] { + Default::default() +} + +// @has foo/type.Faz.html '//pre[@class="rust typedef"]' \ +// 'type Faz<const N: usize> = [u8; N];' +pub type Faz<const N: usize> = [u8; N]; +// @has foo/type.Fiz.html '//pre[@class="rust typedef"]' \ +// '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 '//pre[@class="rust struct"]' \ +// '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 '//pre[@class="rust fn"]' \ +// '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 '//pre[@class="rust union"]' \ +// '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 '//pre[@class="rust enum"]' \ +// '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/src/test/ui/const-generics/associated-type-bound-fail.full.stderr b/src/test/ui/const-generics/associated-type-bound-fail.full.stderr new file mode 100644 index 0000000000000..8ccbe5dee0e44 --- /dev/null +++ b/src/test/ui/const-generics/associated-type-bound-fail.full.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u16: Bar<N>` is not satisfied + --> $DIR/associated-type-bound-fail.rs:14:5 + | +LL | type Assoc: Bar<N>; + | ------ required by this bound in `Foo::Assoc` +... +LL | type Assoc = u16; + | ^^^^^^^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `u16` + | + = help: the following implementations were found: + <u16 as Bar<3_usize>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/associated-type-bound-fail.min.stderr b/src/test/ui/const-generics/associated-type-bound-fail.min.stderr new file mode 100644 index 0000000000000..8ccbe5dee0e44 --- /dev/null +++ b/src/test/ui/const-generics/associated-type-bound-fail.min.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u16: Bar<N>` is not satisfied + --> $DIR/associated-type-bound-fail.rs:14:5 + | +LL | type Assoc: Bar<N>; + | ------ required by this bound in `Foo::Assoc` +... +LL | type Assoc = u16; + | ^^^^^^^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `u16` + | + = help: the following implementations were found: + <u16 as Bar<3_usize>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/associated-type-bound-fail.rs b/src/test/ui/const-generics/associated-type-bound-fail.rs new file mode 100644 index 0000000000000..3440b1356c242 --- /dev/null +++ b/src/test/ui/const-generics/associated-type-bound-fail.rs @@ -0,0 +1,17 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(min, feature(min_const_generics))] + +trait Bar<const N: usize> {} + +trait Foo<const N: usize> { + type Assoc: Bar<N>; +} + +impl Bar<3> for u16 {} +impl<const N: usize> Foo<N> for i16 { + type Assoc = u16; //~ ERROR the trait bound `u16: Bar<N>` +} + +fn main() {} diff --git a/src/test/ui/const-generics/associated-type-bound.rs b/src/test/ui/const-generics/associated-type-bound.rs new file mode 100644 index 0000000000000..374a49194b178 --- /dev/null +++ b/src/test/ui/const-generics/associated-type-bound.rs @@ -0,0 +1,24 @@ +// run-pass +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(min, feature(min_const_generics))] + +trait Bar<const N: usize> {} + +trait Foo<const N: usize> { + type Assoc: Bar<N>; +} + +impl<const N: usize> Bar<N> for u8 {} +impl Bar<3> for u16 {} + +impl<const N: usize> Foo<N> for i8 { + type Assoc = u8; +} + +impl Foo<3> for i16 { + type Assoc = u16; +} + +fn main() {} diff --git a/src/test/ui/const-generics/auxiliary/crayte.rs b/src/test/ui/const-generics/auxiliary/crayte.rs new file mode 100644 index 0000000000000..725005971e1e9 --- /dev/null +++ b/src/test/ui/const-generics/auxiliary/crayte.rs @@ -0,0 +1,19 @@ +// edition:2018 +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] + +pub trait Foo<const N: usize> {} +struct Local; +impl<const N: usize> Foo<N> for Local {} + +pub fn out_foo<const N: usize>() -> impl Foo<N> { Local } +pub fn in_foo<const N: usize>(_: impl Foo<N>) {} + +pub async fn async_simple<const N: usize>(_: [u8; N]) {} +pub async fn async_out_foo<const N: usize>() -> impl Foo<N> { Local } +pub async fn async_in_foo<const N: usize>(_: impl Foo<N>) {} + +pub trait Bar<const N: usize> { + type Assoc: Foo<N>; +} diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr new file mode 100644 index 0000000000000..7dfe250b78e00 --- /dev/null +++ b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -0,0 +1,203 @@ +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:14:23 + | +LL | let _: [u8; foo::<T>()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:15:23 + | +LL | let _: [u8; bar::<N>()]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:25:23 + | +LL | let _ = [0; bar::<N>()]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:30:24 + | +LL | let _: Foo<{ foo::<T>() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:31:24 + | +LL | let _: Foo<{ bar::<N>() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:36:27 + | +LL | let _ = Foo::<{ foo::<T>() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:37:27 + | +LL | let _ = Foo::<{ bar::<N>() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:16:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:17:23 + | +LL | let _: [u8; baz::<'a>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:19:23 + | +LL | let _: [u8; baz::<'b>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:26:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:27:23 + | +LL | let _ = [0; baz::<'a>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:28:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:29:23 + | +LL | let _ = [0; baz::<'b>(&())]; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:32:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:33:24 + | +LL | let _: Foo<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:34:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:35:24 + | +LL | let _: Foo<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:38:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:39:27 + | +LL | let _ = Foo::<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:40:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:41:27 + | +LL | let _ = Foo::<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error: aborting due to 23 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.rs b/src/test/ui/const-generics/const-arg-in-const-arg.rs new file mode 100644 index 0000000000000..9927538ef50c6 --- /dev/null +++ b/src/test/ui/const-generics/const-arg-in-const-arg.rs @@ -0,0 +1,44 @@ +// revisions: min +// FIXME(const_generics): This test currently causes an ICE because +// we don't yet correctly deal with lifetimes, reenable this test once +// this is fixed. +#![cfg_attr(min, feature(min_const_generics))] + +const fn foo<T>() -> usize { std::mem::size_of::<T>() } +const fn bar<const N: usize>() -> usize { N } +const fn faz<'a>(_: &'a ()) -> usize { 13 } +const fn baz<'a>(_: &'a ()) -> usize where &'a (): Sized { 13 } + +struct Foo<const N: usize>; +fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { + let _: [u8; foo::<T>()]; //~ ERROR generic parameters may not + let _: [u8; bar::<N>()]; //~ ERROR generic parameters may not + let _: [u8; faz::<'a>(&())]; //~ ERROR a non-static lifetime + let _: [u8; baz::<'a>(&())]; //~ ERROR a non-static lifetime + let _: [u8; faz::<'b>(&())]; //~ ERROR a non-static lifetime + let _: [u8; baz::<'b>(&())]; //~ ERROR a non-static lifetime + + // NOTE: This can be a future compat warning instead of an error, + // so we stop compilation before emitting this error in this test. + let _ = [0; foo::<T>()]; + + let _ = [0; bar::<N>()]; //~ ERROR generic parameters may not + let _ = [0; faz::<'a>(&())]; //~ ERROR a non-static lifetime + let _ = [0; baz::<'a>(&())]; //~ ERROR a non-static lifetime + let _ = [0; faz::<'b>(&())]; //~ ERROR a non-static lifetime + let _ = [0; baz::<'b>(&())]; //~ ERROR a non-static lifetime + let _: Foo<{ foo::<T>() }>; //~ ERROR generic parameters may not + let _: Foo<{ bar::<N>() }>; //~ ERROR generic parameters may not + let _: Foo<{ faz::<'a>(&()) }>; //~ ERROR a non-static lifetime + let _: Foo<{ baz::<'a>(&()) }>; //~ ERROR a non-static lifetime + let _: Foo<{ faz::<'b>(&()) }>; //~ ERROR a non-static lifetime + let _: Foo<{ baz::<'b>(&()) }>; //~ ERROR a non-static lifetime + let _ = Foo::<{ foo::<T>() }>; //~ ERROR generic parameters may not + let _ = Foo::<{ bar::<N>() }>; //~ ERROR generic parameters may not + let _ = Foo::<{ faz::<'a>(&()) }>; //~ ERROR a non-static lifetime + let _ = Foo::<{ baz::<'a>(&()) }>; //~ ERROR a non-static lifetime + let _ = Foo::<{ faz::<'b>(&()) }>; //~ ERROR a non-static lifetime + let _ = Foo::<{ baz::<'b>(&()) }>; //~ ERROR a non-static lifetime +} + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-hygiene.rs b/src/test/ui/const-generics/const-param-hygiene.rs new file mode 100644 index 0000000000000..c8cefc36732b2 --- /dev/null +++ b/src/test/ui/const-generics/const-param-hygiene.rs @@ -0,0 +1,22 @@ +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] + +macro_rules! bar { + ($($t:tt)*) => { impl<const N: usize> $($t)* }; +} + +macro_rules! baz { + ($t:tt) => { fn test<const M: usize>(&self) -> usize { $t } }; +} + +struct Foo<const N: usize>; + +bar!(Foo<N> { baz!{ M } }); + +fn main() { + assert_eq!(Foo::<7>.test::<3>(), 3); +} diff --git a/src/test/ui/const-generics/const-param-in-async.rs b/src/test/ui/const-generics/const-param-in-async.rs new file mode 100644 index 0000000000000..e8601985287bd --- /dev/null +++ b/src/test/ui/const-generics/const-param-in-async.rs @@ -0,0 +1,35 @@ +// edition:2018 +// check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] + +async fn foo<const N: usize>(arg: [u8; N]) -> usize { arg.len() } + +async fn bar<const N: usize>() -> [u8; N] { + [0; N] +} + +trait Trait<const N: usize> { + fn fynn(&self) -> usize; +} +impl<const N: usize> Trait<N> for [u8; N] { + fn fynn(&self) -> usize { + N + } +} +async fn baz<const N: usize>() -> impl Trait<N> { + [0; N] +} + +async fn biz<const N: usize>(v: impl Trait<N>) -> usize { + v.fynn() +} + +async fn user<const N: usize>() { + let _ = foo::<N>(bar().await).await; + let _ = biz(baz::<N>().await).await; +} + +fn main() { } diff --git a/src/test/ui/const-generics/cross_crate_complex.rs b/src/test/ui/const-generics/cross_crate_complex.rs new file mode 100644 index 0000000000000..30749b8bc6d75 --- /dev/null +++ b/src/test/ui/const-generics/cross_crate_complex.rs @@ -0,0 +1,28 @@ +// aux-build:crayte.rs +// edition:2018 +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] +extern crate crayte; + +use crayte::*; + +async fn foo() { + in_foo(out_foo::<3>()); + async_simple([0; 17]).await; + async_in_foo(async_out_foo::<4>().await).await; +} + +struct Faz<const N: usize>; + +impl<const N: usize> Foo<N> for Faz<N> {} +impl<const N: usize> Bar<N> for Faz<N> { + type Assoc = Faz<N>; +} + +fn main() { + let _ = foo; +} diff --git a/src/test/ui/const-generics/exhaustive-value.full.stderr b/src/test/ui/const-generics/exhaustive-value.full.stderr new file mode 100644 index 0000000000000..fdea1fb0c3ead --- /dev/null +++ b/src/test/ui/const-generics/exhaustive-value.full.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): Foo<N>` is not satisfied + --> $DIR/exhaustive-value.rs:267:5 + | +LL | fn test() {} + | --------- required by `Foo::test` +... +LL | <() as Foo<N>>::test() + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<0_u8>> + <() as Foo<100_u8>> + <() as Foo<101_u8>> + <() as Foo<102_u8>> + and 252 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/exhaustive-value.min.stderr b/src/test/ui/const-generics/exhaustive-value.min.stderr new file mode 100644 index 0000000000000..fdea1fb0c3ead --- /dev/null +++ b/src/test/ui/const-generics/exhaustive-value.min.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): Foo<N>` is not satisfied + --> $DIR/exhaustive-value.rs:267:5 + | +LL | fn test() {} + | --------- required by `Foo::test` +... +LL | <() as Foo<N>>::test() + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<0_u8>> + <() as Foo<100_u8>> + <() as Foo<101_u8>> + <() as Foo<102_u8>> + and 252 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/exhaustive-value.rs b/src/test/ui/const-generics/exhaustive-value.rs new file mode 100644 index 0000000000000..fce036b0da624 --- /dev/null +++ b/src/test/ui/const-generics/exhaustive-value.rs @@ -0,0 +1,272 @@ +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] + +trait Foo<const N: u8> { + fn test() {} +} +impl Foo<0> for () {} +impl Foo<1> for () {} +impl Foo<2> for () {} +impl Foo<3> for () {} +impl Foo<4> for () {} +impl Foo<5> for () {} +impl Foo<6> for () {} +impl Foo<7> for () {} +impl Foo<8> for () {} +impl Foo<9> for () {} +impl Foo<10> for () {} +impl Foo<11> for () {} +impl Foo<12> for () {} +impl Foo<13> for () {} +impl Foo<14> for () {} +impl Foo<15> for () {} +impl Foo<16> for () {} +impl Foo<17> for () {} +impl Foo<18> for () {} +impl Foo<19> for () {} +impl Foo<20> for () {} +impl Foo<21> for () {} +impl Foo<22> for () {} +impl Foo<23> for () {} +impl Foo<24> for () {} +impl Foo<25> for () {} +impl Foo<26> for () {} +impl Foo<27> for () {} +impl Foo<28> for () {} +impl Foo<29> for () {} +impl Foo<30> for () {} +impl Foo<31> for () {} +impl Foo<32> for () {} +impl Foo<33> for () {} +impl Foo<34> for () {} +impl Foo<35> for () {} +impl Foo<36> for () {} +impl Foo<37> for () {} +impl Foo<38> for () {} +impl Foo<39> for () {} +impl Foo<40> for () {} +impl Foo<41> for () {} +impl Foo<42> for () {} +impl Foo<43> for () {} +impl Foo<44> for () {} +impl Foo<45> for () {} +impl Foo<46> for () {} +impl Foo<47> for () {} +impl Foo<48> for () {} +impl Foo<49> for () {} +impl Foo<50> for () {} +impl Foo<51> for () {} +impl Foo<52> for () {} +impl Foo<53> for () {} +impl Foo<54> for () {} +impl Foo<55> for () {} +impl Foo<56> for () {} +impl Foo<57> for () {} +impl Foo<58> for () {} +impl Foo<59> for () {} +impl Foo<60> for () {} +impl Foo<61> for () {} +impl Foo<62> for () {} +impl Foo<63> for () {} +impl Foo<64> for () {} +impl Foo<65> for () {} +impl Foo<66> for () {} +impl Foo<67> for () {} +impl Foo<68> for () {} +impl Foo<69> for () {} +impl Foo<70> for () {} +impl Foo<71> for () {} +impl Foo<72> for () {} +impl Foo<73> for () {} +impl Foo<74> for () {} +impl Foo<75> for () {} +impl Foo<76> for () {} +impl Foo<77> for () {} +impl Foo<78> for () {} +impl Foo<79> for () {} +impl Foo<80> for () {} +impl Foo<81> for () {} +impl Foo<82> for () {} +impl Foo<83> for () {} +impl Foo<84> for () {} +impl Foo<85> for () {} +impl Foo<86> for () {} +impl Foo<87> for () {} +impl Foo<88> for () {} +impl Foo<89> for () {} +impl Foo<90> for () {} +impl Foo<91> for () {} +impl Foo<92> for () {} +impl Foo<93> for () {} +impl Foo<94> for () {} +impl Foo<95> for () {} +impl Foo<96> for () {} +impl Foo<97> for () {} +impl Foo<98> for () {} +impl Foo<99> for () {} +impl Foo<100> for () {} +impl Foo<101> for () {} +impl Foo<102> for () {} +impl Foo<103> for () {} +impl Foo<104> for () {} +impl Foo<105> for () {} +impl Foo<106> for () {} +impl Foo<107> for () {} +impl Foo<108> for () {} +impl Foo<109> for () {} +impl Foo<110> for () {} +impl Foo<111> for () {} +impl Foo<112> for () {} +impl Foo<113> for () {} +impl Foo<114> for () {} +impl Foo<115> for () {} +impl Foo<116> for () {} +impl Foo<117> for () {} +impl Foo<118> for () {} +impl Foo<119> for () {} +impl Foo<120> for () {} +impl Foo<121> for () {} +impl Foo<122> for () {} +impl Foo<123> for () {} +impl Foo<124> for () {} +impl Foo<125> for () {} +impl Foo<126> for () {} +impl Foo<127> for () {} +impl Foo<128> for () {} +impl Foo<129> for () {} +impl Foo<130> for () {} +impl Foo<131> for () {} +impl Foo<132> for () {} +impl Foo<133> for () {} +impl Foo<134> for () {} +impl Foo<135> for () {} +impl Foo<136> for () {} +impl Foo<137> for () {} +impl Foo<138> for () {} +impl Foo<139> for () {} +impl Foo<140> for () {} +impl Foo<141> for () {} +impl Foo<142> for () {} +impl Foo<143> for () {} +impl Foo<144> for () {} +impl Foo<145> for () {} +impl Foo<146> for () {} +impl Foo<147> for () {} +impl Foo<148> for () {} +impl Foo<149> for () {} +impl Foo<150> for () {} +impl Foo<151> for () {} +impl Foo<152> for () {} +impl Foo<153> for () {} +impl Foo<154> for () {} +impl Foo<155> for () {} +impl Foo<156> for () {} +impl Foo<157> for () {} +impl Foo<158> for () {} +impl Foo<159> for () {} +impl Foo<160> for () {} +impl Foo<161> for () {} +impl Foo<162> for () {} +impl Foo<163> for () {} +impl Foo<164> for () {} +impl Foo<165> for () {} +impl Foo<166> for () {} +impl Foo<167> for () {} +impl Foo<168> for () {} +impl Foo<169> for () {} +impl Foo<170> for () {} +impl Foo<171> for () {} +impl Foo<172> for () {} +impl Foo<173> for () {} +impl Foo<174> for () {} +impl Foo<175> for () {} +impl Foo<176> for () {} +impl Foo<177> for () {} +impl Foo<178> for () {} +impl Foo<179> for () {} +impl Foo<180> for () {} +impl Foo<181> for () {} +impl Foo<182> for () {} +impl Foo<183> for () {} +impl Foo<184> for () {} +impl Foo<185> for () {} +impl Foo<186> for () {} +impl Foo<187> for () {} +impl Foo<188> for () {} +impl Foo<189> for () {} +impl Foo<190> for () {} +impl Foo<191> for () {} +impl Foo<192> for () {} +impl Foo<193> for () {} +impl Foo<194> for () {} +impl Foo<195> for () {} +impl Foo<196> for () {} +impl Foo<197> for () {} +impl Foo<198> for () {} +impl Foo<199> for () {} +impl Foo<200> for () {} +impl Foo<201> for () {} +impl Foo<202> for () {} +impl Foo<203> for () {} +impl Foo<204> for () {} +impl Foo<205> for () {} +impl Foo<206> for () {} +impl Foo<207> for () {} +impl Foo<208> for () {} +impl Foo<209> for () {} +impl Foo<210> for () {} +impl Foo<211> for () {} +impl Foo<212> for () {} +impl Foo<213> for () {} +impl Foo<214> for () {} +impl Foo<215> for () {} +impl Foo<216> for () {} +impl Foo<217> for () {} +impl Foo<218> for () {} +impl Foo<219> for () {} +impl Foo<220> for () {} +impl Foo<221> for () {} +impl Foo<222> for () {} +impl Foo<223> for () {} +impl Foo<224> for () {} +impl Foo<225> for () {} +impl Foo<226> for () {} +impl Foo<227> for () {} +impl Foo<228> for () {} +impl Foo<229> for () {} +impl Foo<230> for () {} +impl Foo<231> for () {} +impl Foo<232> for () {} +impl Foo<233> for () {} +impl Foo<234> for () {} +impl Foo<235> for () {} +impl Foo<236> for () {} +impl Foo<237> for () {} +impl Foo<238> for () {} +impl Foo<239> for () {} +impl Foo<240> for () {} +impl Foo<241> for () {} +impl Foo<242> for () {} +impl Foo<243> for () {} +impl Foo<244> for () {} +impl Foo<245> for () {} +impl Foo<246> for () {} +impl Foo<247> for () {} +impl Foo<248> for () {} +impl Foo<249> for () {} +impl Foo<250> for () {} +impl Foo<251> for () {} +impl Foo<252> for () {} +impl Foo<253> for () {} +impl Foo<254> for () {} +impl Foo<255> for () {} + +fn foo<const N: u8>() { + <() as Foo<N>>::test() //~ ERROR the trait bound `(): Foo<N>` +} + +fn main() { + foo::<7>(); +} diff --git a/src/test/ui/const-generics/generic-param-mismatch.full.stderr b/src/test/ui/const-generics/generic-param-mismatch.full.stderr new file mode 100644 index 0000000000000..6befa9d1f6994 --- /dev/null +++ b/src/test/ui/const-generics/generic-param-mismatch.full.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/generic-param-mismatch.rs:7:5 + | +LL | fn test<const N: usize, const M: usize>() -> [u8; M] { + | ------- expected `[u8; M]` because of return type +LL | [0; N] + | ^^^^^^ expected `M`, found `N` + | + = note: expected array `[u8; M]` + found array `[u8; N]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/generic-param-mismatch.min.stderr b/src/test/ui/const-generics/generic-param-mismatch.min.stderr new file mode 100644 index 0000000000000..6befa9d1f6994 --- /dev/null +++ b/src/test/ui/const-generics/generic-param-mismatch.min.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/generic-param-mismatch.rs:7:5 + | +LL | fn test<const N: usize, const M: usize>() -> [u8; M] { + | ------- expected `[u8; M]` because of return type +LL | [0; N] + | ^^^^^^ expected `M`, found `N` + | + = note: expected array `[u8; M]` + found array `[u8; N]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/generic-param-mismatch.rs b/src/test/ui/const-generics/generic-param-mismatch.rs new file mode 100644 index 0000000000000..e409094eb734c --- /dev/null +++ b/src/test/ui/const-generics/generic-param-mismatch.rs @@ -0,0 +1,10 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(min, feature(min_const_generics))] + +fn test<const N: usize, const M: usize>() -> [u8; M] { + [0; N] //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/const-generics/macro_rules-braces.full.stderr b/src/test/ui/const-generics/macro_rules-braces.full.stderr new file mode 100644 index 0000000000000..f6e9aabd90774 --- /dev/null +++ b/src/test/ui/const-generics/macro_rules-braces.full.stderr @@ -0,0 +1,61 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:34:17 + | +LL | let _: baz!(N); + | ^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ N }); + | ^ ^ + +error: constant expression depends on a generic parameter + --> $DIR/macro_rules-braces.rs:10:13 + | +LL | [u8; $x] + | ^^^^^^^^ +... +LL | let _: foo!({{ N }}); + | ------------- in this macro invocation + | + = note: this may fail depending on what value the parameter takes + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: constant expression depends on a generic parameter + --> $DIR/macro_rules-braces.rs:15:13 + | +LL | [u8; { $x }] + | ^^^^^^^^^^^^ +... +LL | let _: bar!({ N }); + | ----------- in this macro invocation + | + = note: this may fail depending on what value the parameter takes + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: constant expression depends on a generic parameter + --> $DIR/macro_rules-braces.rs:20:13 + | +LL | Foo<$x> + | ^^^^^^^ +... +LL | let _: baz!({{ N }}); + | ------------- in this macro invocation + | + = note: this may fail depending on what value the parameter takes + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: constant expression depends on a generic parameter + --> $DIR/macro_rules-braces.rs:25:13 + | +LL | Foo<{ $x }> + | ^^^^^^^^^^^ +... +LL | let _: biz!({ N }); + | ----------- in this macro invocation + | + = note: this may fail depending on what value the parameter takes + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/const-generics/macro_rules-braces.min.stderr b/src/test/ui/const-generics/macro_rules-braces.min.stderr new file mode 100644 index 0000000000000..1fe18e3fc0231 --- /dev/null +++ b/src/test/ui/const-generics/macro_rules-braces.min.stderr @@ -0,0 +1,45 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:34:17 + | +LL | let _: baz!(N); + | ^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ N }); + | ^ ^ + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:31:20 + | +LL | let _: foo!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:33:19 + | +LL | let _: bar!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:36:20 + | +LL | let _: baz!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:38:19 + | +LL | let _: biz!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/const-generics/macro_rules-braces.rs b/src/test/ui/const-generics/macro_rules-braces.rs new file mode 100644 index 0000000000000..c3e2c8ba20359 --- /dev/null +++ b/src/test/ui/const-generics/macro_rules-braces.rs @@ -0,0 +1,43 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(min, feature(min_const_generics))] + +fn test<const N: usize>() { + struct Foo<const M: usize>; + macro_rules! foo { + ($x:expr) => { + [u8; $x] //[full]~ ERROR constant expression depends + } + } + macro_rules! bar { + ($x:expr) => { + [u8; { $x }] //[full]~ ERROR constant expression depends + } + } + macro_rules! baz { + ( $x:expr) => { + Foo<$x> //[full]~ ERROR constant expression depends + } + } + macro_rules! biz { + ($x:expr) => { + Foo<{ $x }> //[full]~ ERROR constant expression depends + }; + } + + let _: foo!(N); + let _: foo!({ N }); + let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not + let _: bar!(N); + let _: bar!({ N }); //[min]~ ERROR generic parameters may not + let _: baz!(N); //~ ERROR expressions must be enclosed in braces + let _: baz!({ N }); + let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not + let _: biz!(N); + let _: biz!({ N }); //[min]~ ERROR generic parameters may not +} + +fn main() { + test::<3>(); +} diff --git a/src/test/ui/const-generics/where-clauses.rs b/src/test/ui/const-generics/where-clauses.rs new file mode 100644 index 0000000000000..cdcaf25094240 --- /dev/null +++ b/src/test/ui/const-generics/where-clauses.rs @@ -0,0 +1,35 @@ +// check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(min, feature(min_const_generics))] + +trait Bar<const N: usize> { fn bar() {} } +trait Foo<const N: usize>: Bar<N> {} + +fn test<T, const N: usize>() where T: Foo<N> { + <T as Bar<N>>::bar(); +} + +struct Faz<const N: usize>; + +impl<const N: usize> Faz<N> { + fn test<T>() where T: Foo<N> { + <T as Bar<N>>::bar() + } +} + +trait Fiz<const N: usize> { + fn fiz<T>() where T: Foo<N> { + <T as Bar<N>>::bar(); + } +} + +impl<const N: usize> Bar<N> for u8 {} +impl<const N: usize> Foo<N> for u8 {} +impl<const N: usize> Fiz<N> for u8 {} +fn main() { + test::<u8, 13>(); + Faz::<3>::test::<u8>(); + <u8 as Fiz<13>>::fiz::<u8>(); +}