diff options
Diffstat (limited to 'tests/ui/const-generics')
678 files changed, 15244 insertions, 0 deletions
diff --git a/tests/ui/const-generics/apit-with-const-param.rs b/tests/ui/const-generics/apit-with-const-param.rs new file mode 100644 index 000000000..2a04dc313 --- /dev/null +++ b/tests/ui/const-generics/apit-with-const-param.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Trait {} + +fn f<const N: usize>(_: impl Trait) {} + +fn main() {} diff --git a/tests/ui/const-generics/arg-in-pat-1.rs b/tests/ui/const-generics/arg-in-pat-1.rs new file mode 100644 index 000000000..82555084e --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-1.rs @@ -0,0 +1,23 @@ +// check-pass +enum ConstGenericEnum<const N: usize> { + Foo([i32; N]), + Bar, +} + +fn foo<const N: usize>(val: &ConstGenericEnum<N>) { + if let ConstGenericEnum::<N>::Foo(field, ..) = val {} +} + +fn bar<const N: usize>(val: &ConstGenericEnum<N>) { + match val { + ConstGenericEnum::<N>::Foo(field, ..) => (), + ConstGenericEnum::<N>::Bar => (), + } +} + +fn main() { + match ConstGenericEnum::Bar { + ConstGenericEnum::<3>::Foo(field, ..) => (), + ConstGenericEnum::<3>::Bar => (), + } +} diff --git a/tests/ui/const-generics/arg-in-pat-2.rs b/tests/ui/const-generics/arg-in-pat-2.rs new file mode 100644 index 000000000..dc9e722ed --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-2.rs @@ -0,0 +1,10 @@ +// check-pass +enum Generic<const N: usize> { + Variant, +} + +fn main() { + match todo!() { + Generic::<0usize>::Variant => todo!() + } +} diff --git a/tests/ui/const-generics/arg-in-pat-3.rs b/tests/ui/const-generics/arg-in-pat-3.rs new file mode 100644 index 000000000..24626a3b6 --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-3.rs @@ -0,0 +1,43 @@ +// check-pass +struct Foo<const N: usize>; + +fn bindingp() { + match Foo { + mut x @ Foo::<3> => { + let ref mut _x @ Foo::<3> = x; + } + } +} + +struct Bar<const N: usize> { + field: Foo<N>, +} + +fn structp() { + match todo!() { + Bar::<3> { + field: Foo::<3>, + } => (), + } +} + +struct Baz<const N: usize>(Foo<N>); + +fn tuplestructp() { + match Baz(Foo) { + Baz::<3>(Foo::<3>) => (), + } +} + +impl<const N: usize> Baz<N> { + const ASSOC: usize = 3; +} + +fn pathp() { + match 3 { + Baz::<3>::ASSOC => (), + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/const-generics/argument_order.rs b/tests/ui/const-generics/argument_order.rs new file mode 100644 index 000000000..196d9b8a1 --- /dev/null +++ b/tests/ui/const-generics/argument_order.rs @@ -0,0 +1,15 @@ +struct Bad<const N: usize, T> { + arr: [u8; { N }], + another: T, +} + +struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> { + //~^ ERROR lifetime parameters must be declared prior + a: &'a T, + b: &'b U, +} + +fn main() { + let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + //~^ ERROR lifetime provided when a type was expected + } diff --git a/tests/ui/const-generics/argument_order.stderr b/tests/ui/const-generics/argument_order.stderr new file mode 100644 index 000000000..99122c6f5 --- /dev/null +++ b/tests/ui/const-generics/argument_order.stderr @@ -0,0 +1,18 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/argument_order.rs:6:32 + | +LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> { + | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>` + +error[E0747]: lifetime provided when a type was expected + --> $DIR/argument_order.rs:13:23 + | +LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + | ^^^^^^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, N, T, M, U>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs new file mode 100644 index 000000000..b4a083636 --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs @@ -0,0 +1,48 @@ +// check-pass + +pub fn yes_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 32]> +where + A: PartialEq<B>, +{ + Vec::<A>::new() +} + +pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]> +where + A: PartialEq<B>, +{ + Vec::<A>::new() +} + +pub fn yes_array_into_vec<T>() -> Vec<T> { + [].into() +} + +pub fn yes_array_into_box<T>() -> Box<[T]> { + [].into() +} + +use std::collections::VecDeque; + +pub fn yes_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 32]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 32]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs new file mode 100644 index 000000000..35df3278a --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs @@ -0,0 +1,40 @@ +// check-pass + +pub fn yes_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]> +where + A: PartialEq<B>, +{ + Vec::<A>::new() +} + +pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]> +where + A: PartialEq<B>, +{ + Vec::<A>::new() +} + +use std::collections::VecDeque; + +pub fn yes_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]> +where + A: PartialEq<B>, +{ + VecDeque::<A>::new() +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs b/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs new file mode 100644 index 000000000..294b405e0 --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::{convert::TryFrom, rc::Rc, sync::Arc}; + +pub fn yes_vec() { + let v: Vec<_> = [0; 33].into(); +} + +pub fn yes_box() { + let boxed_slice = Box::new([0; 33]) as Box<[i32]>; + let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice); + let boxed_slice = <Box<[i32]>>::from([0; 33]); +} + +pub fn yes_rc() { + let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>; + let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice); +} + +pub fn yes_arc() { + let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>; + let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice); +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs b/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs new file mode 100644 index 000000000..9998bb84c --- /dev/null +++ b/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs @@ -0,0 +1,66 @@ +// check-pass + +pub fn yes_as_ref() -> impl AsRef<[u8]> { + [0; 32] +} + +pub fn yes_as_mut() -> impl AsMut<[u8]> { + [0; 32] +} + +pub fn yes_borrow() -> impl std::borrow::Borrow<[u8]> { + [0; 32] +} + +pub fn yes_borrow_mut() -> impl std::borrow::BorrowMut<[u8]> { + [0; 32] +} + +pub fn yes_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + [0; 32] +} + +pub fn yes_ref_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + let a: &'static _ = &[0; 32]; + a +} + +pub fn yes_hash() -> impl std::hash::Hash { + [0; 32] +} + +pub fn yes_debug() -> impl std::fmt::Debug { + [0; 32] +} + +pub fn yes_ref_into_iterator() -> impl IntoIterator<Item=&'static u8> { + let a: &'static _ = &[0; 32]; + a +} + +pub fn yes_partial_eq() -> impl PartialEq<[u8; 32]> { + [0; 32] +} + +pub fn yes_partial_eq_slice() -> impl PartialEq<[u8]> { + [0; 32] +} + +pub fn yes_slice_partial_eq() -> impl PartialEq<[u8; 32]> { + let a: &'static _ = &[0; 32]; + &a[..] +} + +pub fn yes_eq() -> impl Eq { + [0; 32] +} + +pub fn yes_partial_ord() -> impl PartialOrd<[u8; 32]> { + [0; 32] +} + +pub fn yes_ord() -> impl Ord { + [0; 32] +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs b/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs new file mode 100644 index 000000000..c609a7c6f --- /dev/null +++ b/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs @@ -0,0 +1,66 @@ +// check-pass + +pub fn yes_as_ref() -> impl AsRef<[u8]> { + [0; 33] +} + +pub fn yes_as_mut() -> impl AsMut<[u8]> { + [0; 33] +} + +pub fn yes_borrow() -> impl std::borrow::Borrow<[u8]> { + [0; 33] +} + +pub fn yes_borrow_mut() -> impl std::borrow::BorrowMut<[u8]> { + [0; 33] +} + +pub fn yes_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + [0; 33] +} + +pub fn yes_ref_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + let a: &'static _ = &[0; 33]; + a +} + +pub fn yes_hash() -> impl std::hash::Hash { + [0; 33] +} + +pub fn yes_debug() -> impl std::fmt::Debug { + [0; 33] +} + +pub fn yes_ref_into_iterator() -> impl IntoIterator<Item=&'static u8> { + let a: &'static _ = &[0; 33]; + a +} + +pub fn yes_partial_eq() -> impl PartialEq<[u8; 33]> { + [0; 33] +} + +pub fn yes_partial_eq_slice() -> impl PartialEq<[u8]> { + [0; 33] +} + +pub fn yes_slice_partial_eq() -> impl PartialEq<[u8; 33]> { + let a: &'static _ = &[0; 33]; + &a[..] +} + +pub fn yes_eq() -> impl Eq { + [0; 33] +} + +pub fn yes_partial_ord() -> impl PartialOrd<[u8; 33]> { + [0; 33] +} + +pub fn yes_ord() -> impl Ord { + [0; 33] +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs b/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs new file mode 100644 index 000000000..457e5ae60 --- /dev/null +++ b/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(trusted_len)] + +use std::{ + array::IntoIter, + fmt::Debug, + iter::{ExactSizeIterator, FusedIterator, TrustedLen}, +}; + +pub fn yes_iterator() -> impl Iterator<Item = i32> { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_exact_size_iterator() -> impl ExactSizeIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_fused_iterator() -> impl FusedIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_trusted_len() -> impl TrustedLen { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_clone() -> impl Clone { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_debug() -> impl Debug { + IntoIterator::into_iter([0i32; 32]) +} + + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs b/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs new file mode 100644 index 000000000..4f343f3f9 --- /dev/null +++ b/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(trusted_len)] + +use std::{ + array::IntoIter, + fmt::Debug, + iter::{ExactSizeIterator, FusedIterator, TrustedLen}, +}; + +pub fn yes_iterator() -> impl Iterator<Item = i32> { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_exact_size_iterator() -> impl ExactSizeIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_fused_iterator() -> impl FusedIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_trusted_len() -> impl TrustedLen { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_clone() -> impl Clone { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_debug() -> impl Debug { + IntoIterator::into_iter([0i32; 33]) +} + + +fn main() {} diff --git a/tests/ui/const-generics/array-wrapper-struct-ctor.rs b/tests/ui/const-generics/array-wrapper-struct-ctor.rs new file mode 100644 index 000000000..a712f691d --- /dev/null +++ b/tests/ui/const-generics/array-wrapper-struct-ctor.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(dead_code)] + +struct ArrayStruct<T, const N: usize> { + data: [T; N], +} + +struct ArrayTuple<T, const N: usize>([T; N]); + +fn main() { + let _ = ArrayStruct { data: [0u32; 8] }; + let _ = ArrayTuple([0u32; 8]); +} diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs new file mode 100644 index 000000000..4d0aaf88e --- /dev/null +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -0,0 +1,18 @@ +#![feature(associated_const_equality)] + +pub enum Mode { + Cool, +} + +pub trait Parse { + const MODE: Mode; +} + +pub trait CoolStuff: Parse<MODE = Mode::Cool> {} +//~^ ERROR expected associated constant bound +//~| ERROR expected type + +fn no_help() -> Mode::Cool {} +//~^ ERROR expected type, found variant + +fn main() {} diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr new file mode 100644 index 000000000..ba727ee0e --- /dev/null +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -0,0 +1,33 @@ +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 + | +LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:15:17 + | +LL | fn no_help() -> Mode::Cool {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error: expected associated constant bound, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:28 + | +LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {} + | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | +note: associated constant defined here + --> $DIR/assoc_const_eq_diagnostic.rs:8:5 + | +LL | const MODE: Mode; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/associated-type-bound-fail.rs b/tests/ui/const-generics/associated-type-bound-fail.rs new file mode 100644 index 000000000..937b8bcb6 --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound-fail.rs @@ -0,0 +1,12 @@ +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/tests/ui/const-generics/associated-type-bound-fail.stderr b/tests/ui/const-generics/associated-type-bound-fail.stderr new file mode 100644 index 000000000..e5e7ee26e --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound-fail.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `u16: Bar<N>` is not satisfied + --> $DIR/associated-type-bound-fail.rs:9:18 + | +LL | type Assoc = u16; + | ^^^ the trait `Bar<N>` is not implemented for `u16` + | + = help: the trait `Bar<3>` is implemented for `u16` +note: required by a bound in `Foo::Assoc` + --> $DIR/associated-type-bound-fail.rs:4:17 + | +LL | type Assoc: Bar<N>; + | ^^^^^^ required by this bound in `Foo::Assoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/associated-type-bound.rs b/tests/ui/const-generics/associated-type-bound.rs new file mode 100644 index 000000000..3044736b4 --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound.rs @@ -0,0 +1,19 @@ +// run-pass +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/tests/ui/const-generics/auxiliary/const_generic_lib.rs b/tests/ui/const-generics/auxiliary/const_generic_lib.rs new file mode 100644 index 000000000..922f92d9f --- /dev/null +++ b/tests/ui/const-generics/auxiliary/const_generic_lib.rs @@ -0,0 +1,7 @@ +pub struct Struct<const N: usize>(pub [u8; N]); + +pub type Alias = Struct<2>; + +pub fn function(value: Struct<3>) -> u8 { + value.0[0] +} diff --git a/tests/ui/const-generics/auxiliary/crayte.rs b/tests/ui/const-generics/auxiliary/crayte.rs new file mode 100644 index 000000000..19a8bb0f4 --- /dev/null +++ b/tests/ui/const-generics/auxiliary/crayte.rs @@ -0,0 +1,16 @@ +// edition:2018 + +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/tests/ui/const-generics/auxiliary/generics_of_parent.rs b/tests/ui/const-generics/auxiliary/generics_of_parent.rs new file mode 100644 index 000000000..5c2b1f4bd --- /dev/null +++ b/tests/ui/const-generics/auxiliary/generics_of_parent.rs @@ -0,0 +1,23 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// library portion of regression test for #87674 +pub struct Foo<const N: usize>([(); N + 1]) +where + [(); N + 1]: ; + +// library portion of regression test for #87603 +pub struct S<T: Copy + Default, const N: usize> +where + [T; N * 2]: Sized, +{ + pub s: [T; N * 2], +} +impl<T: Default + Copy, const N: usize> S<T, N> +where + [T; N * 2]: Sized, +{ + pub fn test() -> Self { + S { s: [T::default(); N * 2] } + } +} diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs new file mode 100644 index 000000000..cd5b8161d --- /dev/null +++ b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs @@ -0,0 +1,8 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// library portion of testing that `impl Trait<{ expr }>` doesnt +// ice because of a `DefKind::TyParam` parent +pub fn foo<const N: usize>(foo: impl Into<[(); N + 1]>) { + foo.into(); +} diff --git a/tests/ui/const-generics/auxiliary/legacy-const-generics.rs b/tests/ui/const-generics/auxiliary/legacy-const-generics.rs new file mode 100644 index 000000000..67352a2fb --- /dev/null +++ b/tests/ui/const-generics/auxiliary/legacy-const-generics.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_legacy_const_generics(1)] +pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] { + [x, Y, z] +} diff --git a/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs b/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs new file mode 100644 index 000000000..df1c99e86 --- /dev/null +++ b/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Trait<T> { + const ASSOC_CONST: usize = 0; +} + +impl Trait<()> for u8 {} + +// `u8::ASSOC_CONST` is resolved today, but will be ambiguous +// under lazy normalization. +fn foo<T, U>() -> [(T, U); u8::ASSOC_CONST] +where + u8: Trait<T> + Trait<U>, +{ + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/backcompat/unevaluated-consts.rs b/tests/ui/const-generics/backcompat/unevaluated-consts.rs new file mode 100644 index 000000000..3f90d22ae --- /dev/null +++ b/tests/ui/const-generics/backcompat/unevaluated-consts.rs @@ -0,0 +1,18 @@ +// check-pass + +// If we allow the parent generics here without using lazy normalization +// this results in a cycle error. +struct Foo<T, U>(T, U); + +impl<T> From<[u8; 1 + 1]> for Foo<T, [u8; 1 + 1]> { + fn from(value: [u8; 1 + 1]) -> Foo<T, [u8; 1 + 1]> { + todo!(); + } +} + +fn break_me<T>() +where + [u8; 1 + 1]: From<[u8; 1 + 1]> +{} + +fn main() {} diff --git a/tests/ui/const-generics/bad-const-generic-exprs.rs b/tests/ui/const-generics/bad-const-generic-exprs.rs new file mode 100644 index 000000000..ca91643ed --- /dev/null +++ b/tests/ui/const-generics/bad-const-generic-exprs.rs @@ -0,0 +1,22 @@ +struct Wow<const N: usize>; + +fn main() { + let _: Wow<if true {}>; + //~^ ERROR invalid const generic expression + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow<|| ()>; + //~^ ERROR invalid const generic expression + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow<A.b>; + //~^ ERROR expected one of + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow<A.0>; + //~^ ERROR expected one of + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + + // FIXME(compiler-errors): This one is still unsatisfying, + // and probably a case I could see someone typing by accident.. + let _: Wow<[12]>; + //~^ ERROR expected type, found + //~| ERROR type provided when a constant was expected +} diff --git a/tests/ui/const-generics/bad-const-generic-exprs.stderr b/tests/ui/const-generics/bad-const-generic-exprs.stderr new file mode 100644 index 000000000..24668b08b --- /dev/null +++ b/tests/ui/const-generics/bad-const-generic-exprs.stderr @@ -0,0 +1,59 @@ +error: invalid const generic expression + --> $DIR/bad-const-generic-exprs.rs:4:16 + | +LL | let _: Wow<if true {}>; + | ^^^^^^^^^^ + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ if true {} }>; + | + + + +error: invalid const generic expression + --> $DIR/bad-const-generic-exprs.rs:7:16 + | +LL | let _: Wow<|| ()>; + | ^^^^^ + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ || () }>; + | + + + +error: expected one of `,` or `>`, found `.` + --> $DIR/bad-const-generic-exprs.rs:10:17 + | +LL | let _: Wow<A.b>; + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ A.b }>; + | + + + +error: expected one of `,` or `>`, found `.` + --> $DIR/bad-const-generic-exprs.rs:13:17 + | +LL | let _: Wow<A.0>; + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ A.0 }>; + | + + + +error: expected type, found `12` + --> $DIR/bad-const-generic-exprs.rs:19:17 + | +LL | let _: Wow<[12]>; + | ^^ expected type + +error[E0747]: type provided when a constant was expected + --> $DIR/bad-const-generic-exprs.rs:19:16 + | +LL | let _: Wow<[12]>; + | ^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/broken-mir-1.rs b/tests/ui/const-generics/broken-mir-1.rs new file mode 100644 index 000000000..6b6140e3a --- /dev/null +++ b/tests/ui/const-generics/broken-mir-1.rs @@ -0,0 +1,13 @@ +// run-pass +pub trait Foo { + fn foo(&self); +} + + +impl<T, const N: usize> Foo for [T; N] { + fn foo(&self) { + let _ = &self; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/broken-mir-2.rs b/tests/ui/const-generics/broken-mir-2.rs new file mode 100644 index 000000000..9d6228117 --- /dev/null +++ b/tests/ui/const-generics/broken-mir-2.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(dead_code)] + +use std::fmt::Debug; + +#[derive(Debug)] +struct S<T: Debug, const N: usize>([T; N]); + +fn main() {} diff --git a/tests/ui/const-generics/cannot-infer-type-for-const-param.rs b/tests/ui/const-generics/cannot-infer-type-for-const-param.rs new file mode 100644 index 000000000..a6e767489 --- /dev/null +++ b/tests/ui/const-generics/cannot-infer-type-for-const-param.rs @@ -0,0 +1,10 @@ +// check-pass + +// This test confirms that the types can be inferred correctly for this example with const +// generics. Previously this would ICE, and more recently error. + +struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]); + +fn main() { + let _ = Foo::<3>([1, 2, 3]); +} diff --git a/tests/ui/const-generics/coerce_unsized_array.rs b/tests/ui/const-generics/coerce_unsized_array.rs new file mode 100644 index 000000000..ffd5eb9d4 --- /dev/null +++ b/tests/ui/const-generics/coerce_unsized_array.rs @@ -0,0 +1,8 @@ +// run-pass +fn foo<const N: usize>(v: &[u8; N]) -> &[u8] { + v +} + +fn main() { + assert_eq!(foo(&[1, 2]), &[1, 2]); +} diff --git a/tests/ui/const-generics/concrete-const-as-fn-arg.rs b/tests/ui/const-generics/concrete-const-as-fn-arg.rs new file mode 100644 index 000000000..372f0433e --- /dev/null +++ b/tests/ui/const-generics/concrete-const-as-fn-arg.rs @@ -0,0 +1,11 @@ +// Test that a concrete const type i.e. A<2>, can be used as an argument type in a function +// run-pass + +struct A<const N: usize>; // ok + +fn with_concrete_const_arg(_: A<2>) -> u32 { 17 } + +fn main() { + let val: A<2> = A; + assert_eq!(with_concrete_const_arg(val), 17); +} diff --git a/tests/ui/const-generics/concrete-const-impl-method.rs b/tests/ui/const-generics/concrete-const-impl-method.rs new file mode 100644 index 000000000..53c9c0ead --- /dev/null +++ b/tests/ui/const-generics/concrete-const-impl-method.rs @@ -0,0 +1,21 @@ +// Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>, +// is callable. +// run-pass + +pub struct A<const N: u32>; + +impl A<2> { + fn impl_method(&self) -> u32 { + 17 + } + + fn associated_non_method() -> u32 { + 17 + } +} + +fn main() { + let val: A<2> = A; + assert_eq!(val.impl_method(), 17); + assert_eq!(A::<2>::associated_non_method(), 17); +} diff --git a/tests/ui/const-generics/condition-in-trait-const-arg.rs b/tests/ui/const-generics/condition-in-trait-const-arg.rs new file mode 100644 index 000000000..6f85237cf --- /dev/null +++ b/tests/ui/const-generics/condition-in-trait-const-arg.rs @@ -0,0 +1,14 @@ +// Checks that `impl Trait<{anon_const}> for Type` evaluates successfully. +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +trait IsZeroTrait<const IS_ZERO: bool>{} + +impl IsZeroTrait<{0u8 == 0u8}> for () {} + +impl IsZeroTrait<true> for ((),) {} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr new file mode 100644 index 000000000..8672e79b3 --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr @@ -0,0 +1,162 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:13:12 + | +LL | let _: [u8; foo::<T>()]; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); foo::<T>()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:15:12 + | +LL | let _: [u8; bar::<N>()]; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); bar::<N>()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:36:12 + | +LL | let _: Foo<{ foo::<T>() }>; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { foo::<T>() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:38:12 + | +LL | let _: Foo<{ bar::<N>() }>; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { bar::<N>() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:25:17 + | +LL | let _ = [0; foo::<T>()]; + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); foo::<T>()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:27:17 + | +LL | let _ = [0; bar::<N>()]; + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); bar::<N>()]:` + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:33:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:47:19 + | +LL | let _ = Foo::<{ foo::<T>() }>; + | ^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { foo::<T>() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:49:19 + | +LL | let _ = Foo::<{ bar::<N>() }>; + | ^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { bar::<N>() }]:` + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr new file mode 100644 index 000000000..f1353aa99 --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -0,0 +1,359 @@ +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:13:23 + | +LL | let _: [u8; foo::<T>()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic 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` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +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::<'a>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:20:23 + | +LL | let _: [u8; baz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:23:23 + | +LL | let _: [u8; baz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:27: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` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:23 + | +LL | let _ = [0; baz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:23 + | +LL | let _ = [0; baz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:36:24 + | +LL | let _: Foo<{ foo::<T>() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:38: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` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:43:24 + | +LL | let _: Foo<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:46:24 + | +LL | let _: Foo<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:47:27 + | +LL | let _ = Foo::<{ foo::<T>() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:49: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` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:54:27 + | +LL | let _ = Foo::<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` 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:57:27 + | +LL | let _ = Foo::<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:15:23 + | +LL | let _: [u8; bar::<N>()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: [u8; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:38:24 + | +LL | let _: Foo<{ bar::<N>() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Foo<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: constant expression depends on a generic parameter + --> $DIR/const-arg-in-const-arg.rs:25:17 + | +LL | let _ = [0; foo::<T>()]; + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:27:23 + | +LL | let _ = [0; bar::<N>()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = [0; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:33:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:49:27 + | +LL | let _ = Foo::<{ bar::<N>() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = Foo::<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: aborting due to 36 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.rs b/tests/ui/const-generics/const-arg-in-const-arg.rs new file mode 100644 index 000000000..44a4f560a --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.rs @@ -0,0 +1,60 @@ +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +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>()]; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _: [u8; bar::<N>()]; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _: [u8; faz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: [u8; baz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + let _: [u8; faz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: [u8; baz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + + let _ = [0; foo::<T>()]; //[min]~ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR unconstrained generic constant + let _ = [0; bar::<N>()]; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _ = [0; faz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = [0; baz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + let _ = [0; faz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = [0; baz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + let _: Foo<{ foo::<T>() }>; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _: Foo<{ bar::<N>() }>; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _: Foo<{ faz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: Foo<{ baz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + let _: Foo<{ faz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: Foo<{ baz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + let _ = Foo::<{ foo::<T>() }>; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _ = Foo::<{ bar::<N>() }>; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _ = Foo::<{ faz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = Foo::<{ baz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + let _ = Foo::<{ faz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = Foo::<{ baz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime +} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-in-fn.rs b/tests/ui/const-generics/const-arg-in-fn.rs new file mode 100644 index 000000000..9b225b18d --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-fn.rs @@ -0,0 +1,9 @@ +// run-pass +fn const_u32_identity<const X: u32>() -> u32 { + X +} + + fn main() { + let val = const_u32_identity::<18>(); + assert_eq!(val, 18); +} diff --git a/tests/ui/const-generics/const-arg-type-arg-misordered.rs b/tests/ui/const-generics/const-arg-type-arg-misordered.rs new file mode 100644 index 000000000..8ee17e637 --- /dev/null +++ b/tests/ui/const-generics/const-arg-type-arg-misordered.rs @@ -0,0 +1,8 @@ +type Array<T, const N: usize> = [T; N]; + +fn foo<const N: usize>() -> Array<N, ()> { + //~^ ERROR constant provided when a type was expected + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-type-arg-misordered.stderr b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr new file mode 100644 index 000000000..4e12f7a8c --- /dev/null +++ b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -0,0 +1,9 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/const-arg-type-arg-misordered.rs:3:35 + | +LL | fn foo<const N: usize>() -> Array<N, ()> { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs b/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs new file mode 100644 index 000000000..d863d097d --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs @@ -0,0 +1,10 @@ +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +fn main() { + let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + //~^ ERROR mismatched types + let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr new file mode 100644 index 000000000..d5eefd357 --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:6:67 + | +LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + | ------------------------- ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/auxiliary/const_generic_lib.rs:1:12 + | +LL | pub struct Struct<const N: usize>(pub [u8; N]); + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:8:65 + | +LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + | ------------------------- ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/auxiliary/const_generic_lib.rs:1:12 + | +LL | pub struct Struct<const N: usize>(pub [u8; N]); + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/const-argument-cross-crate.rs b/tests/ui/const-generics/const-argument-cross-crate.rs new file mode 100644 index 000000000..5693409e9 --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// revisions: full min +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +struct Container(#[allow(unused_tuple_struct_fields)] const_generic_lib::Alias); + +fn main() { + let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8])); + assert_eq!(res, 14u8); + let _ = Container(const_generic_lib::Struct([0u8, 1u8])); +} diff --git a/tests/ui/const-generics/const-argument-if-length.full.stderr b/tests/ui/const-generics/const-argument-if-length.full.stderr new file mode 100644 index 000000000..2ceba59cf --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.full.stderr @@ -0,0 +1,35 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-argument-if-length.rs:15:12 + | +LL | pub struct AtLeastByte<T: ?Sized> { + | - this type parameter needs to be `std::marker::Sized` +LL | value: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - pub struct AtLeastByte<T: ?Sized> { +LL + pub struct AtLeastByte<T> { + | +help: borrowed types always have a statically known size + | +LL | value: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box<T>, + | ++++ + + +error: unconstrained generic constant + --> $DIR/const-argument-if-length.rs:17:10 + | +LL | pad: [u8; is_zst::<T>()], + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/const-argument-if-length.min.stderr b/tests/ui/const-generics/const-argument-if-length.min.stderr new file mode 100644 index 000000000..f85e60f63 --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.min.stderr @@ -0,0 +1,36 @@ +error: generic parameters may not be used in const operations + --> $DIR/const-argument-if-length.rs:17:24 + | +LL | pad: [u8; is_zst::<T>()], + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-argument-if-length.rs:15:12 + | +LL | pub struct AtLeastByte<T: ?Sized> { + | - this type parameter needs to be `std::marker::Sized` +LL | value: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - pub struct AtLeastByte<T: ?Sized> { +LL + pub struct AtLeastByte<T> { + | +help: borrowed types always have a statically known size + | +LL | value: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box<T>, + | ++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/const-argument-if-length.rs b/tests/ui/const-generics/const-argument-if-length.rs new file mode 100644 index 000000000..db1eafca2 --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.rs @@ -0,0 +1,22 @@ +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +pub const fn is_zst<T: ?Sized>() -> usize { + if std::mem::size_of::<T>() == 0 { + 1 + } else { + 0 + } +} + +pub struct AtLeastByte<T: ?Sized> { + value: T, + //~^ ERROR the size for values of type `T` cannot be known at compilation time + pad: [u8; is_zst::<T>()], + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr new file mode 100644 index 000000000..f1f3a9c3d --- /dev/null +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr @@ -0,0 +1,12 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-argument-non-static-lifetime.rs:15:17 + | +LL | let _: &'a (); + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.rs b/tests/ui/const-generics/const-argument-non-static-lifetime.rs new file mode 100644 index 000000000..36a569784 --- /dev/null +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.rs @@ -0,0 +1,21 @@ +// [full] check-pass +// revisions: full min + +// regression test for #78180 +// compile-flags: -Zsave-analysis + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] +#![allow(dead_code)] + +fn test<const N: usize>() {} + +fn wow<'a>() -> &'a () { + test::<{ + let _: &'a (); //[min]~ ERROR a non-static lifetime + 3 + }>(); + &() +} + +fn main() {} diff --git a/tests/ui/const-generics/const-fn-with-const-param.rs b/tests/ui/const-generics/const-fn-with-const-param.rs new file mode 100644 index 000000000..161bfaab4 --- /dev/null +++ b/tests/ui/const-generics/const-fn-with-const-param.rs @@ -0,0 +1,10 @@ +// Checks that `const fn` with const params can be used. +// run-pass + +const fn const_u32_identity<const X: u32>() -> u32 { + X +} + +fn main() { + assert_eq!(const_u32_identity::<18>(), 18); +} diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.rs b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs new file mode 100644 index 000000000..e64adacac --- /dev/null +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs @@ -0,0 +1,5 @@ +struct X<const N: usize = { + let s: &'static str; s.len() //~ ERROR E0381 +}>; + +fn main() {} diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr new file mode 100644 index 000000000..0ed370b83 --- /dev/null +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `s` isn't initialized + --> $DIR/const-generic-default-wont-borrowck.rs:2:26 + | +LL | let s: &'static str; s.len() + | - ^^^^^^^ `*s` used here but it isn't initialized + | | + | binding declared here but left uninitialized + | +help: consider assigning a value + | +LL | let s: &'static str = todo!(); s.len() + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/const-generics/const-generic-function.rs b/tests/ui/const-generics/const-generic-function.rs new file mode 100644 index 000000000..c8d2683e5 --- /dev/null +++ b/tests/ui/const-generics/const-generic-function.rs @@ -0,0 +1,21 @@ +fn foo<const N: i32>() -> i32 { + N +} + +const fn bar(n: i32, m: i32) -> i32 { + n +} + +const fn baz() -> i32 { + 1 +} + +const FOO: i32 = 3; + +fn main() { + foo::<baz()>(); //~ ERROR expected type, found function `baz` + //~| ERROR unresolved item provided when a constant was expected + foo::<bar(bar(1, 1), bar(1, 1))>(); //~ ERROR expected type, found `1` + foo::<bar(1, 1)>(); //~ ERROR expected type, found `1` + foo::<bar(FOO, 2)>(); //~ ERROR expected type, found `2` +} diff --git a/tests/ui/const-generics/const-generic-function.stderr b/tests/ui/const-generics/const-generic-function.stderr new file mode 100644 index 000000000..5ad3f1006 --- /dev/null +++ b/tests/ui/const-generics/const-generic-function.stderr @@ -0,0 +1,54 @@ +error: expected type, found `1` + --> $DIR/const-generic-function.rs:18:19 + | +LL | foo::<bar(bar(1, 1), bar(1, 1))>(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(bar(1, 1), bar(1, 1)) }>(); + | + + + +error: expected type, found `1` + --> $DIR/const-generic-function.rs:19:15 + | +LL | foo::<bar(1, 1)>(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(1, 1) }>(); + | + + + +error: expected type, found `2` + --> $DIR/const-generic-function.rs:20:20 + | +LL | foo::<bar(FOO, 2)>(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(FOO, 2) }>(); + | + + + +error[E0573]: expected type, found function `baz` + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::<baz()>(); + | ^^^^^ not a type + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::<baz()>(); + | ^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | foo::<{ baz() }>(); + | + + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0573, E0747. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/const-generic-type_name.rs b/tests/ui/const-generics/const-generic-type_name.rs new file mode 100644 index 000000000..bb16be9c5 --- /dev/null +++ b/tests/ui/const-generics/const-generic-type_name.rs @@ -0,0 +1,8 @@ +// run-pass + +#[derive(Debug)] +struct S<const N: usize>; + +fn main() { + assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3>"); +} diff --git a/tests/ui/const-generics/const-param-after-const-literal-arg.rs b/tests/ui/const-generics/const-param-after-const-literal-arg.rs new file mode 100644 index 000000000..d8a0e076e --- /dev/null +++ b/tests/ui/const-generics/const-param-after-const-literal-arg.rs @@ -0,0 +1,7 @@ +// check-pass + +struct Foo<const A: usize, const B: usize>; + +impl<const A: usize> Foo<1, A> {} // ok + +fn main() {} diff --git a/tests/ui/const-generics/const-param-before-other-params.rs b/tests/ui/const-generics/const-param-before-other-params.rs new file mode 100644 index 000000000..cb1cebe1f --- /dev/null +++ b/tests/ui/const-generics/const-param-before-other-params.rs @@ -0,0 +1,7 @@ +fn bar<const X: u8, 'a>(_: &'a ()) { + //~^ ERROR lifetime parameters must be declared prior to type and const parameters +} + +fn foo<const X: u8, T>(_: &T) {} + +fn main() {} diff --git a/tests/ui/const-generics/const-param-before-other-params.stderr b/tests/ui/const-generics/const-param-before-other-params.stderr new file mode 100644 index 000000000..2c7a47bbc --- /dev/null +++ b/tests/ui/const-generics/const-param-before-other-params.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/const-param-before-other-params.rs:1:21 + | +LL | fn bar<const X: u8, 'a>(_: &'a ()) { + | --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: u8>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/const-param-elided-lifetime.full.stderr b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr new file mode 100644 index 000000000..d6753a74f --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr @@ -0,0 +1,33 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A<const N: &u8>; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl<const N: &u8> A<N> { + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo<const M: &u8>(&self) {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl<const N: &u8> B for A<N> {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar<const N: &u8>() {} + | ^ explicit lifetime name needed here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr new file mode 100644 index 000000000..4bba42c77 --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -0,0 +1,78 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A<const N: &u8>; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl<const N: &u8> A<N> { + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo<const M: &u8>(&self) {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl<const N: &u8> B for A<N> {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar<const N: &u8>() {} + | ^ explicit lifetime name needed here + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A<const N: &u8>; + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl<const N: &u8> A<N> { + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl<const N: &u8> B for A<N> {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar<const N: &u8>() {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo<const M: &u8>(&self) {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.rs b/tests/ui/const-generics/const-param-elided-lifetime.rs new file mode 100644 index 000000000..487b82dbf --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.rs @@ -0,0 +1,30 @@ +// Elided lifetimes within the type of a const generic parameters is disallowed. This matches the +// behaviour of trait bounds where `fn foo<T: Ord<&u8>>() {}` is illegal. Though we could change +// elided lifetimes within the type of a const generic parameters to be 'static, like elided +// lifetimes within const/static items. +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct A<const N: &u8>; +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden +trait B {} + +impl<const N: &u8> A<N> { +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + fn foo<const M: &u8>(&self) {} + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //[min]~^^ ERROR `&'static u8` is forbidden +} + +impl<const N: &u8> B for A<N> {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + +fn bar<const N: &u8>() {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/const-param-in-async.rs b/tests/ui/const-generics/const-param-in-async.rs new file mode 100644 index 000000000..f823431e6 --- /dev/null +++ b/tests/ui/const-generics/const-param-in-async.rs @@ -0,0 +1,31 @@ +// edition:2018 +// check-pass + +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/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr new file mode 100644 index 000000000..f639e276f --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 + | +LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]); + | ^ the type must not depend on the parameter `N` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 + | +LL | pub struct SelfDependent<const N: [u8; N]>; + | ^ the type must not depend on the parameter `N` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr new file mode 100644 index 000000000..24aa40521 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -0,0 +1,33 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 + | +LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]); + | ^ the type must not depend on the parameter `N` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 + | +LL | pub struct SelfDependent<const N: [u8; N]>; + | ^ the type must not depend on the parameter `N` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/const-param-type-depends-on-const-param.rs:11:47 + | +LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]); + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/const-param-type-depends-on-const-param.rs:15:35 + | +LL | pub struct SelfDependent<const N: [u8; N]>; + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs new file mode 100644 index 000000000..64b2acb03 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// Currently, const parameters cannot depend on other generic parameters, +// as our current implementation can't really support this. +// +// We may want to lift this restriction in the future. + +pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]); +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//[min]~^^ ERROR `[u8; N]` is forbidden + +pub struct SelfDependent<const N: [u8; N]>; +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//[min]~^^ ERROR `[u8; N]` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs new file mode 100644 index 000000000..781f50e61 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zsave-analysis +// Regression test for #69414 ^ + +use std::marker::PhantomData; + +struct B<T, const N: T>(PhantomData<[T; N]>); +//~^ ERROR the type of const parameters must not depend on other generic parameters + +fn main() {} diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr new file mode 100644 index 000000000..8e14defd6 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:22 + | +LL | struct B<T, const N: T>(PhantomData<[T; N]>); + | ^ the type must not depend on the parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr new file mode 100644 index 000000000..32f7dea82 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr @@ -0,0 +1,19 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 + | +LL | pub struct Dependent<T, const X: T>([(); X]); + | ^ the type must not depend on the parameter `T` + +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent<T, const X: T>([(); X]); + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr new file mode 100644 index 000000000..32f7dea82 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr @@ -0,0 +1,19 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 + | +LL | pub struct Dependent<T, const X: T>([(); X]); + | ^ the type must not depend on the parameter `T` + +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent<T, const X: T>([(); X]); + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs new file mode 100644 index 000000000..71d91fd7e --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -0,0 +1,15 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// Currently, const parameters cannot depend on other generic parameters, +// as our current implementation can't really support this. +// +// We may want to lift this restriction in the future. + +pub struct Dependent<T, const X: T>([(); X]); +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//~| ERROR: parameter `T` is never used + +fn main() {} diff --git a/tests/ui/const-generics/const-parameter-uppercase-lint.rs b/tests/ui/const-generics/const-parameter-uppercase-lint.rs new file mode 100644 index 000000000..b08d62ccc --- /dev/null +++ b/tests/ui/const-generics/const-parameter-uppercase-lint.rs @@ -0,0 +1,7 @@ +#![deny(non_upper_case_globals)] + +fn noop<const x: u32>() { + //~^ ERROR const parameter `x` should have an upper case name +} + +fn main() {} diff --git a/tests/ui/const-generics/const-parameter-uppercase-lint.stderr b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr new file mode 100644 index 000000000..efaa18285 --- /dev/null +++ b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -0,0 +1,14 @@ +error: const parameter `x` should have an upper case name + --> $DIR/const-parameter-uppercase-lint.rs:3:15 + | +LL | fn noop<const x: u32>() { + | ^ help: convert the identifier to upper case (notice the capitalization): `X` + | +note: the lint level is defined here + --> $DIR/const-parameter-uppercase-lint.rs:1:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs new file mode 100644 index 000000000..6e04cfaec --- /dev/null +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -0,0 +1,27 @@ +// build-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Func<T> { + type Output; + + fn call_once(self, arg: T) -> Self::Output; +} + + +struct Closure; + +impl const Func<&usize> for Closure { + type Output = usize; + + fn call_once(self, arg: &usize) -> Self::Output { + *arg + } +} + +enum Bug<T = [(); Closure.call_once(&0) ]> { + V(T), +} + +fn main() {} diff --git a/tests/ui/const-generics/core-types.rs b/tests/ui/const-generics/core-types.rs new file mode 100644 index 000000000..91410c4af --- /dev/null +++ b/tests/ui/const-generics/core-types.rs @@ -0,0 +1,50 @@ +// Check that all types allowed with `min_const_generics` work. +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct A<const N: u8>; +struct B<const N: u16>; +struct C<const N: u32>; +struct D<const N: u64>; +struct E<const N: u128>; +struct F<const N: usize>; +struct G<const N: i8>; +struct H<const N: i16>; +struct I<const N: i32>; +struct J<const N: i64>; +struct K<const N: i128>; +struct L<const N: isize>; +struct M<const N: char>; +struct N<const N: bool>; + +fn main() { + let _ = A::<{u8::MIN}>; + let _ = A::<{u8::MAX}>; + let _ = B::<{u16::MIN}>; + let _ = B::<{u16::MAX}>; + let _ = C::<{u32::MIN}>; + let _ = C::<{u32::MAX}>; + let _ = D::<{u64::MIN}>; + let _ = D::<{u64::MAX}>; + let _ = E::<{u128::MIN}>; + let _ = E::<{u128::MAX}>; + let _ = F::<{usize::MIN}>; + let _ = F::<{usize::MAX}>; + let _ = G::<{i8::MIN}>; + let _ = G::<{i8::MAX}>; + let _ = H::<{i16::MIN}>; + let _ = H::<{i16::MAX}>; + let _ = I::<{i32::MIN}>; + let _ = I::<{i32::MAX}>; + let _ = J::<{i64::MIN}>; + let _ = J::<{i64::MAX}>; + let _ = K::<{i128::MIN}>; + let _ = K::<{i128::MAX}>; + let _ = L::<{isize::MIN}>; + let _ = L::<{isize::MAX}>; + let _ = M::<'A'>; + let _ = N::<true>; +} diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs new file mode 100644 index 000000000..ebde155f7 --- /dev/null +++ b/tests/ui/const-generics/cross_crate_complex.rs @@ -0,0 +1,23 @@ +// aux-build:crayte.rs +// edition:2018 +// run-pass +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/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs new file mode 100644 index 000000000..eed982534 --- /dev/null +++ b/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -0,0 +1,11 @@ +pub struct Defaulted<const N: usize=3>; +impl Defaulted { + pub fn new() -> Self { + Defaulted + } +} +impl<const N: usize> Defaulted<N> { + pub fn value(&self) -> usize { + N + } +} diff --git a/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs b/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs new file mode 100644 index 000000000..26a2c47ff --- /dev/null +++ b/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs @@ -0,0 +1 @@ +pub struct Foo<'a, const N: usize, T: 'a + ?Sized>(pub &'a T, [(); N]); diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 000000000..b836cfeae --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo<const N: usize, const M: usize = { N + 1 }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:9:62 + | +LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.rs b/tests/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 000000000..7f50d4c9f --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,12 @@ +// revisions: full min +//[full] check-pass +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo<const N: usize, const M: usize = { N + 1 }>; +//[min]~^ ERROR generic parameters may not be used in const operations + +struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T); +//[min]~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/defaults/complex-unord-param.rs b/tests/ui/const-generics/defaults/complex-unord-param.rs new file mode 100644 index 000000000..aebc5975a --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-unord-param.rs @@ -0,0 +1,17 @@ +// run-pass +// Checks a complicated usage of unordered params +#![allow(dead_code)] + +struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { + args: &'a [&'a [T; M]; N], + specifier: A, +} + +fn main() { + let array = [1, 2, 3]; + let nest = [&array]; + let _ = NestedArrays { + args: &nest, + specifier: true, + }; +} diff --git a/tests/ui/const-generics/defaults/const-default.rs b/tests/ui/const-generics/defaults/const-default.rs new file mode 100644 index 000000000..65cb0eb14 --- /dev/null +++ b/tests/ui/const-generics/defaults/const-default.rs @@ -0,0 +1,24 @@ +// run-pass +pub struct ConstDefault<const N: usize = 3>; + +impl<const N: usize> ConstDefault<N> { + fn foo(self) -> usize { + N + } +} + +impl ConstDefault { + fn new() -> Self { + ConstDefault + } + + fn bar(self) {} +} + +pub fn main() { + let s = ConstDefault::new(); + assert_eq!(s.foo(), 3); + + let w = ConstDefault::<3>; + w.bar(); +} diff --git a/tests/ui/const-generics/defaults/const-param-as-default-value.rs b/tests/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 000000000..c1c955d87 --- /dev/null +++ b/tests/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,21 @@ +// run-pass +struct Foo<const N: usize, const M: usize = N>([u8; N], [u8; M]); + +fn foo<const N: usize>() -> Foo<N> { + let x = [0; N]; + Foo(x, x) +} + +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); +} diff --git a/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 000000000..5f0cafe2e --- /dev/null +++ b/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,12 @@ +// run-pass +struct Foo<const N: usize, T = [u8; N]>(T); + +impl<const N: usize> Foo<N> { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/tests/ui/const-generics/defaults/default-annotation.rs b/tests/ui/const-generics/defaults/default-annotation.rs new file mode 100644 index 000000000..7a9f5732f --- /dev/null +++ b/tests/ui/const-generics/defaults/default-annotation.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(staged_api)] +#![allow(incomplete_features)] +// FIXME(const_generics_defaults): It seems like we aren't testing the right thing here, +// I would assume that we want the attributes to apply to the const parameter defaults +// themselves. +#![stable(feature = "const_default_test", since="none")] + +#[unstable(feature = "const_default_stable", issue="none")] +pub struct ConstDefaultUnstable<const N: usize = 3>; + +#[stable(feature = "const_default_unstable", since="none")] +pub struct ConstDefaultStable<const N: usize = { + 3 +}>; + +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs new file mode 100644 index 000000000..45275e609 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs @@ -0,0 +1,14 @@ +struct Struct<const N: usize = { Self; 10 }>; +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +enum Enum<const N: usize = { Self; 10 }> { } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +union Union<const N: usize = { Self; 10 }> { not_empty: () } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +fn main() { + let _: Struct; + let _: Enum; + let _: Union; +} diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr new file mode 100644 index 000000000..72d7001fd --- /dev/null +++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr @@ -0,0 +1,21 @@ +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:1:34 + | +LL | struct Struct<const N: usize = { Self; 10 }>; + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:4:30 + | +LL | enum Enum<const N: usize = { Self; 10 }> { } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:7:32 + | +LL | union Union<const N: usize = { Self; 10 }> { not_empty: () } + | ^^^^ `Self` in generic parameter default + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0735`. diff --git a/tests/ui/const-generics/defaults/default-on-impl.rs b/tests/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 000000000..9ce46aa09 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,6 @@ +struct Foo<const N: usize>; + +impl<const N: usize = 1> Foo<N> {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-on-impl.stderr b/tests/ui/const-generics/defaults/default-on-impl.stderr new file mode 100644 index 000000000..4b2b05742 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-on-impl.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:3:6 + | +LL | impl<const N: usize = 1> Foo<N> {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 000000000..41a52c7eb --- /dev/null +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,3 @@ +struct Foo<const N: u8 = { 255 + 1 }>; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 000000000..e8ebddade --- /dev/null +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:1:28 + | +LL | struct Foo<const N: u8 = { 255 + 1 }>; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs new file mode 100644 index 000000000..9c59e672d --- /dev/null +++ b/tests/ui/const-generics/defaults/doesnt_infer.rs @@ -0,0 +1,13 @@ +// test that defaulted const params are not used to help type inference + +struct Foo<const N: u32 = 2>; + +impl<const N: u32> Foo<N> { + fn foo() -> Self { loop {} } +} + +fn main() { + let foo = Foo::<1>::foo(); + let foo = Foo::foo(); + //~^ error: type annotations needed for `Foo<N>` +} diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr new file mode 100644 index 000000000..227b2f402 --- /dev/null +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Foo<N>` + --> $DIR/doesnt_infer.rs:11:9 + | +LL | let foo = Foo::foo(); + | ^^^ + | +help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified + | +LL | let foo: Foo<N> = Foo::foo(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/defaults/external.rs b/tests/ui/const-generics/defaults/external.rs new file mode 100644 index 000000000..25ec523cb --- /dev/null +++ b/tests/ui/const-generics/defaults/external.rs @@ -0,0 +1,24 @@ +// aux-build:const_defaulty.rs +// check-pass +extern crate const_defaulty; +use const_defaulty::Defaulted; + +struct Local<const N: usize=4>; +impl Local { + fn new() -> Self { + Local + } +} +impl<const N: usize>Local<N> { + fn value(&self) -> usize { + N + } +} + +fn main() { + let v = Defaulted::new(); + assert_eq!(v.value(), 3); + + let l = Local::new(); + assert_eq!(l.value(), 4); +} diff --git a/tests/ui/const-generics/defaults/forward-declared.rs b/tests/ui/const-generics/defaults/forward-declared.rs new file mode 100644 index 000000000..ede3d873b --- /dev/null +++ b/tests/ui/const-generics/defaults/forward-declared.rs @@ -0,0 +1,13 @@ +struct Foo<const N: usize = M, const M: usize = 10>; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar<const N: usize = M, const M: usize = 10> {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +struct Foo2<const N: usize = N>; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar2<const N: usize = N> {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +fn main() {} diff --git a/tests/ui/const-generics/defaults/forward-declared.stderr b/tests/ui/const-generics/defaults/forward-declared.stderr new file mode 100644 index 000000000..4856c7a1f --- /dev/null +++ b/tests/ui/const-generics/defaults/forward-declared.stderr @@ -0,0 +1,27 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:1:29 + | +LL | struct Foo<const N: usize = M, const M: usize = 10>; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:4:27 + | +LL | enum Bar<const N: usize = M, const M: usize = 10> {} + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:7:30 + | +LL | struct Foo2<const N: usize = N>; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:10:28 + | +LL | enum Bar2<const N: usize = N> {} + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs b/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs new file mode 100644 index 000000000..f082bd8d2 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: usize, const M: usize = { N + 1 }>; +fn no_constraining() -> Foo<10> { + Foo::<10, 11> +} + +pub fn different_than_default() -> Foo<10> { + Foo::<10, 12> + //~^ error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr new file mode 100644 index 000000000..61b355118 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/generic-expr-default-concrete.rs:10:5 + | +LL | Foo::<10, 12> + | ^^^^^^^^^^^^^ expected `11`, found `12` + | + = note: expected constant `11` + found constant `12` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs new file mode 100644 index 000000000..777865d1c --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs @@ -0,0 +1,16 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: usize, const M: usize = { N + 1 }>; +fn should_unify<const N: usize>() -> Foo<N> where [(); { N + 1 }]: { + Foo::<N, { N + 1 }> +} +pub fn shouldnt_unify<const N: usize>() -> Foo<N> +where + [(); { N + 1 }]:, + [(); { N + 2 }]:, { + Foo::<N, { N + 2 }> + //~^ error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr new file mode 100644 index 000000000..e83f89a60 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/generic-expr-default-mismatched-types.rs:12:5 + | +LL | Foo::<N, { N + 2 }> + | ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }` + | + = note: expected constant `{ N + 1 }` + found constant `{ N + 2 }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default.rs b/tests/ui/const-generics/defaults/generic-expr-default.rs new file mode 100644 index 000000000..8fe43feb7 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default.rs @@ -0,0 +1,24 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<const N: usize, const M: usize = { N + 1 }>; +pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> { + //~^ error: unconstrained generic constant + loop {} +} +pub fn has_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); N1 + 1]: { + loop {} +} + +type FooAlias<const N: usize, const NP: usize = { N + 1 }> = [(); NP]; +fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N> +{ + //~^^ error: unconstrained generic constant + todo!() +} +fn has_evaluatable_bound_alias<const N: usize>() -> FooAlias<N> +where [(); N + 1]: { + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default.stderr b/tests/ui/const-generics/defaults/generic-expr-default.stderr new file mode 100644 index 000000000..ada1498d1 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/generic-expr-default.rs:5:54 + | +LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> { + | ^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:` + +error: unconstrained generic constant + --> $DIR/generic-expr-default.rs:14:58 + | +LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N> + | ^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/intermixed-lifetime.rs b/tests/ui/const-generics/defaults/intermixed-lifetime.rs new file mode 100644 index 000000000..beaf7fc60 --- /dev/null +++ b/tests/ui/const-generics/defaults/intermixed-lifetime.rs @@ -0,0 +1,9 @@ +// Checks that lifetimes cannot be interspersed between consts and types. + +struct Foo<const N: usize, 'a, T = u32>(&'a (), T); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +struct Bar<const N: usize, T = u32, 'a>(&'a (), T); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn main() {} diff --git a/tests/ui/const-generics/defaults/intermixed-lifetime.stderr b/tests/ui/const-generics/defaults/intermixed-lifetime.stderr new file mode 100644 index 000000000..5cff61dd9 --- /dev/null +++ b/tests/ui/const-generics/defaults/intermixed-lifetime.stderr @@ -0,0 +1,14 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/intermixed-lifetime.rs:3:28 + | +LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T); + | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/intermixed-lifetime.rs:6:37 + | +LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T); + | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/mismatch.rs b/tests/ui/const-generics/defaults/mismatch.rs new file mode 100644 index 000000000..ec131505e --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatch.rs @@ -0,0 +1,22 @@ +pub struct Example<const N: usize = 13>; +pub struct Example2<T = u32, const N: usize = 13>(T); +pub struct Example3<const N: usize = 13, T = u32>(T); +pub struct Example4<const N: usize = 13, const M: usize = 4>; + +fn main() { + let e: Example<13> = (); + //~^ Error: mismatched types + //~| expected struct `Example` + let e: Example2<u32, 13> = (); + //~^ Error: mismatched types + //~| expected struct `Example2` + let e: Example3<13, u32> = (); + //~^ Error: mismatched types + //~| expected struct `Example3` + let e: Example3<7> = (); + //~^ Error: mismatched types + //~| expected struct `Example3<7>` + let e: Example4<7> = (); + //~^ Error: mismatched types + //~| expected struct `Example4<7>` +} diff --git a/tests/ui/const-generics/defaults/mismatch.stderr b/tests/ui/const-generics/defaults/mismatch.stderr new file mode 100644 index 000000000..52c54aace --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatch.stderr @@ -0,0 +1,58 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:7:26 + | +LL | let e: Example<13> = (); + | ----------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + | + = note: expected struct `Example` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:10:32 + | +LL | let e: Example2<u32, 13> = (); + | ----------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:13:32 + | +LL | let e: Example3<13, u32> = (); + | ----------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:26 + | +LL | let e: Example3<7> = (); + | ----------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:19:26 + | +LL | let e: Example4<7> = (); + | ----------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + | + = note: expected struct `Example4<7>` + found unit type `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs new file mode 100644 index 000000000..5c9323261 --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs @@ -0,0 +1,41 @@ +trait Trait { + fn foo<U>() {} +} +impl Trait for () { + fn foo<const M: u64>() {} + //~^ error: method `foo` has an incompatible generic parameter for trait +} + +trait Other { + fn bar<const M: u8>() {} +} +impl Other for () { + fn bar<T>() {} + //~^ error: method `bar` has an incompatible generic parameter for trait +} + +trait Uwu { + fn baz<const N: u32>() {} +} +impl Uwu for () { + fn baz<const N: i32>() {} + //~^ error: method `baz` has an incompatible generic parameter for trait +} + +trait Aaaaaa { + fn bbbb<const N: u32, T>() {} +} +impl Aaaaaa for () { + fn bbbb<T, const N: u32>() {} + //~^ error: method `bbbb` has an incompatible generic parameter for trait +} + +trait Names { + fn abcd<T, const N: u32>() {} +} +impl Names for () { + fn abcd<const N: u32, T>() {} + //~^ error: method `abcd` has an incompatible generic parameter for trait +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr new file mode 100644 index 000000000..3455f2c8e --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr @@ -0,0 +1,68 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Trait` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12 + | +LL | trait Trait { + | ----- +LL | fn foo<U>() {} + | - expected type parameter +LL | } +LL | impl Trait for () { + | ----------------- +LL | fn foo<const M: u64>() {} + | ^^^^^^^^^^^^ found const parameter of type `u64` + +error[E0053]: method `bar` has an incompatible generic parameter for trait `Other` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12 + | +LL | trait Other { + | ----- +LL | fn bar<const M: u8>() {} + | ----------- expected const parameter of type `u8` +LL | } +LL | impl Other for () { + | ----------------- +LL | fn bar<T>() {} + | ^ found type parameter + +error[E0053]: method `baz` has an incompatible generic parameter for trait `Uwu` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:21:12 + | +LL | trait Uwu { + | --- +LL | fn baz<const N: u32>() {} + | ------------ expected const parameter of type `u32` +LL | } +LL | impl Uwu for () { + | --------------- +LL | fn baz<const N: i32>() {} + | ^^^^^^^^^^^^ found const parameter of type `i32` + +error[E0053]: method `bbbb` has an incompatible generic parameter for trait `Aaaaaa` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:29:13 + | +LL | trait Aaaaaa { + | ------ +LL | fn bbbb<const N: u32, T>() {} + | ------------ expected const parameter of type `u32` +LL | } +LL | impl Aaaaaa for () { + | ------------------ +LL | fn bbbb<T, const N: u32>() {} + | ^ found type parameter + +error[E0053]: method `abcd` has an incompatible generic parameter for trait `Names` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:37:13 + | +LL | trait Names { + | ----- +LL | fn abcd<T, const N: u32>() {} + | - expected type parameter +LL | } +LL | impl Names for () { + | ----------------- +LL | fn abcd<const N: u32, T>() {} + | ^^^^^^^^^^^^ found const parameter of type `u32` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs new file mode 100644 index 000000000..f928fc9e7 --- /dev/null +++ b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs @@ -0,0 +1,4 @@ +struct Foo<const M: usize = 10, 'a>(&'a u32); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn main() {} diff --git a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr new file mode 100644 index 000000000..ba08b4646 --- /dev/null +++ b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/param-order-err-pretty-prints-default.rs:1:33 + | +LL | struct Foo<const M: usize = 10, 'a>(&'a u32); + | ----------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const M: usize = 10>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.rs b/tests/ui/const-generics/defaults/pretty-printing-ast.rs new file mode 100644 index 000000000..e202d4e86 --- /dev/null +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.rs @@ -0,0 +1,11 @@ +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] + +trait Foo<const KIND: bool = true> {} + +fn foo<const SIZE: usize = 5>() {} + +struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>; diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout new file mode 100644 index 000000000..121138605 --- /dev/null +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -0,0 +1,18 @@ +#![feature(prelude_import)] +#![no_std] +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Foo<const KIND : bool = true> {} + +fn foo<const SIZE : usize = 5>() {} + +struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize = + FROM>; diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs new file mode 100644 index 000000000..118da2723 --- /dev/null +++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -0,0 +1,11 @@ +// Regression test for #82792. + +// run-pass + +#[repr(C)] +pub struct Loaf<T: Sized, const N: usize = 1> { + head: [T; N], + slice: [T], +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait.rs b/tests/ui/const-generics/defaults/rp_impl_trait.rs new file mode 100644 index 000000000..dde8eea45 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait.rs @@ -0,0 +1,29 @@ +// run-pass +struct Uwu<const N: u32 = 1, const M: u32 = N>; + +trait Trait {} +impl<const N: u32> Trait for Uwu<N> {} + +fn rawr<const N: u32>() -> impl Trait { + Uwu::<N> +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { } + +impl<const N: u8> Traitor<N> for u32 {} +impl Traitor<1, 1> for u64 {} + +fn uwu<const N: u8>() -> impl Traitor<N> { + 1_u32 +} + +fn owo() -> impl Traitor { + 1_u64 +} + +fn main() { + rawr::<3>(); + rawr::<7>(); + uwu::<{ u8::MAX }>(); + owo(); +} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs new file mode 100644 index 000000000..80013e7b4 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -0,0 +1,30 @@ +struct Uwu<const N: u32 = 1, const M: u32 = N>; + +trait Trait {} +impl<const N: u32> Trait for Uwu<N> {} + +fn rawr() -> impl Trait { + //~^ error: the trait bound `Uwu<10, 12>: Trait` is not satisfied + Uwu::<10, 12> +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> {} + +impl<const N: u8> Traitor<N, 2> for u32 {} +impl Traitor<1, 2> for u64 {} + +fn uwu<const N: u8>() -> impl Traitor<N> { + //~^ error: the trait bound `u32: Traitor<N>` is not satisfied + 1_u32 +} + +fn owo() -> impl Traitor { + //~^ error: the trait bound `u64: Traitor` is not satisfied + 1_u64 +} + +fn main() { + rawr(); + uwu(); + owo(); +} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr new file mode 100644 index 000000000..a46bd5352 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `Uwu<10, 12>: Trait` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:6:14 + | +LL | fn rawr() -> impl Trait { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10, 12>` +LL | +LL | Uwu::<10, 12> + | ------------- return type was inferred to be `Uwu<10, 12>` here + | + = help: the trait `Trait` is implemented for `Uwu<N>` + +error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:16:26 + | +LL | fn uwu<const N: u8>() -> impl Traitor<N> { + | ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32` +LL | +LL | 1_u32 + | ----- return type was inferred to be `u32` here + | + = help: the trait `Traitor<N, 2>` is implemented for `u32` + +error[E0277]: the trait bound `u64: Traitor` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:21:13 + | +LL | fn owo() -> impl Traitor { + | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64` +LL | +LL | 1_u64 + | ----- return type was inferred to be `u64` here + | + = help: the trait `Traitor<1, 2>` is implemented for `u64` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/defaults/self-referential.rs b/tests/ui/const-generics/defaults/self-referential.rs new file mode 100644 index 000000000..14a870dc3 --- /dev/null +++ b/tests/ui/const-generics/defaults/self-referential.rs @@ -0,0 +1,4 @@ +trait Foo<const M: u8, const M: u8 = M> {} +//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters +impl Foo<2> for () {} +fn main() {} diff --git a/tests/ui/const-generics/defaults/self-referential.stderr b/tests/ui/const-generics/defaults/self-referential.stderr new file mode 100644 index 000000000..170c1f7f7 --- /dev/null +++ b/tests/ui/const-generics/defaults/self-referential.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters + --> $DIR/self-referential.rs:1:30 + | +LL | trait Foo<const M: u8, const M: u8 = M> {} + | - ^ already used + | | + | first use of `M` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/const-generics/defaults/simple-defaults.rs b/tests/ui/const-generics/defaults/simple-defaults.rs new file mode 100644 index 000000000..6a782d223 --- /dev/null +++ b/tests/ui/const-generics/defaults/simple-defaults.rs @@ -0,0 +1,13 @@ +// run-pass +// Checks that type param defaults are allowed after const params. +#![allow(dead_code)] + +struct FixedOutput<'a, const N: usize, T=u32> { + out: &'a [T; N], +} + +trait FixedOutputter { + fn out(&self) -> FixedOutput<'_, 10>; +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs b/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs new file mode 100644 index 000000000..a1828727e --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs @@ -0,0 +1,24 @@ +// aux-build:trait_object_lt_defaults_lib.rs +// run-pass +#![allow(dead_code)] +extern crate trait_object_lt_defaults_lib; + +// Tests that `A<'a, 3, dyn Test>` is short for `A<'a, 3, dyn Test + 'a>` +// and `Foo<'a, 3, dyn Test>` is short for `Foo<'a, 3, dyn Test + 'a>` +// Test is in `const-generics/defaults` because it relies on param ordering + +trait Test {} + +struct A<'a, const N: usize, T: ?Sized + 'a>(&'a T, [(); N]); +fn blah<'a>(mut a: A<'a, 3, dyn Test>, arg: &'a (dyn Test + 'a)) { + a.0 = arg; +} + +fn other_blah<'a>( + mut a: trait_object_lt_defaults_lib::Foo<'a, 3, dyn Test>, + arg: &'a (dyn Test + 'a), +) { + a.0 = arg; +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/trait_objects.rs b/tests/ui/const-generics/defaults/trait_objects.rs new file mode 100644 index 000000000..750e40313 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects.rs @@ -0,0 +1,43 @@ +// run-pass +trait Trait<const N: u8 = 12> { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait for u32 {} + +impl Trait<12> for u64 { + fn uwu(&self) -> u8 { + *self as u8 + } +} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2> for bool { } +impl Traitor for u8 { + fn owo(&self) -> u8 { + *self + } +} + +fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 { + arg.owo() +} + +fn main() { + assert_eq!(foo(&10_u32), 12); + assert_eq!(foo(&3_u64), 3); + + assert_eq!(bar(&true), 2); + assert_eq!(bar(&1_u8), 1); +} diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.rs b/tests/ui/const-generics/defaults/trait_objects_fail.rs new file mode 100644 index 000000000..6ab803f99 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects_fail.rs @@ -0,0 +1,30 @@ +trait Trait<const N: u8 = 12> { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait<2> for u32 {} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2, 3> for bool {} + +fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 { + arg.owo() +} + +fn main() { + foo(&10_u32); + //~^ error: the trait bound `u32: Trait` is not satisfied + bar(&true); + //~^ error: the trait bound `bool: Traitor<_>` is not satisfied +} diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.stderr b/tests/ui/const-generics/defaults/trait_objects_fail.stderr new file mode 100644 index 000000000..0e8334d03 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects_fail.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `u32: Trait` is not satisfied + --> $DIR/trait_objects_fail.rs:26:9 + | +LL | foo(&10_u32); + | ^^^^^^^ the trait `Trait` is not implemented for `u32` + | + = help: the trait `Trait<2>` is implemented for `u32` + = note: required for the cast from `u32` to the object type `dyn Trait` + +error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied + --> $DIR/trait_objects_fail.rs:28:9 + | +LL | bar(&true); + | ^^^^^ the trait `Traitor<_>` is not implemented for `bool` + | + = help: the trait `Traitor<2, 3>` is implemented for `bool` + = note: required for the cast from `bool` to the object type `dyn Traitor<_>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/defaults/type-default-const-param-name.rs b/tests/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 000000000..405664ded --- /dev/null +++ b/tests/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,14 @@ +// check-pass +struct N; + +struct Foo<const N: usize = 1, T = N>(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/tests/ui/const-generics/defaults/wfness.rs b/tests/ui/const-generics/defaults/wfness.rs new file mode 100644 index 000000000..a93f67081 --- /dev/null +++ b/tests/ui/const-generics/defaults/wfness.rs @@ -0,0 +1,23 @@ +struct Ooopsies<const N: u8 = { u8::MAX + 1 }>; +//~^ error: evaluation of constant value failed + +trait Trait<const N: u8> {} +impl Trait<3> for () {} +struct WhereClause<const N: u8 = 2> +where + (): Trait<N>; +//~^ error: the trait bound `(): Trait<2>` is not satisfied + +trait Traitor<T, const N: u8> {} +struct WhereClauseTooGeneric<T = u32, const N: u8 = 2>(T) +where + (): Traitor<T, N>; + +// no error on struct def +struct DependentDefaultWfness<const N: u8 = 1, T = WhereClause<N>>(T); +fn foo() -> DependentDefaultWfness { + //~^ error: the trait bound `(): Trait<1>` is not satisfied + loop {} +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr new file mode 100644 index 000000000..25038f830 --- /dev/null +++ b/tests/ui/const-generics/defaults/wfness.stderr @@ -0,0 +1,34 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/wfness.rs:1:33 + | +LL | struct Ooopsies<const N: u8 = { u8::MAX + 1 }>; + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error[E0277]: the trait bound `(): Trait<2>` is not satisfied + --> $DIR/wfness.rs:8:9 + | +LL | (): Trait<N>; + | ^^^^^^^^ the trait `Trait<2>` is not implemented for `()` + | + = help: the trait `Trait<3>` is implemented for `()` + +error[E0277]: the trait bound `(): Trait<1>` is not satisfied + --> $DIR/wfness.rs:18:13 + | +LL | fn foo() -> DependentDefaultWfness { + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()` + | + = help: the trait `Trait<3>` is implemented for `()` +note: required by a bound in `WhereClause` + --> $DIR/wfness.rs:8:9 + | +LL | struct WhereClause<const N: u8 = 2> + | ----------- required by a bound in this +LL | where +LL | (): Trait<N>; + | ^^^^^^^^ required by this bound in `WhereClause` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/wrong-order.rs b/tests/ui/const-generics/defaults/wrong-order.rs new file mode 100644 index 000000000..d53d56f41 --- /dev/null +++ b/tests/ui/const-generics/defaults/wrong-order.rs @@ -0,0 +1,9 @@ +struct A<T = u32, const N: usize> { + //~^ ERROR generic parameters with a default must be trailing + arg: T, +} + +struct Foo<const N: u8 = 3, T>(T); +//~^ error: generic parameters with a default must be trailing + +fn main() {} diff --git a/tests/ui/const-generics/defaults/wrong-order.stderr b/tests/ui/const-generics/defaults/wrong-order.stderr new file mode 100644 index 000000000..4d2628d03 --- /dev/null +++ b/tests/ui/const-generics/defaults/wrong-order.stderr @@ -0,0 +1,14 @@ +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:1:10 + | +LL | struct A<T = u32, const N: usize> { + | ^ + +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:6:18 + | +LL | struct Foo<const N: u8 = 3, T>(T); + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/deref-into-array-generic.rs b/tests/ui/const-generics/deref-into-array-generic.rs new file mode 100644 index 000000000..7d75af12b --- /dev/null +++ b/tests/ui/const-generics/deref-into-array-generic.rs @@ -0,0 +1,27 @@ +// check-pass + +struct Test<T, const N: usize>([T; N]); + +impl<T: Copy + Default, const N: usize> Default for Test<T, N> { + fn default() -> Self { + Self([T::default(); N]) + } +} + +impl<T, const N: usize> std::ops::Deref for Test<T, N> { + type Target = [T; N]; + + fn deref(&self) -> &[T; N] { + &self.0 + } +} + +fn test() -> Test<u64, 16> { + let test = Test::default(); + println!("{}", test.len()); + test +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/different_generic_args.full.stderr b/tests/ui/const-generics/different_generic_args.full.stderr new file mode 100644 index 000000000..eba1768f7 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.full.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args.rs:11:9 + | +LL | u = ConstUsize::<4> {}; + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` + | + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args.min.stderr b/tests/ui/const-generics/different_generic_args.min.stderr new file mode 100644 index 000000000..eba1768f7 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.min.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args.rs:11:9 + | +LL | u = ConstUsize::<4> {}; + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` + | + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args.rs b/tests/ui/const-generics/different_generic_args.rs new file mode 100644 index 000000000..9ee0e0747 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.rs @@ -0,0 +1,13 @@ +// Check that types with different const arguments are different. +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct ConstUsize<const V: usize> {} + +fn main() { + let mut u = ConstUsize::<3> {}; + u = ConstUsize::<4> {}; + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/different_generic_args_array.rs b/tests/ui/const-generics/different_generic_args_array.rs new file mode 100644 index 000000000..4d225dfdd --- /dev/null +++ b/tests/ui/const-generics/different_generic_args_array.rs @@ -0,0 +1,11 @@ +// Check that different const types are different. +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +struct Const<const V: [usize; 1]> {} + +fn main() { + let mut x = Const::<{ [3] }> {}; + x = Const::<{ [4] }> {}; + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/different_generic_args_array.stderr b/tests/ui/const-generics/different_generic_args_array.stderr new file mode 100644 index 000000000..4c5b5ada4 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args_array.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args_array.rs:9:9 + | +LL | x = Const::<{ [4] }> {}; + | ^^^^^^^^^^^^^^^^^^^ expected `[3]`, found `[4]` + | + = note: expected struct `Const<[3]>` + found struct `Const<[4]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs new file mode 100644 index 000000000..6c4ee1af2 --- /dev/null +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that during error handling for the "trait not implemented" error +// we dont try to evaluate std::mem::size_of::<Self::Assoc> causing an ICE + +struct Adt; + +trait Foo { + type Assoc; + fn foo() + where + [Adt; std::mem::size_of::<Self::Assoc>()]: , + { + <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar() + //~^ Error: the trait bound + } + + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr new file mode 100644 index 000000000..d8eebeb0d --- /dev/null +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `[Adt; std::mem::size_of::<Self::Assoc>()]: Foo` is not satisfied + --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9 + | +LL | <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/dyn-supertraits.rs b/tests/ui/const-generics/dyn-supertraits.rs new file mode 100644 index 000000000..3dee326a1 --- /dev/null +++ b/tests/ui/const-generics/dyn-supertraits.rs @@ -0,0 +1,80 @@ +// run-pass + +trait Foo<const N: usize> { + fn myfun(&self) -> usize; +} +trait Bar<const N: usize> : Foo<N> {} +trait Baz: Foo<3> {} + +struct FooType<const N: usize>; +struct BarType<const N: usize>; +struct BazType; + +impl<const N: usize> Foo<N> for FooType<N> { + fn myfun(&self) -> usize { N } +} +impl<const N: usize> Foo<N> for BarType<N> { + fn myfun(&self) -> usize { N + 1 } +} +impl<const N: usize> Bar<N> for BarType<N> {} +impl Foo<3> for BazType { + fn myfun(&self) -> usize { 999 } +} +impl Baz for BazType {} + +trait Foz {} +trait Boz: Foo<3> + Foz {} +trait Bok<const N: usize>: Foo<N> + Foz {} + +struct FozType; +struct BozType; +struct BokType<const N: usize>; + +impl Foz for FozType {} + +impl Foz for BozType {} +impl Foo<3> for BozType { + fn myfun(&self) -> usize { 9999 } +} +impl Boz for BozType {} + +impl<const N: usize> Foz for BokType<N> {} +impl<const N: usize> Foo<N> for BokType<N> { + fn myfun(&self) -> usize { N + 2 } +} +impl<const N: usize> Bok<N> for BokType<N> {} + +fn a<const N: usize>(x: &dyn Foo<N>) -> usize { x.myfun() } +fn b(x: &dyn Foo<3>) -> usize { x.myfun() } +fn c<T: Bok<N>, const N: usize>(x: T) -> usize { a::<N>(&x) } +fn d<T: ?Sized + Foo<3>>(x: &T) -> usize { x.myfun() } +fn e(x: &dyn Bar<3>) -> usize { d(x) } + +fn main() { + let foo = FooType::<3> {}; + assert!(a(&foo) == 3); + assert!(b(&foo) == 3); + assert!(d(&foo) == 3); + + let bar = BarType::<3> {}; + assert!(a(&bar) == 4); + assert!(b(&bar) == 4); + assert!(d(&bar) == 4); + assert!(e(&bar) == 4); + + let baz = BazType {}; + assert!(a(&baz) == 999); + assert!(b(&baz) == 999); + assert!(d(&baz) == 999); + + let boz = BozType {}; + assert!(a(&boz) == 9999); + assert!(b(&boz) == 9999); + assert!(d(&boz) == 9999); + + let bok = BokType::<3> {}; + assert!(a(&bok) == 5); + assert!(b(&bok) == 5); + assert!(d(&bok) == 5); + assert!(c(BokType::<3> {}) == 5); +} diff --git a/tests/ui/const-generics/early/closing-args-token.rs b/tests/ui/const-generics/early/closing-args-token.rs new file mode 100644 index 000000000..cb4d6299e --- /dev/null +++ b/tests/ui/const-generics/early/closing-args-token.rs @@ -0,0 +1,26 @@ +struct S<const X: u32>; +struct T<const X: bool>; + +fn bad_args_1() { + S::<5 + 2 >> 7>; + //~^ ERROR expressions must be enclosed in braces to be used as const generic arguments + //~| ERROR comparison operators cannot be chained +} + +fn bad_args_2() { + S::<{ 5 + 2 } >> 7>; + //~^ ERROR comparison operators cannot be chained +} + +fn bad_args_3() { + T::<0 >= 3>; + //~^ ERROR expected expression, found `;` +} + +fn bad_args_4() { + let mut x = 0; + T::<x >>= 2 > 0>; + //~^ ERROR comparison operators cannot be chained +} + +fn main() {} diff --git a/tests/ui/const-generics/early/closing-args-token.stderr b/tests/ui/const-generics/early/closing-args-token.stderr new file mode 100644 index 000000000..58fff3a85 --- /dev/null +++ b/tests/ui/const-generics/early/closing-args-token.stderr @@ -0,0 +1,52 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/closing-args-token.rs:5:9 + | +LL | S::<5 + 2 >> 7>; + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | S::<{ 5 + 2 } >> 7>; + | + + + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:5:16 + | +LL | S::<5 + 2 >> 7>; + | ^ ^ + | +help: split the comparison into two + | +LL | S::<5 + 2 >> 7 && 7>; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:11:20 + | +LL | S::<{ 5 + 2 } >> 7>; + | ^ ^ + | +help: split the comparison into two + | +LL | S::<{ 5 + 2 } >> 7 && 7>; + | ++++ + +error: expected expression, found `;` + --> $DIR/closing-args-token.rs:16:16 + | +LL | T::<0 >= 3>; + | ^ expected expression + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:22:12 + | +LL | T::<x >>= 2 > 0>; + | ^^ ^ + | +help: split the comparison into two + | +LL | T::<x >>= 2 && 2 > 0>; + | ++++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/const-generics/early/const-expression-parameter.rs b/tests/ui/const-generics/early/const-expression-parameter.rs new file mode 100644 index 000000000..4cf7ba869 --- /dev/null +++ b/tests/ui/const-generics/early/const-expression-parameter.rs @@ -0,0 +1,19 @@ +fn i32_identity<const X: i32>() -> i32 { + 5 +} + +fn foo_a() { + i32_identity::<-1>(); // ok +} + +fn foo_b() { + i32_identity::<1 + 2>(); //~ ERROR expressions must be enclosed in braces +} + +fn foo_c() { + i32_identity::< -1 >(); // ok +} + +fn main() { + i32_identity::<5>(); // ok +} diff --git a/tests/ui/const-generics/early/const-expression-parameter.stderr b/tests/ui/const-generics/early/const-expression-parameter.stderr new file mode 100644 index 000000000..4ce1be25e --- /dev/null +++ b/tests/ui/const-generics/early/const-expression-parameter.stderr @@ -0,0 +1,13 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-parameter.rs:10:20 + | +LL | i32_identity::<1 + 2>(); + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | i32_identity::<{ 1 + 2 }>(); + | + + + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.rs b/tests/ui/const-generics/early/const-param-from-outer-fn.rs new file mode 100644 index 000000000..c3b418ee3 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.rs @@ -0,0 +1,7 @@ +fn foo<const X: u32>() { + fn bar() -> u32 { + X //~ ERROR can't use generic parameters from outer function + } +} + +fn main() {} diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr new file mode 100644 index 000000000..e3bf38b70 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -0,0 +1,13 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/const-param-from-outer-fn.rs:3:9 + | +LL | fn foo<const X: u32>() { + | - const parameter from outer function +LL | fn bar() -> u32 { + | - help: try using a local generic parameter instead: `<X>` +LL | X + | ^ use of generic parameter from outer function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/const-generics/early/const-param-hygiene.rs b/tests/ui/const-generics/early/const-param-hygiene.rs new file mode 100644 index 000000000..fd4e5b409 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-hygiene.rs @@ -0,0 +1,17 @@ +// run-pass + +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/tests/ui/const-generics/early/const-param-shadowing.rs b/tests/ui/const-generics/early/const-param-shadowing.rs new file mode 100644 index 000000000..ddd15dbc4 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-shadowing.rs @@ -0,0 +1,7 @@ +type N = u32; +struct Foo<const M: usize>; +fn test<const N: usize>() -> Foo<N> { //~ ERROR type provided when + Foo +} + +fn main() {} diff --git a/tests/ui/const-generics/early/const-param-shadowing.stderr b/tests/ui/const-generics/early/const-param-shadowing.stderr new file mode 100644 index 000000000..625338bd9 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-shadowing.stderr @@ -0,0 +1,14 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/const-param-shadowing.rs:3:34 + | +LL | fn test<const N: usize>() -> Foo<N> { + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | fn test<const N: usize>() -> Foo<{ N }> { + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/early/invalid-const-arguments.rs b/tests/ui/const-generics/early/invalid-const-arguments.rs new file mode 100644 index 000000000..6619c9758 --- /dev/null +++ b/tests/ui/const-generics/early/invalid-const-arguments.rs @@ -0,0 +1,16 @@ +#![crate_type="lib"] + +struct A<const N: u8>; +trait Foo {} +impl Foo for A<N> {} +//~^ ERROR cannot find type +//~| unresolved item provided when a constant + +struct B<const N: u8>; +impl<N> Foo for B<N> {} +//~^ ERROR type provided when a constant + +struct C<const C: u8, const N: u8>; +impl<const N: u8> Foo for C<N, T> {} +//~^ ERROR cannot find type +//~| unresolved item provided when a constant diff --git a/tests/ui/const-generics/early/invalid-const-arguments.stderr b/tests/ui/const-generics/early/invalid-const-arguments.stderr new file mode 100644 index 000000000..b46e7e24f --- /dev/null +++ b/tests/ui/const-generics/early/invalid-const-arguments.stderr @@ -0,0 +1,73 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/invalid-const-arguments.rs:5:16 + | +LL | struct A<const N: u8>; + | ---------------------- similarly named struct `A` defined here +LL | trait Foo {} +LL | impl Foo for A<N> {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl Foo for A<A> {} + | ~ +help: you might be missing a type parameter + | +LL | impl<N> Foo for A<N> {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/invalid-const-arguments.rs:14:32 + | +LL | struct A<const N: u8>; + | ---------------------- similarly named struct `A` defined here +... +LL | impl<const N: u8> Foo for C<N, T> {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl<const N: u8> Foo for C<N, A> {} + | ~ +help: you might be missing a type parameter + | +LL | impl<const N: u8, T> Foo for C<N, T> {} + | +++ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:5:16 + | +LL | impl Foo for A<N> {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl Foo for A<{ N }> {} + | + + + +error[E0747]: type provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:10:19 + | +LL | impl<N> Foo for B<N> {} + | ^ + | +help: consider changing this type parameter to be a `const` generic + | +LL | impl<const N: u8> Foo for B<N> {} + | ~~~~~~~~~~~ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:14:32 + | +LL | impl<const N: u8> Foo for C<N, T> {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl<const N: u8> Foo for C<N, { T }> {} + | + + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0412, E0747. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/early/macro_rules-braces.rs b/tests/ui/const-generics/early/macro_rules-braces.rs new file mode 100644 index 000000000..0ae914635 --- /dev/null +++ b/tests/ui/const-generics/early/macro_rules-braces.rs @@ -0,0 +1,73 @@ +mod m { + pub const P: usize = 0; +} + +const Q: usize = 0; + +fn test<const N: usize>() { + struct Foo<const M: usize>; + macro_rules! foo { + ($x:expr) => { + [u8; $x] + } + } + macro_rules! bar { + ($x:expr) => { + [u8; { $x }] + } + } + macro_rules! baz { + ( $x:expr) => { + Foo<$x> + } + } + macro_rules! biz { + ($x:expr) => { + Foo<{ $x }> + }; + } + + let _: foo!(N); + let _: foo!({ N }); + let _: foo!({{ N }}); //~ ERROR generic parameters may not + let _: foo!(Q); + let _: foo!(m::P); + let _: bar!(N); + let _: bar!({ N }); //~ ERROR generic parameters may not + let _: bar!(Q); + let _: bar!(m::P); + let _: baz!(N); + let _: baz!({ N }); + let _: baz!({{ N }}); //~ ERROR generic parameters may not + let _: baz!(Q); + let _: baz!({ m::P }); + let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces + let _: biz!(N); + let _: biz!({ N }); //~ ERROR generic parameters may not + let _: biz!(Q); + let _: biz!(m::P); + let _: foo!(3); + let _: foo!({ 3 }); + let _: foo!({{ 3 }}); + let _: bar!(3); + let _: bar!({ 3 }); + let _: baz!(3); + let _: baz!({ 3 }); + let _: baz!({{ 3 }}); + let _: biz!(3); + let _: biz!({ 3 }); + let _: foo!(10 + 7); + let _: foo!({ 10 + 7 }); + let _: foo!({{ 10 + 7 }}); + let _: bar!(10 + 7); + let _: bar!({ 10 + 7 }); + let _: baz!(10 + 7); //~ ERROR expressions must be enclosed in braces + let _: baz!({ 10 + 7 }); + let _: baz!({{ 10 + 7 }}); + let _: biz!(10 + 7); + let _: biz!({ 10 + 7 }); +} + +fn main() { + test::<3>(); +} diff --git a/tests/ui/const-generics/early/macro_rules-braces.stderr b/tests/ui/const-generics/early/macro_rules-braces.stderr new file mode 100644 index 000000000..49382dbf0 --- /dev/null +++ b/tests/ui/const-generics/early/macro_rules-braces.stderr @@ -0,0 +1,60 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:44:17 + | +LL | let _: baz!(m::P); + | ^^^^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ m::P }); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:64:17 + | +LL | let _: baz!(10 + 7); + | ^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ 10 + 7 }); + | + + + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:32:20 + | +LL | let _: foo!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:36:19 + | +LL | let _: bar!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:41:20 + | +LL | let _: baz!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:46:19 + | +LL | let _: biz!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/ensure_is_evaluatable.rs b/tests/ui/const-generics/ensure_is_evaluatable.rs new file mode 100644 index 000000000..1e8d8c3d3 --- /dev/null +++ b/tests/ui/const-generics/ensure_is_evaluatable.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const N: usize, const M: usize>() -> [(); N+2] +where + [(); N + 1]:, + [(); M + 1]:, +{ + bar() + //~^ ERROR: unconstrained +} + +fn bar<const N: usize>() -> [(); N] +where + [(); N + 1]:, +{ + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/ensure_is_evaluatable.stderr b/tests/ui/const-generics/ensure_is_evaluatable.stderr new file mode 100644 index 000000000..bf6c35ad8 --- /dev/null +++ b/tests/ui/const-generics/ensure_is_evaluatable.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/ensure_is_evaluatable.rs:9:5 + | +LL | bar() + | ^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N + 1]:` +note: required by a bound in `bar` + --> $DIR/ensure_is_evaluatable.rs:15:10 + | +LL | fn bar<const N: usize>() -> [(); N] + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/enum-variants.rs b/tests/ui/const-generics/enum-variants.rs new file mode 100644 index 000000000..5c6c4a8ef --- /dev/null +++ b/tests/ui/const-generics/enum-variants.rs @@ -0,0 +1,24 @@ +// check-pass +enum Foo<const N: usize> { + Variant, + Variant2(), + Variant3{}, +} + +struct Bar<const N: usize>; +struct Bar2<const N: usize>(); +struct Bar3<const N: usize> {} + +fn main() { + let _ = Foo::Variant::<1>; + let _ = Foo::Variant2::<1>(); + let _ = Foo::Variant3::<1>{}; + + let _ = Foo::<1>::Variant; + let _ = Foo::<1>::Variant2(); + let _ = Foo::<1>::Variant3{}; + + let _ = Bar::<1>; + let _ = Bar2::<1>(); + let _ = Bar3::<1>{}; +} diff --git a/tests/ui/const-generics/exhaustive-value.rs b/tests/ui/const-generics/exhaustive-value.rs new file mode 100644 index 000000000..778d49834 --- /dev/null +++ b/tests/ui/const-generics/exhaustive-value.rs @@ -0,0 +1,267 @@ +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/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr new file mode 100644 index 000000000..76a83ba67 --- /dev/null +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(): Foo<N>` is not satisfied + --> $DIR/exhaustive-value.rs:262:5 + | +LL | <() as Foo<N>>::test() + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` + | + = help: the following other types implement trait `Foo<N>`: + <() as Foo<0>> + <() as Foo<100>> + <() as Foo<101>> + <() as Foo<102>> + <() as Foo<103>> + <() as Foo<104>> + <() as Foo<105>> + <() as Foo<106>> + and 248 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/expose-default-substs-param-env.rs b/tests/ui/const-generics/expose-default-substs-param-env.rs new file mode 100644 index 000000000..e40c93116 --- /dev/null +++ b/tests/ui/const-generics/expose-default-substs-param-env.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait Foo<const N: usize> {} +pub trait Bar: Foo<{ 1 }> { } + +fn main() {} diff --git a/tests/ui/const-generics/float-generic.adt_const_params.stderr b/tests/ui/const-generics/float-generic.adt_const_params.stderr new file mode 100644 index 000000000..fef5ef0d1 --- /dev/null +++ b/tests/ui/const-generics/float-generic.adt_const_params.stderr @@ -0,0 +1,11 @@ +error[E0741]: `f32` is forbidden as the type of a const generic parameter + --> $DIR/float-generic.rs:5:17 + | +LL | fn foo<const F: f32>() {} + | ^^^ + | + = note: floats do not derive `Eq` or `Ord`, which are required for const parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/float-generic.rs b/tests/ui/const-generics/float-generic.rs new file mode 100644 index 000000000..b72059b5b --- /dev/null +++ b/tests/ui/const-generics/float-generic.rs @@ -0,0 +1,12 @@ +// revisions: simple adt_const_params +#![cfg_attr(adt_const_params, feature(adt_const_params))] +#![cfg_attr(adt_const_params, allow(incomplete_features))] + +fn foo<const F: f32>() {} +//~^ ERROR `f32` is forbidden as the type of a const generic parameter + +const C: f32 = 1.0; + +fn main() { + foo::<C>(); +} diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr new file mode 100644 index 000000000..89ca36b0f --- /dev/null +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -0,0 +1,11 @@ +error: `f32` is forbidden as the type of a const generic parameter + --> $DIR/float-generic.rs:5:17 + | +LL | fn foo<const F: f32>() {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn-const-param-call.full.stderr b/tests/ui/const-generics/fn-const-param-call.full.stderr new file mode 100644 index 000000000..b55c24498 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.full.stderr @@ -0,0 +1,15 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:11:25 + | +LL | struct Wrapper<const F: fn() -> u32>; + | ^^^^^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:13:15 + | +LL | impl<const F: fn() -> u32> Wrapper<F> { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr new file mode 100644 index 000000000..d984449e6 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.min.stderr @@ -0,0 +1,14 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:11:25 + | +LL | struct Wrapper<const F: fn() -> u32>; + | ^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:13:15 + | +LL | impl<const F: fn() -> u32> Wrapper<F> { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/fn-const-param-call.rs b/tests/ui/const-generics/fn-const-param-call.rs new file mode 100644 index 000000000..dc516fb71 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.rs @@ -0,0 +1,22 @@ +// Check that functions cannot be used as const parameters. +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn function() -> u32 { + 17 +} + +struct Wrapper<const F: fn() -> u32>; //~ ERROR: using function pointers as const generic parameters + +impl<const F: fn() -> u32> Wrapper<F> { +//~^ ERROR: using function pointers as const generic parameters + fn call() -> u32 { + F() + } +} + +fn main() { + assert_eq!(Wrapper::<function>::call(), 17); +} diff --git a/tests/ui/const-generics/fn-const-param-infer.full.stderr b/tests/ui/const-generics/fn-const-param-infer.full.stderr new file mode 100644 index 000000000..2d66a1923 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:6:25 + | +LL | struct Checked<const F: fn(usize) -> bool>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr new file mode 100644 index 000000000..f0767a109 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:6:25 + | +LL | struct Checked<const F: fn(usize) -> bool>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn-const-param-infer.rs b/tests/ui/const-generics/fn-const-param-infer.rs new file mode 100644 index 000000000..22f5f529c --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.rs @@ -0,0 +1,29 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Checked<const F: fn(usize) -> bool>; +//~^ ERROR: using function pointers as const generic parameters + +fn not_one(val: usize) -> bool { val != 1 } +fn not_two(val: usize) -> bool { val != 2 } + +fn generic_arg<T>(val: T) -> bool { true } + +fn generic<T>(val: usize) -> bool { val != 1 } + +fn main() { + let _: Option<Checked<not_one>> = None; + let _: Checked<not_one> = Checked::<not_one>; + let _: Checked<not_one> = Checked::<not_two>; + + let _ = Checked::<generic_arg>; + let _ = Checked::<{generic_arg::<usize>}>; + let _ = Checked::<{generic_arg::<u32>}>; + + let _ = Checked::<generic>; + let _ = Checked::<{generic::<u16>}>; + let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>; + let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; +} diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.rs b/tests/ui/const-generics/fn_with_two_const_inputs.rs new file mode 100644 index 000000000..0d6246a9f --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_const_inputs.rs @@ -0,0 +1,23 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn both(_: usize, b: usize) -> usize { + b +} + +fn foo<const N: usize, const M: usize>() -> [(); N + 2] +where + [(); both(N + 1, M + 1)]:, +{ + bar() + //~^ ERROR: unconstrained generic constant +} + +fn bar<const N: usize>() -> [(); N] +where + [(); N + 1]:, +{ + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.stderr b/tests/ui/const-generics/fn_with_two_const_inputs.stderr new file mode 100644 index 000000000..614e7e0d2 --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_const_inputs.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/fn_with_two_const_inputs.rs:12:5 + | +LL | bar() + | ^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N + 1]:` +note: required by a bound in `bar` + --> $DIR/fn_with_two_const_inputs.rs:18:10 + | +LL | fn bar<const N: usize>() -> [(); N] + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn_with_two_same_const_inputs.rs b/tests/ui/const-generics/fn_with_two_same_const_inputs.rs new file mode 100644 index 000000000..f0ce093e0 --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_same_const_inputs.rs @@ -0,0 +1,22 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn both(_: usize, b: usize) -> usize { + b +} + +fn foo<const N: usize>() +where + [(); both(N + 1, N + 1)]:, +{ + bar::<N>(); +} + +fn bar<const N: usize>() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/forbid-non-structural_match-types.rs b/tests/ui/const-generics/forbid-non-structural_match-types.rs new file mode 100644 index 000000000..6ae9d5cfb --- /dev/null +++ b/tests/ui/const-generics/forbid-non-structural_match-types.rs @@ -0,0 +1,13 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B<const X: A>; // ok + +struct C; + +struct D<const X: C>; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]` + +fn main() {} diff --git a/tests/ui/const-generics/forbid-non-structural_match-types.stderr b/tests/ui/const-generics/forbid-non-structural_match-types.stderr new file mode 100644 index 000000000..81b9bdfbd --- /dev/null +++ b/tests/ui/const-generics/forbid-non-structural_match-types.stderr @@ -0,0 +1,9 @@ +error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/forbid-non-structural_match-types.rs:11:19 + | +LL | struct D<const X: C>; + | ^ `C` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/foreign-item-const-parameter.rs b/tests/ui/const-generics/foreign-item-const-parameter.rs new file mode 100644 index 000000000..4fe377b59 --- /dev/null +++ b/tests/ui/const-generics/foreign-item-const-parameter.rs @@ -0,0 +1,7 @@ +extern "C" { + fn foo<const X: usize>(); //~ ERROR foreign items may not have const parameters + + fn bar<T, const X: usize>(_: T); //~ ERROR foreign items may not have type or const parameters +} + +fn main() {} diff --git a/tests/ui/const-generics/foreign-item-const-parameter.stderr b/tests/ui/const-generics/foreign-item-const-parameter.stderr new file mode 100644 index 000000000..b02db8700 --- /dev/null +++ b/tests/ui/const-generics/foreign-item-const-parameter.stderr @@ -0,0 +1,19 @@ +error[E0044]: foreign items may not have const parameters + --> $DIR/foreign-item-const-parameter.rs:2:5 + | +LL | fn foo<const X: usize>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters + | + = help: replace the const parameters with concrete consts + +error[E0044]: foreign items may not have type or const parameters + --> $DIR/foreign-item-const-parameter.rs:4:5 + | +LL | fn bar<T, const X: usize>(_: T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters + | + = help: replace the type or const parameters with concrete types or consts + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/const-generics/generic-param-mismatch.rs b/tests/ui/const-generics/generic-param-mismatch.rs new file mode 100644 index 000000000..2e201e50a --- /dev/null +++ b/tests/ui/const-generics/generic-param-mismatch.rs @@ -0,0 +1,5 @@ +fn test<const N: usize, const M: usize>() -> [u8; M] { + [0; N] //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic-param-mismatch.stderr b/tests/ui/const-generics/generic-param-mismatch.stderr new file mode 100644 index 000000000..d0776d49d --- /dev/null +++ b/tests/ui/const-generics/generic-param-mismatch.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/generic-param-mismatch.rs:2: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/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs new file mode 100644 index 000000000..d3e53d7a8 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs @@ -0,0 +1,13 @@ +// run-pass + +// To avoid having to `or` gate `_` as an expr. +#![feature(generic_arg_infer)] + +fn foo() -> [u8; 3] { + let x: [u8; _] = [0; _]; + x +} + +fn main() { + assert_eq!([0; _], foo()); +} diff --git a/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs b/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs new file mode 100644 index 000000000..251160a0f --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs @@ -0,0 +1,15 @@ +// run-pass +#![feature(generic_arg_infer)] + +// test that we dont use defaults to aide in type inference + +struct Foo<const N: usize = 2>; +impl<const N: usize> Foo<N> { + fn make_arr() -> [(); N] { + [(); N] + } +} + +fn main() { + let [(), (), ()] = Foo::<_>::make_arr(); +} diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.rs b/tests/ui/const-generics/generic_arg_infer/in-signature.rs new file mode 100644 index 000000000..1f60b2242 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.rs @@ -0,0 +1,61 @@ +#![crate_type = "rlib"] +#![feature(generic_arg_infer)] + +struct Foo<const N: usize>; +struct Bar<T, const N: usize>(T); + +fn arr_fn() -> [u8; _] { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + [0; 3] +} + +fn ty_fn() -> Bar<i32, _> { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::<i32, 3>(0) +} + +fn ty_fn_mixed() -> Bar<_, _> { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::<i32, 3>(0) +} + +const ARR_CT: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static ARR_STATIC: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +trait ArrAssocConst { + const ARR: [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConst { + const ARR: Bar<i32, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConstMixed { + const ARR: Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +trait AssocTy { + type Assoc; +} +impl AssocTy for i8 { + type Assoc = [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i16 { + type Assoc = Bar<i32, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i32 { + type Assoc = Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr new file mode 100644 index 000000000..52d1b29f9 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -0,0 +1,119 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:7:21 + | +LL | fn arr_fn() -> [u8; _] { + | -----^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `[u8; 3]` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:12:24 + | +LL | fn ty_fn() -> Bar<i32, _> { + | ---------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:17:25 + | +LL | fn ty_fn_mixed() -> Bar<_, _> { + | ----^--^- + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures + | help: replace with the correct return type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:22:15 + | +LL | const ARR_CT: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:24:20 + | +LL | static ARR_STATIC: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:26:14 + | +LL | const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:28:19 + | +LL | static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:30:20 + | +LL | const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:32:25 + | +LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar<i32, 3>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:35:21 + | +LL | const ARR: [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:39:25 + | +LL | const ARR: Bar<i32, _>; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:43:20 + | +LL | const ARR: Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:51:23 + | +LL | type Assoc = [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:55:27 + | +LL | type Assoc = Bar<i32, _>; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:59:22 + | +LL | type Assoc = Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs new file mode 100644 index 000000000..29aa0f59d --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs @@ -0,0 +1,22 @@ +#![feature(generic_arg_infer)] + +struct All<'a, T, const N: usize> { + v: &'a T, +} + +struct BadInfer<_>; +//~^ ERROR expected identifier +//~| ERROR parameter `_` is never used + +fn all_fn<'a, T, const N: usize>() {} + +fn bad_infer_fn<_>() {} +//~^ ERROR expected identifier + + +fn main() { + let a: All<_, _, _>; + all_fn(); + let v: [u8; _]; + let v: [u8; 10] = [0; _]; +} diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr new file mode 100644 index 000000000..e6d0c743d --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr @@ -0,0 +1,24 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/infer-arg-test.rs:7:17 + | +LL | struct BadInfer<_>; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/infer-arg-test.rs:13:17 + | +LL | fn bad_infer_fn<_>() {} + | ^ expected identifier, found reserved identifier + +error[E0392]: parameter `_` is never used + --> $DIR/infer-arg-test.rs:7:17 + | +LL | struct BadInfer<_>; + | ^ unused parameter + | + = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `_` to be a const parameter, use `const _: usize` instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs b/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs new file mode 100644 index 000000000..23c8d7537 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_arg_infer)] + +struct Foo<const N: bool, const M: u8>; +struct Bar<const N: u8, const M: u32>; + +fn main() { + let _: Foo<true, _> = Foo::<_, 1>; + let _: Foo<_, 1> = Foo::<true, _>; + let _: Bar<1, _> = Bar::<_, 300>; + let _: Bar<_, 300> = Bar::<1, _>; +} diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.rs b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs new file mode 100644 index 000000000..b45e2cbc7 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs @@ -0,0 +1,8 @@ +#![feature(portable_simd)] +#![feature(generic_arg_infer)] +use std::simd::Mask; + +fn main() { + let y = Mask::<_, _>::splat(false); + //~^ ERROR: type annotations needed for +} diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr new file mode 100644 index 000000000..13ea4a295 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed for `Mask<_, LANES>` + --> $DIR/issue-91614.rs:6:9 + | +LL | let y = Mask::<_, _>::splat(false); + | ^ ------------------- type must be known at this point + | + = note: cannot satisfy `_: MaskElement` + = help: the following types implement trait `MaskElement`: + i16 + i32 + i64 + i8 + isize +note: required by a bound in `Mask::<T, LANES>::splat` + --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL +help: consider giving `y` an explicit type, where the type for type parameter `T` is specified + | +LL | let y: Mask<_, LANES> = Mask::<_, _>::splat(false); + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs new file mode 100644 index 000000000..06f00de13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: u8>([u8; N as usize]) +where + [(); N as usize]:; + +struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:; + +// unifying with subtrees +struct Evaluatable<const N: u16>; +fn foo<const N: u8>() where Evaluatable<{N as usize as u16 }>: { + let _ = Foo::<N>([1; N as usize]); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs new file mode 100644 index 000000000..3b5b87b2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Evaluatable<const N: u128> {} + +struct Foo<const N: u8>([u8; N as usize]) +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:` +where + Evaluatable<{N as u128}>:; + +struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr new file mode 100644 index 000000000..5ca04d25e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr @@ -0,0 +1,26 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:6:25 + | +LL | struct Foo<const N: u8>([u8; N as usize]) + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N as usize]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:12:26 + | +LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:16:25 + | +LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs new file mode 100644 index 000000000..7561ae2fe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs @@ -0,0 +1,47 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128<const N: u128>; + +struct HasCastInTraitImpl<const N: usize, const M: u128>; +impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + +pub fn use_trait_impl<const N: usize>() +where + [(); { N + 1}]:, + EvaluatableU128<{N as u128}>:, { + fn assert_impl<T: Trait>() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + //~^ Error: mismatched types + assert_impl::<HasCastInTraitImpl<14, 13>>(); + //~^ Error: mismatched types +} +pub fn use_trait_impl_2<const N: usize>() +where + [(); { N + 1}]:, + EvaluatableU128<{N as _}>:, { + fn assert_impl<T: Trait>() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + //~^ Error: mismatched types + assert_impl::<HasCastInTraitImpl<14, 13>>(); + //~^ Error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr new file mode 100644 index 000000000..cdf97bd88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -0,0 +1,187 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:17:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:20:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:23:5 + | +LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:25:5 + | +LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:35:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:38:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:41:5 + | +LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:43:5 + | +LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs new file mode 100644 index 000000000..184263f89 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs @@ -0,0 +1,29 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128<const N: u128>; + +struct HasCastInTraitImpl<const N: usize, const M: u128>; +impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + +pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, { + fn assert_impl<T: Trait>() {} + + assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>(); + assert_impl::<HasCastInTraitImpl<N, { N as _ }>>(); + assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>(); + assert_impl::<HasCastInTraitImpl<13, 13>>(); +} +pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, { + fn assert_impl<T: Trait>() {} + + assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>(); + assert_impl::<HasCastInTraitImpl<N, { N as _ }>>(); + assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>(); + assert_impl::<HasCastInTraitImpl<13, 13>>(); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 000000000..916d60c0e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const N: u8>(a: [(); N as usize]) { + bar::<{ N as usize as usize }>(); + //~^ error: unconstrained generic constant +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 000000000..d48b639db --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-consts-as-cast-5.rs:5:11 + | +LL | bar::<{ N as usize as usize }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr new file mode 100644 index 000000000..1d10dfdf1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -0,0 +1,19 @@ +error: unconstrained generic constant + --> $DIR/array-size-in-generic-struct-param.rs:8:38 + | +LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); 0 + N]:` + +error: overly complex generic constant + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^^^^^^^^^^ field access is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr new file mode 100644 index 000000000..18e9135d0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -0,0 +1,29 @@ +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:8:48 + | +LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^ cannot perform const operation using `CFG` + | + = help: const parameters may only be used as standalone arguments, i.e. `CFG` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: `Config` is forbidden as the type of a const generic parameter + --> $DIR/array-size-in-generic-struct-param.rs:17:21 + | +LL | struct B<const CFG: Config> { + | ^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs new file mode 100644 index 000000000..7d3fe413c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs @@ -0,0 +1,29 @@ +// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`. +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs, adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +#[allow(dead_code)] +struct ArithArrayLen<const N: usize>([u32; 0 + N]); +//[full]~^ ERROR unconstrained generic constant +//[min]~^^ ERROR generic parameters may not be used in const operations + +#[derive(PartialEq, Eq)] +struct Config { + arr_size: usize, +} + +struct B<const CFG: Config> { + //[min]~^ ERROR `Config` is forbidden + arr: [u8; CFG.arr_size], + //[full]~^ ERROR overly complex generic constant + //[min]~^^ ERROR generic parameters may not be used in const operations +} + +const C: Config = Config { arr_size: 5 }; + +fn main() { + let b = B::<C> { arr: [1, 2, 3, 4, 5] }; + assert_eq!(b.arr.len(), 5); +} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs new file mode 100644 index 000000000..e8f89cb1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs @@ -0,0 +1,27 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} +impl<T> Trait for T { + const ASSOC: usize = std::mem::size_of::<T>(); +} + +struct Foo<T: Trait>([u8; T::ASSOC]) +where + [(); T::ASSOC]:; + +fn bar<T: Trait>() +where + [(); T::ASSOC]:, +{ + let _: Foo<T> = Foo::<_>(make()); +} + +fn make() -> ! { + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs new file mode 100644 index 000000000..c8f7553da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, { + bar::<{ T::ASSOC }>(); + //~^ ERROR: unconstrained generic constant +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr new file mode 100644 index 000000000..e4a0cabe5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/doesnt_unify_evaluatable.rs:9:11 + | +LL | bar::<{ T::ASSOC }>(); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs new file mode 100644 index 000000000..274caa1e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +struct Foo<T: Trait>(T) +where + [(); T::ASSOC]:; + +impl<T: Trait> Drop for Foo<T> +where + [(); T::ASSOC]:, +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs new file mode 100644 index 000000000..6597b9f2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo<T: Trait, U: Trait>() where [(); T::ASSOC]:, { + bar::<{ T::ASSOC }>(); +} + +fn bar<const N: usize>() -> [(); N] { + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-const.rs b/tests/ui/const-generics/generic_const_exprs/associated-const.rs new file mode 100644 index 000000000..a67776322 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-const.rs @@ -0,0 +1,11 @@ +// check-pass +struct Foo<T>(T); +impl<T> Foo<T> { + const VALUE: usize = std::mem::size_of::<T>(); +} + +fn test<T>() { + let _ = [0; Foo::<u8>::VALUE]; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs new file mode 100644 index 000000000..b839008d4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait BlockCipher { + const BLOCK_SIZE: usize; +} + +struct FooCipher; +impl BlockCipher for FooCipher { + const BLOCK_SIZE: usize = 64; +} + +struct BarCipher; +impl BlockCipher for BarCipher { + const BLOCK_SIZE: usize = 32; +} + +pub struct Block<C>(#[allow(unused_tuple_struct_fields)] C); + +pub fn test<C: BlockCipher, const M: usize>() +where + [u8; M - C::BLOCK_SIZE]: Sized, +{ + let _ = [0; M - C::BLOCK_SIZE]; +} + +fn main() { + test::<FooCipher, 128>(); + test::<BarCipher, 64>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs new file mode 100644 index 000000000..97be07493 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs @@ -0,0 +1,8 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<const N: usize>; + +pub fn foo<const N: usize>() -> Foo<{ N + 1 }> { + Foo +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs new file mode 100644 index 000000000..15d618cae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] +where + [u8; std::mem::size_of::<T>() - 1]: Sized, +{ + [0; std::mem::size_of::<T>() - 1] +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs new file mode 100644 index 000000000..df454dae7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] + +use std::str::FromStr; + +pub struct If<const CONDITION: bool>; + +pub trait True {} + +impl True for If<true> {} + +pub struct FixedI32<const FRAC: u32>; + +impl<const FRAC: u32> FromStr for FixedI32<FRAC> +where + If<{ FRAC <= 32 }>: True, +{ + type Err = (); + fn from_str(_s: &str) -> Result<Self, Self::Err> { + unimplemented!() + } +} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.rs b/tests/ui/const-generics/generic_const_exprs/closures.rs new file mode 100644 index 000000000..1ea310d06 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.rs @@ -0,0 +1,6 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +fn test<const N: usize>() -> [u8; N + (|| 42)()] {} +//~^ ERROR cycle detected when building an abstract representation + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.stderr b/tests/ui/const-generics/generic_const_exprs/closures.stderr new file mode 100644 index 000000000..a7d891d77 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.stderr @@ -0,0 +1,26 @@ +error[E0391]: cycle detected when building an abstract representation for `test::{constant#0}` + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + | +note: ...which requires building THIR for `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + = note: ...which again requires building an abstract representation for `test::{constant#0}`, completing the cycle +note: cycle used when checking that `test` is well-formed + --> $DIR/closures.rs:3:1 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs new file mode 100644 index 000000000..7332a8f03 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs @@ -0,0 +1,11 @@ +#![feature(inline_const, generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +fn foo<T>() { + let _ = [0u8; const { std::mem::size_of::<T>() }]; + //~^ ERROR: overly complex generic constant +} + +fn main() { + foo::<i32>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr new file mode 100644 index 000000000..f26259908 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -0,0 +1,20 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-block-is-poly.rs:1:26 + | +LL | #![feature(inline_const, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: overly complex generic constant + --> $DIR/const-block-is-poly.rs:5:19 + | +LL | let _ = [0u8; const { std::mem::size_of::<T>() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 000000000..5874625ad --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + type Assoc: Default; +} + +impl Foo<0> for () { + type Assoc = u32; +} + +impl Foo<3> for () { + type Assoc = i64; +} + +fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc +where + (): Foo<{ N + 1 }>, +{ + Default::default() +} + +fn main() { + let mut _q = Default::default(); + _q = foo::<_, 2>(_q); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs new file mode 100644 index 000000000..6093fc70b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs, generic_arg_infer)] +#![allow(incomplete_features)] + +// minimized repro for #105205 +// +// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a +// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter +// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed` +// obligation into `WellFormed(Expr(L - 1))` + +fn foo<const N: usize, const M: usize>(_: [(); N + 1 + M]) {} + +fn ice<const L: usize>() +where + [(); (L - 1) + 1 + L]:, +{ + foo::<_, L>([(); L + 1 + L]); + //~^ ERROR: mismatched types + //~^^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr new file mode 100644 index 000000000..da5194696 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/wf_obligation.rs:17:17 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L` + | + = note: expected constant `N + 1 + M` + found constant `L + 1 + L` + +error: unconstrained generic constant + --> $DIR/wf_obligation.rs:17:22 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs new file mode 100644 index 000000000..dfc69e0b0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs @@ -0,0 +1,15 @@ +// aux-build:const_evaluatable_lib.rs +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized { + assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]); +} + +fn main() { + assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]); + user::<u32>(); + user::<u64>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs new file mode 100644 index 000000000..b08fffd69 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs @@ -0,0 +1,14 @@ +// aux-build:const_evaluatable_lib.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user<T>() { + let _ = const_evaluatable_lib::test1::<T>(); + //~^ ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr new file mode 100644 index 000000000..7b4d46b82 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -0,0 +1,54 @@ +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::<T>() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::<T>() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr new file mode 100644 index 000000000..d674e3acd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -0,0 +1,39 @@ +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:14:32 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:21:37 + | +LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + +error: aborting due to 2 previous errors; 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr new file mode 100644 index 000000000..74111ef1d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -0,0 +1,34 @@ +error: overly complex generic constant + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: overly complex generic constant + --> $DIR/dependence_lint.rs:21:17 + | +LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:14:12 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs new file mode 100644 index 000000000..b715e07f8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs @@ -0,0 +1,26 @@ +// revisions: full gce +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![cfg_attr(gce, feature(generic_const_exprs))] +#![allow(incomplete_features)] + +use std::mem::size_of; + +fn foo<T>() { + [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + //[gce]~^ ERROR unconstrained + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR unconstrained generic + [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + //[gce]~^ ERROR overly complex + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR overly complex +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.rs b/tests/ui/const-generics/generic_const_exprs/different-fn.rs new file mode 100644 index 000000000..e8bc703bd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; +use std::marker::PhantomData; + +struct Foo<T>(PhantomData<T>); + +fn test<T>() -> [u8; size_of::<T>()] { + [0; size_of::<Foo<T>>()] + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types +} + +fn main() { + test::<u32>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.stderr b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr new file mode 100644 index 000000000..83a2f3740 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/different-fn.rs:10:5 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()` + | + = note: expected constant `size_of::<T>()` + found constant `size_of::<Foo<T>>()` + +error: unconstrained generic constant + --> $DIR/different-fn.rs:10:9 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/division.rs b/tests/ui/const-generics/generic_const_exprs/division.rs new file mode 100644 index 000000000..098fa9e04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/division.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn with_bound<const N: usize>() where [u8; N / 2]: Sized { + let _: [u8; N / 2] = [0; N / 2]; +} + +fn main() { + with_bound::<4>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 000000000..3543960c3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a repro for #82279. It checks that we don't error +// when calling is_const_evaluatable on `std::mem::size_of::<T>()` +// when looking for candidates that may prove `T: Foo` in `foo` + +trait Foo {} + +#[allow(dead_code)] +fn foo<T: Foo>() {} + +impl<T> Foo for T where [(); std::mem::size_of::<T>()]: {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/drop_impl.rs b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs new file mode 100644 index 000000000..077f77aa0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs @@ -0,0 +1,16 @@ +//check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: usize> +where + [(); N + 1]: ; + +impl<const N: usize> Drop for Foo<N> +where + [(); N + 1]: , +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs new file mode 100644 index 000000000..e4111157e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we use the elaborated predicates from traits +// to satisfy const evaluatable predicates. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::mem::size_of; + +trait Foo: Sized +where + [(); size_of::<Self>()]: Sized, +{ +} + +impl Foo for u64 {} +impl Foo for u32 {} + +fn foo<T: Foo>() -> [u8; size_of::<T>()] { + [0; size_of::<T>()] +} + +fn main() { + assert_eq!(foo::<u32>(), [0; 4]); + assert_eq!(foo::<u64>(), [0; 8]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs new file mode 100644 index 000000000..8023b998a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -0,0 +1,26 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Const<const U: u8>; + +pub trait Trait { + type AssocTy; + fn assoc_fn() -> Self::AssocTy; +} + +impl<const U: u8> Trait for Const<U> // OK, trait impl predicates +where + Const<{ my_const_fn(U) }>: , +{ + type AssocTy = Const<{ my_const_fn(U) }>; + //~^ ERROR private type + fn assoc_fn() -> Self::AssocTy { + Const + } +} + +const fn my_const_fn(val: u8) -> u8 { + // body of this function doesn't matter + val +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr new file mode 100644 index 000000000..2d9de8805 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:16:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs new file mode 100644 index 000000000..c59d62e57 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs @@ -0,0 +1,26 @@ +// build-pass + +#![feature(generic_const_exprs)] +//~^ WARNING the feature `generic_const_exprs` is incomplete + +trait Generic { + const ASSOC: usize; +} + +impl Generic for u8 { + const ASSOC: usize = 17; +} +impl Generic for u16 { + const ASSOC: usize = 13; +} + + +fn uses_assoc_type<T: Generic, const N: usize>() -> [u8; N + T::ASSOC] { + [0; N + T::ASSOC] +} + +fn only_generic_n<const N: usize>() -> [u8; N + 13] { + uses_assoc_type::<u16, N>() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr new file mode 100644 index 000000000..8eb1fccc5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/eval-try-unify.rs:3:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs new file mode 100644 index 000000000..340e35e1c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs @@ -0,0 +1,22 @@ +// check-pass + +// We previously always returned ambiguity when equating generic consts, even if they +// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1` +// should fail. +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +enum Assert<const COND: bool> {} +trait IsTrue {} +impl IsTrue for Assert<true> {} + +struct Foo<const N: usize, const M: usize>; +trait Bar<const N: usize, const M: usize> {} +impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M> +where + Assert<{ N > 1 }>: IsTrue, + Assert<{ M > 1 }>: IsTrue, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs new file mode 100644 index 000000000..10ab2fd86 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs @@ -0,0 +1,11 @@ +type Arr<const N: usize> = [u8; N - 1]; +//~^ ERROR generic parameters may not be used in const operations + +fn test<const N: usize>() -> Arr<N> where Arr<N>: Default { + Default::default() +} + +fn main() { + let x = test::<33>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr new file mode 100644 index 000000000..2d60ebaa8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/feature-gate-generic_const_exprs.rs:1:33 + | +LL | type Arr<const N: usize> = [u8; N - 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/fn_call.rs b/tests/ui/const-generics/generic_const_exprs/fn_call.rs new file mode 100644 index 000000000..cbe4277df --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/fn_call.rs @@ -0,0 +1,30 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn test_me<T>(a: usize, b: usize) -> usize { + if a < b { + std::mem::size_of::<T>() + } else { + usize::MAX + } +} + +fn test_simple<T>() -> [u8; std::mem::size_of::<T>()] +where + [u8; std::mem::size_of::<T>()]: Sized, +{ + [0; std::mem::size_of::<T>()] +} + +fn test_with_args<T, const N: usize>() -> [u8; test_me::<T>(N, N + 1) + N] +where + [u8; test_me::<T>(N, N + 1) + N]: Sized, +{ + [0; test_me::<T>(N, N + 1) + N] +} + +fn main() { + assert_eq!([0; 8], test_simple::<u64>()); + assert_eq!([0; 12], test_with_args::<u64, 4>()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs new file mode 100644 index 000000000..b8f9827ec --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn test<const N: usize>() -> [u8; N - 1] { + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr new file mode 100644 index 000000000..bd71b49ee --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/from-sig-fail.rs:4:35 + | +LL | fn test<const N: usize>() -> [u8; N - 1] { + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig.rs b/tests/ui/const-generics/generic_const_exprs/from-sig.rs new file mode 100644 index 000000000..28de4f864 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ N > 10 }> { + Foo +} + +fn main() { + let _: Foo<true> = test::<12>(); + let _: Foo<false> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.rs b/tests/ui/const-generics/generic_const_exprs/function-call.rs new file mode 100644 index 000000000..3c866333d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zdeduplicate-diagnostics=yes + +const fn foo<T>() -> usize { + // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here, + // which would cause this function to fail on 32 bit systems. + if false { + std::mem::size_of::<T>() + } else { + 8 + } +} + +fn test<T>() { + let _ = [0; foo::<T>()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.stderr b/tests/ui/const-generics/generic_const_exprs/function-call.stderr new file mode 100644 index 000000000..84abfe578 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.stderr @@ -0,0 +1,12 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/function-call.rs:15:17 + | +LL | let _ = [0; foo::<T>()]; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs new file mode 100644 index 000000000..7120d6ee2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; + +struct Foo<T, const N: usize>(T); + +impl<T> Foo<T, { size_of::<T>() }> { + fn test() { + let _: [u8; std::mem::size_of::<T>()]; + } +} + +trait Bar<const N: usize> { + fn test_me(); +} + +impl<T> Bar<{ size_of::<T>() }> for Foo<T, 3> { + fn test_me() { + let _: [u8; std::mem::size_of::<T>()]; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs new file mode 100644 index 000000000..b8058c252 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::{mem, ptr}; + +fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1]) +where + [T; N - 1]: Sized, +{ + let arr = mem::ManuallyDrop::new(arr); + unsafe { + let head = ptr::read(&arr[0]); + let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]); + (head, tail) + } +} + +fn main() { + let arr = [0, 1, 2, 3, 4]; + let (head, tail) = split_first(arr); + assert_eq!(head, 0); + assert_eq!(tail, [1, 2, 3, 4]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100217.rs b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs new file mode 100644 index 000000000..acdc348a3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs @@ -0,0 +1,42 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait TraitOne { + const MY_NUM: usize; + type MyErr: std::fmt::Debug; + + fn do_one_stuff(arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr>; +} + +trait TraitTwo { + fn do_two_stuff(); +} + +impl<O: TraitOne> TraitTwo for O +where + [(); Self::MY_NUM]:, +{ + fn do_two_stuff() { + O::do_one_stuff([5; Self::MY_NUM]).unwrap() + } +} + +struct Blargotron; + +#[derive(Debug)] +struct ErrTy<const N: usize>([(); N]); + +impl TraitOne for Blargotron { + const MY_NUM: usize = 3; + type MyErr = ErrTy<{ Self::MY_NUM }>; + + fn do_one_stuff(_arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr> { + Ok(()) + } +} + +fn main() { + Blargotron::do_two_stuff(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100360.rs b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs new file mode 100644 index 000000000..5572f1f88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs @@ -0,0 +1,13 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +fn foo<const B: &'static bool>(arg: &'static bool) -> bool { + B == arg +} + +fn main() { + foo::<{ &true }>(&false); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102074.rs b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs new file mode 100644 index 000000000..66d15cf12 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs @@ -0,0 +1,23 @@ +// check-pass +// Checks that the NoopMethodCall lint doesn't call Instance::resolve on unresolved consts + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[derive(Debug, Clone)] +pub struct Aes128CipherKey([u8; Aes128Cipher::KEY_LEN]); + +impl Aes128CipherKey { + pub fn new(key: &[u8; Aes128Cipher::KEY_LEN]) -> Self { + Self(key.clone()) + } +} + +#[derive(Debug, Clone)] +pub struct Aes128Cipher; + +impl Aes128Cipher { + const KEY_LEN: usize = 16; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs new file mode 100644 index 000000000..7aea0d30d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait X { + type Y<'a>; +} + +const _: () = { + fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument +}; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr new file mode 100644 index 000000000..8278edabe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr @@ -0,0 +1,33 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + | ^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.rs b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs new file mode 100644 index 000000000..d8b23bc01 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait<T> { + fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr new file mode 100644 index 000000000..ed7a8cb19 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr @@ -0,0 +1,14 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:5:12 + | +LL | fn fnc<const N: usize = "">(&self) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:6:12 + | +LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.rs b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs new file mode 100644 index 000000000..e28ba3b1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Combination<const STRATEGIES: usize>; + +impl<const STRATEGIES: usize> Combination<STRATEGIES> { + fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> { + Combination + } +} + +pub fn main() { + Combination::<0>.and::<_>().and::<_>(); + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr new file mode 100644 index 000000000..0be4c43da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-105608.rs:13:22 + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ^^^ cannot infer type of the type parameter `M` declared on the associated function `and` + | +help: consider specifying the generic argument + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr new file mode 100644 index 000000000..0742db398 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | + = note: expected constant `X` + found constant `Self::SIZE` + +error: unconstrained generic constant + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr new file mode 100644 index 000000000..65822856e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -0,0 +1,27 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | | + | arguments to this struct are incorrect + | + = note: expected array `[u32; X]` + found array `[u32; Self::SIZE]` +note: tuple struct defined here + --> $DIR/issue-62504.rs:14:8 + | +LL | struct ArrayHolder<const X: usize>([u32; X]); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs new file mode 100644 index 000000000..a97f4b8ff --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs @@ -0,0 +1,27 @@ +// revisions: full min +#![allow(incomplete_features)] +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +trait HasSize { + const SIZE: usize; +} + +impl<const X: usize> HasSize for ArrayHolder<X> { + const SIZE: usize = X; +} + +struct ArrayHolder<const X: usize>([u32; X]); + +impl<const X: usize> ArrayHolder<X> { + pub const fn new() -> Self { + ArrayHolder([0; Self::SIZE]) + //~^ ERROR mismatched types + //[full]~^^ ERROR unconstrained generic constant + //[min]~^^^ ERROR constant expression depends on a generic parameter + } +} + +fn main() { + let mut array = ArrayHolder::new(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.rs b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs new file mode 100644 index 000000000..9b36699bb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Bar<T> {} +impl<T> Bar<T> for [u8; T] {} +//~^ ERROR expected value, found type parameter `T` + +struct Foo<const N: usize> {} +impl<const N: usize> Foo<N> +where + [u8; N]: Bar<[(); N]>, +{ + fn foo() {} +} + +fn main() { + Foo::foo(); + //~^ ERROR the function or associated item +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr new file mode 100644 index 000000000..eb4ff8305 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -0,0 +1,30 @@ +error[E0423]: expected value, found type parameter `T` + --> $DIR/issue-69654.rs:5:25 + | +LL | impl<T> Bar<T> for [u8; T] {} + | - ^ not a value + | | + | found this type parameter + +error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo<const N: usize> {} + | -------------------------- function or associated item `foo` not found for this struct +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds + | +note: trait bound `[u8; _]: Bar<[(); _]>` was not satisfied + --> $DIR/issue-69654.rs:11:14 + | +LL | impl<const N: usize> Foo<N> + | ------ +LL | where +LL | [u8; N]: Bar<[(); N]>, + | ^^^^^^^^^^^^ unsatisfied trait bound introduced here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr new file mode 100644 index 000000000..ea6f5f692 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -0,0 +1,38 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:17 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `LHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `LHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:24 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `RHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `RHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:25 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `I` + | + = help: const parameters may only be used as standalone arguments, i.e. `I` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:36 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `J` + | + = help: const parameters may only be used as standalone arguments, i.e. `J` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs new file mode 100644 index 000000000..657fec2e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -0,0 +1,33 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +pub struct IsLessOrEqual<const LHS: u32, const RHS: u32>; +pub struct Condition<const CONDITION: bool>; +pub trait True {} + +impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where + Condition<{ LHS <= RHS }>: True +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations +{ +} +impl True for Condition<true> {} + +struct S<const I: u32, const J: u32>; +impl<const I: u32, const J: u32> S<I, J> +where + IsLessOrEqual<I, 8>: True, + IsLessOrEqual<J, 8>: True, + IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations + // Condition<{ 8 - I <= 8 - J }>: True, +{ + fn print() { + println!("I {} J {}", I, J); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr new file mode 100644 index 000000000..f2fddfbfb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:12 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:32 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr new file mode 100644 index 000000000..42671412f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72819-generic-in-const-eval.rs:8:17 + | +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs new file mode 100644 index 000000000..7a5aa9e47 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs @@ -0,0 +1,23 @@ +// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type +// bounds. +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Arr<const N: usize> +where Assert::<{N < usize::MAX / 2}>: IsTrue, +//[min]~^ ERROR generic parameters may not be used in const operations +{ +} + +enum Assert<const CHECK: bool> {} + +trait IsTrue {} + +impl IsTrue for Assert<true> {} + +fn main() { + let x: Arr<{usize::MAX}> = Arr {}; + //[full]~^ ERROR mismatched types + //[full]~| ERROR mismatched types +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73298.rs b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs new file mode 100644 index 000000000..3c59e1b79 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs @@ -0,0 +1,23 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::convert::AsMut; +use std::default::Default; + +trait Foo: Sized { + type Baz: Default + AsMut<[u8]>; + fn bar() { + Self::Baz::default().as_mut(); + } +} + +impl Foo for () { + type Baz = [u8; 1 * 1]; + //type Baz = [u8; 1]; +} + +fn main() { + <() as Foo>::bar(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73899.rs b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs new file mode 100644 index 000000000..d1ab1be04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo {} + +impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + +trait FooImpl<const IS_ZERO: bool> {} + +impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} + +impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {} + +fn foo<T: Foo>(_v: T) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74634.rs b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs new file mode 100644 index 000000000..cd1f7a9da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs @@ -0,0 +1,28 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait If<const COND: bool> {} +impl If<true> for () {} + +trait IsZero<const N: u8> { + type Answer; +} + +struct True; +struct False; + +impl<const N: u8> IsZero<N> for () +where (): If<{N == 0}> { + type Answer = True; +} + +trait Foobar<const N: u8> {} + +impl<const N: u8> Foobar<N> for () +where (): IsZero<N, Answer = True> {} + +impl<const N: u8> Foobar<N> for () +where (): IsZero<N, Answer = False> {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.rs b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs new file mode 100644 index 000000000..0bcb997d9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs @@ -0,0 +1,8 @@ +fn bug<'a>() +where + [(); { //~ ERROR mismatched types + let _: &'a (); //~ ERROR a non-static lifetime is not allowed in a `const` + }]: +{} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr new file mode 100644 index 000000000..e7673df0a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr @@ -0,0 +1,22 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-74713.rs:4:17 + | +LL | let _: &'a (); + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-74713.rs:3:10 + | +LL | [(); { + | __________^ +LL | | let _: &'a (); +LL | | }]: + | |_____^ expected `usize`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.rs b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs new file mode 100644 index 000000000..10247ce6b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Bool<const B: bool>; + +trait True {} + +impl True for Bool<true> {} + +fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True { + todo!() +} + +fn main() { + test::<2>(); + //~^ ERROR function takes 2 generic arguments +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr new file mode 100644 index 000000000..c587a7e15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-76595.rs:15:5 + | +LL | test::<2>(); + | ^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `T`, `P` + --> $DIR/issue-76595.rs:10:4 + | +LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True { + | ^^^^ - -------------- +help: add missing generic argument + | +LL | test::<2, P>(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs new file mode 100644 index 000000000..2fa9a71fb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a minimized reproduction for #79518 where +// during error handling for the type mismatch we would try +// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE + +trait Foo { + type Assoc: PartialEq; + const AssocInstance: Self::Assoc; + + fn foo() + where + [(); std::mem::size_of::<Self::Assoc>()]: , + { + Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()]; + //~^ Error: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr new file mode 100644 index 000000000..9baf9790e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32 + | +LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()]; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); std::mem::size_of::<Self::Assoc>()]` + | | + | expected because this is `<Self as Foo>::Assoc` + | + = note: expected associated type `<Self as Foo>::Assoc` + found array `[(); std::mem::size_of::<Self::Assoc>()]` + = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); std::mem::size_of::<Self::Assoc>()]` or calling a method that returns `<Self as Foo>::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs new file mode 100644 index 000000000..77d3c98da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the correct `param_env` is used so that +// attempting to normalize `Self::N` does not cause an ICE. + +pub struct Foo<const N: usize>; + +impl<const N: usize> Foo<N> { + pub fn foo() {} +} + +pub trait Bar { + const N: usize; + fn bar() + where + [(); Self::N]: , + { + Foo::<{ Self::N }>::foo(); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.rs b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs new file mode 100644 index 000000000..275f69953 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs @@ -0,0 +1,32 @@ +// check-fail + +// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::size_of; + +struct Inline<T> +where + [u8; size_of::<T>() + 1]: , +{ + _phantom: PhantomData<T>, + buf: [u8; size_of::<T>() + 1], +} + +impl<T> Inline<T> +where + [u8; size_of::<T>() + 1]: , +{ + pub fn new(val: T) -> Inline<T> { + todo!() + } +} + +fn main() { + let dst = Inline::<dyn Debug>::new(0); //~ ERROR + //~^ ERROR +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr new file mode 100644 index 000000000..6aa8ee13b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -0,0 +1,71 @@ +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::<dyn Debug>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::<dyn Debug>::{constant#0}` + --> $DIR/issue-80742.rs:22:10 + | +LL | [u8; size_of::<T>() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied + --> $DIR/issue-80742.rs:30:36 + | +LL | struct Inline<T> + | ---------------- function or associated item `new` not found for this struct +... +LL | let dst = Inline::<dyn Debug>::new(0); + | ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | + = note: doesn't satisfy `dyn Debug: Sized` + | +note: trait bound `dyn Debug: Sized` was not satisfied + --> $DIR/issue-80742.rs:20:6 + | +LL | impl<T> Inline<T> + | ^ --------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl<T: ?Sized> Inline<T> + | ++++++++ + +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::<dyn Debug>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::<dyn Debug>::{constant#0}` + --> $DIR/issue-80742.rs:14:10 + | +LL | [u8; size_of::<T>() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::<dyn Debug>::new(0); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:12:15 + | +LL | struct Inline<T> + | ^ required by this bound in `Inline` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Inline<T: ?Sized> + | ++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0599. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-82268.rs b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs new file mode 100644 index 000000000..d08fc5beb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Collate<Op> { + type Pass; + type Fail; + + fn collate(self) -> (Self::Pass, Self::Fail); +} + +impl<Op> Collate<Op> for () { + type Pass = (); + type Fail = (); + + fn collate(self) -> ((), ()) { + ((), ()) + } +} + +trait CollateStep<X, Prev> { + type Pass; + type Fail; + fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail); +} + +impl<X, P, F> CollateStep<X, (P, F)> for () { + type Pass = (X, P); + type Fail = F; + + fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) { + ((x, p), f) + } +} + +struct CollateOpImpl<const MASK: u32>; +trait CollateOpStep { + type NextOp; + type Apply; +} + +impl<const MASK: u32> CollateOpStep for CollateOpImpl<MASK> +where + CollateOpImpl<{ MASK >> 1 }>: Sized, +{ + type NextOp = CollateOpImpl<{ MASK >> 1 }>; + type Apply = (); +} + +impl<H, T, Op: CollateOpStep> Collate<Op> for (H, T) +where + T: Collate<Op::NextOp>, + Op::Apply: CollateStep<H, (T::Pass, T::Fail)>, +{ + type Pass = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Pass; + type Fail = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Fail; + + fn collate(self) -> (Self::Pass, Self::Fail) { + <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::collate_step(self.0, self.1.collate()) + } +} + +fn collate<X, const MASK: u32>(x: X) -> (X::Pass, X::Fail) +where + X: Collate<CollateOpImpl<MASK>>, +{ + x.collate() +} + +fn main() { + dbg!(collate::<_, 5>(("Hello", (42, ('!', ()))))); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.rs b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs new file mode 100644 index 000000000..fac811d13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs @@ -0,0 +1,38 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {} +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR: method not compatible with trait [E0308] + self.reference.size() + //~^ ERROR: unconstrained generic constant + //~| ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr new file mode 100644 index 000000000..b693023f1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr @@ -0,0 +1,34 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:30:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error: unconstrained generic constant + --> $DIR/issue-83765.rs:32:24 + | +LL | self.reference.size() + | ^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` +note: required by a bound in `TensorSize::size` + --> $DIR/issue-83765.rs:9:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` + +error[E0308]: mismatched types + --> $DIR/issue-83765.rs:32:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected constant `DIM` + found constant `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83972.rs b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs new file mode 100644 index 000000000..0063719b8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs @@ -0,0 +1,38 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub trait Foo { + fn foo(&self); +} + +pub struct FooImpl<const N: usize>; +impl<const N: usize> Foo for FooImpl<N> { + fn foo(&self) {} +} + +pub trait Bar: 'static { + type Foo: Foo; + fn get() -> &'static Self::Foo; +} + +struct BarImpl; +impl Bar for BarImpl { + type Foo = FooImpl< + { + { 4 } + }, + >; + fn get() -> &'static Self::Foo { + &FooImpl + } +} + +pub fn boom<B: Bar>() { + B::get().foo(); +} + +fn main() { + boom::<BarImpl>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84408.rs b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs new file mode 100644 index 000000000..fb2e5590d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs @@ -0,0 +1,38 @@ +// Regression test for #84408. +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Melon<const X: usize> { + fn new(arr: [i32; X]) -> Self; + fn change<T: Melon<X>>(self) -> T; +} + +struct Foo([i32; 5]); +struct Bar<const A: usize, const B: usize>([i32; A + B]) +where + [(); A + B]: ; + +impl Melon<5> for Foo { + fn new(arr: [i32; 5]) -> Self { + Foo(arr) + } + fn change<T: Melon<5>>(self) -> T { + T::new(self.0) + } +} + +impl<const A: usize, const B: usize> Melon<{ A + B }> for Bar<A, B> +where + [(); A + B]: , +{ + fn new(arr: [i32; A + B]) -> Self { + Bar(arr) + } + fn change<T: Melon<{ A + B }>>(self) -> T { + T::new(self.0) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84669.rs b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs new file mode 100644 index 000000000..3933ff20a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs @@ -0,0 +1,30 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Output; + + fn foo() -> Self::Output; +} + +impl Foo for [u8; 3] { + type Output = [u8; 1 + 2]; + + fn foo() -> [u8; 3] { + [1u8; 3] + } +} + +fn bug<const N: usize>() +where + [u8; N]: Foo, + <[u8; N] as Foo>::Output: AsRef<[u8]>, +{ + <[u8; N]>::foo().as_ref(); +} + +fn main() { + bug::<3>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.rs b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs new file mode 100644 index 000000000..3a7f4c618 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs @@ -0,0 +1,32 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait _Contains<T> { + const does_contain: bool; +} + +trait Contains<T, const Satisfied: bool> {} + +trait Delegates<T> {} + +impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + +const fn contains<A, B>() -> bool +where + A: _Contains<B>, +{ + A::does_contain +} + +impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + +fn writes_to_path<C>(cap: &C) { + writes_to_specific_path(&cap); + //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277] + //~| ERROR: unconstrained generic constant + //~| ERROR: mismatched types [E0308] +} + +fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr new file mode 100644 index 000000000..e50ac671e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `Delegates<U>` is implemented for `T` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ------------ unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ + | | + | required by a bound introduced by this call + | + = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^----------------------^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error[E0308]: mismatched types + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::<T, U>() }` + | + = note: expected constant `true` + found constant `{ contains::<T, U>() }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-86710.rs b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs new file mode 100644 index 000000000..bdd8a21b3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::marker::PhantomData; + +fn main() { + let x = FooImpl::<BarImpl<1>> { phantom: PhantomData }; + let _ = x.foo::<BarImpl<1>>(); +} + +trait Foo<T> +where + T: Bar, +{ + fn foo<U>(&self) + where + T: Operation<U>, + <T as Operation<U>>::Output: Bar; +} + +struct FooImpl<T> +where + T: Bar, +{ + phantom: PhantomData<T>, +} + +impl<T> Foo<T> for FooImpl<T> +where + T: Bar, +{ + fn foo<U>(&self) + where + T: Operation<U>, + <T as Operation<U>>::Output: Bar, + { + <<T as Operation<U>>::Output as Bar>::error_occurs_here(); + } +} + +trait Bar { + fn error_occurs_here(); +} + +struct BarImpl<const N: usize>; + +impl<const N: usize> Bar for BarImpl<N> { + fn error_occurs_here() {} +} + +trait Operation<Rhs> { + type Output; +} + +//// Part-A: This causes error. +impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> +where + BarImpl<{ N + M }>: Sized, +{ + type Output = BarImpl<{ N + M }>; +} + +//// Part-B: This doesn't cause error. +// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> { +// type Output = BarImpl<M>; +// } + +//// Part-C: This also doesn't cause error. +// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> { +// type Output = BarImpl<{ M }>; +// } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-89851.rs b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs new file mode 100644 index 000000000..cde849d90 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs @@ -0,0 +1,12 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub const BAR: () = ice::<"">(); +pub const fn ice<const N: &'static str>() { + &10; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-90847.rs b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs new file mode 100644 index 000000000..ebc6fe141 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs @@ -0,0 +1,9 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(adt_const_params)] + +struct Foo<const A: [(); 0 + 0]> where [(); 0 + 0]: Sized; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs new file mode 100644 index 000000000..643126a46 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs @@ -0,0 +1,10 @@ +// aux-build:issue-94287-aux.rs +// build-fail + +extern crate issue_94287_aux; + +use std::str::FromStr; + +fn main() { + let _ = <issue_94287_aux::FixedI32<16>>::from_str(""); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr new file mode 100644 index 000000000..7390a0077 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr @@ -0,0 +1,15 @@ +error: failed to evaluate generic const expression + --> $DIR/auxiliary/issue-94287-aux.rs:15:8 + | +LL | If<{ FRAC <= 32 }>: True, + | ^^^^^^^^^^^^^^ + | + = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]` +help: consider enabling this feature + --> $DIR/issue-94287.rs:1:1 + | +LL | #![feature(generic_const_exprs)] + | + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94293.rs b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs new file mode 100644 index 000000000..713c5d89a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(const_evaluatable_unchecked)] + +pub struct If<const CONDITION: bool>; +pub trait True {} +impl True for If<true> {} + +pub struct FixedI8<const FRAC: u32> { + pub bits: i8, +} + +impl<const FRAC_LHS: u32, const FRAC_RHS: u32> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> +where + If<{ FRAC_RHS <= 8 }>: True, +{ + fn eq(&self, _rhs: &FixedI8<FRAC_RHS>) -> bool { + unimplemented!() + } +} + +impl<const FRAC: u32> PartialEq<i8> for FixedI8<FRAC> { + fn eq(&self, rhs: &i8) -> bool { + let rhs_as_fixed = FixedI8::<0> { bits: *rhs }; + PartialEq::eq(self, &rhs_as_fixed) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs new file mode 100644 index 000000000..67e30232e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub const fn new() -> Self { + Self { + changes: [0; CHANGES.len()], + } + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr new file mode 100644 index 000000000..1cceaece7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs new file mode 100644 index 000000000..00568a089 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub fn combine(&mut self, other: &Self) { + for _change in &self.changes {} + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr new file mode 100644 index 000000000..774e842bc --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99647.rs b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs new file mode 100644 index 000000000..f797beda8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99705.rs b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs new file mode 100644 index 000000000..75b57b621 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs @@ -0,0 +1,33 @@ +// check-pass +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +pub trait MyIterator { + type Output; +} + +pub trait Foo { + const ABC: usize; +} + +pub struct IteratorStruct<const N: usize>{ + +} + +pub struct Bar<const N: usize> { + pub data: [usize; N] +} + +impl<const N: usize> MyIterator for IteratorStruct<N> { + type Output = Bar<N>; +} + +pub fn test1<T: Foo>() -> impl MyIterator<Output = Bar<{T::ABC}>> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} + +pub trait Baz<const N: usize>{} +impl<const N: usize> Baz<N> for Bar<N> {} +pub fn test2<T: Foo>() -> impl MyIterator<Output = impl Baz<{ T::ABC }>> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} diff --git a/tests/ui/const-generics/generic_const_exprs/less_than.rs b/tests/ui/const-generics/generic_const_exprs/less_than.rs new file mode 100644 index 000000000..2e9af1bf4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/less_than.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized { + Foo +} + +fn main() { + let _: Foo<true> = test::<12>(); + let _: Foo<false> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.rs b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs new file mode 100644 index 000000000..cd5d76dd9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// We do not yet want to support let-bindings in abstract consts, +// so this test should keep failing for now. +fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + //~^ ERROR overly complex generic constant + //~| ERROR overly complex generic constant + Default::default() +} + +fn main() { + let x = test::<31>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr new file mode 100644 index 000000000..823a4f8a1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -0,0 +1,20 @@ +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:68 + | +LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:35 + | +LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs new file mode 100644 index 000000000..2bd3c801f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn complex_maths<T>(n : usize) -> usize { + 2 * n + 1 +} + +struct Example<T, const N: usize> { + a: [f32; N], + b: [f32; complex_maths::<T>(N)], + //~^ ERROR unconstrained + c: T, +} diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr new file mode 100644 index 000000000..7b41e39b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/needs_where_clause.rs:11:6 + | +LL | b: [f32; complex_maths::<T>(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs new file mode 100644 index 000000000..7e5022817 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn callee<const M2: usize>() -> usize +where + [u8; M2 + 1]: Sized, +{ + M2 +} + +fn caller<const N1: usize>() -> usize +where + [u8; N1 + 1]: Sized, + [u8; (N1 + 1) + 1]: Sized, +{ + callee::<{ N1 + 1 }>() +} + +fn main() { + assert_eq!(caller::<4>(), 5); +} + +// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs new file mode 100644 index 000000000..769e3ae68 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Generic<const K: u64>; + +struct ConstU64<const K: u64>; + +impl<const K: u64> Generic<K> +where + ConstU64<{ K - 1 }>: , +{ + fn foo(self) -> u64 { + K + } +} + +impl<const K: u64> Generic<K> +where + ConstU64<{ K - 1 }>: , + ConstU64<{ K + 1 }>: , + ConstU64<{ K + 1 - 1 }>: , +{ + fn bar(self) -> u64 { + let x: Generic<{ K + 1 }> = Generic; + x.foo() + } +} + +fn main() { + assert_eq!((Generic::<10>).bar(), 11); +} + +// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the +// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs new file mode 100644 index 000000000..316887e5e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs @@ -0,0 +1,34 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn zero_init<const N: usize>() -> Substs1<N> +where + [u8; N + 1]: , +{ + Substs1([0; N + 1]) +} +struct Substs1<const N: usize>([u8; N + 1]) +where + [(); N + 1]: ; + +fn substs2<const M: usize>() -> Substs1<{ M * 2 }> +where + [(); { M * 2 } + 1]: , +{ + zero_init::<{ M * 2 }>() +} + +fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }> +where + [(); (L - 1) * 2 + 1]: , +{ + substs2::<{ L - 1 }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 3]); +} + +// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the +// ``{ N + 1 }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs new file mode 100644 index 000000000..d45a6465b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs @@ -0,0 +1,29 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_parens, unused_braces)] + +fn zero_init<const N: usize>() -> Substs1<{ (N) }> +where + [u8; { (N) }]: , +{ + Substs1([0; { (N) }]) +} + +struct Substs1<const N: usize>([u8; { (N) }]) +where + [(); { (N) }]: ; + +fn substs2<const M: usize>() -> Substs1<{ (M) }> { + zero_init::<{ (M) }>() +} + +fn substs3<const L: usize>() -> Substs1<{ (L) }> { + substs2::<{ (L) }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 2]); +} + +// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the +// ``{ (N) }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/no_dependence.rs b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs new file mode 100644 index 000000000..db8dc6ed4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs @@ -0,0 +1,13 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn two_args<const N: usize, const M: usize>() -> [u8; M + 2] { + [0; M + 2] +} + +fn yay<const N: usize>() -> [u8; 4] { + two_args::<N, 2>() // no lint +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs new file mode 100644 index 000000000..9c5de0317 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs @@ -0,0 +1,29 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused)] + +const fn complex_maths(n : usize) -> usize { + 2 * n + 1 +} + +pub struct Example<const N: usize> { + a: [f32; N], + b: [f32; complex_maths(N)], + //~^ ERROR unconstrained generic +} + +impl<const N: usize> Example<N> { + pub fn new() -> Self { + Self { + a: [0.; N], + b: [0.; complex_maths(N)], + } + } +} + +impl Example<2> { + pub fn sum(&self) -> f32 { + self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>() + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr new file mode 100644 index 000000000..3e5c2f5ca --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/no_where_clause.rs:10:6 + | +LL | b: [f32; complex_maths(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs new file mode 100644 index 000000000..1254b4435 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs @@ -0,0 +1,16 @@ +// aux-build:anon_const_non_local.rs + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate anon_const_non_local; + +fn bar<const M: usize>() +where + [(); M + 1]:, +{ + let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::<M>(); + //~^ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr new file mode 100644 index 000000000..3926c830a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non_local_anon_const_diagnostics.rs:12:43 + | +LL | let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::<M>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `anon_const_non_local::::foo::{constant#0}` + | + = note: expected constant `2` + found constant `anon_const_non_local::::foo::{constant#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs new file mode 100644 index 000000000..b37b354ae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_braces)] + +#[rustfmt::skip] +fn foo<const N: usize>() { + bar::<{{{{{{ N }}}}}}>(); +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs new file mode 100644 index 000000000..24d333aba --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + + +const fn bar<T: ?Sized>() -> usize { 7 } + +trait Foo { + fn test(&self) -> [u8; bar::<Self>()]; +} + +impl Foo for () { + fn test(&self) -> [u8; bar::<Self>()] { + [0; bar::<Self>()] + } +} + +fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr new file mode 100644 index 000000000..4e1d71f15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-ret.rs:17:16 + | +LL | fn use_dyn(v: &dyn Foo) { + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-safety-err-ret.rs:8:23 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) -> [u8; bar::<Self>()]; + | ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type + = help: consider moving `test` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs new file mode 100644 index 000000000..42c1cc507 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(where_clauses_object_safety)] + + +const fn bar<T: ?Sized>() -> usize { 7 } + +trait Foo { + fn test(&self) where [u8; bar::<Self>()]: Sized; + //~^ ERROR the trait `Foo` cannot be made into an object + //~| WARN this was previously accepted by the compiler but is being phased out +} + +impl Foo for () { + fn test(&self) where [u8; bar::<Self>()]: Sized {} +} + +fn use_dyn(v: &dyn Foo) { + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr new file mode 100644 index 000000000..440cf457e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr @@ -0,0 +1,24 @@ +error: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | fn test(&self) where [u8; bar::<Self>()]: Sized; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443> +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) where [u8; bar::<Self>()]: Sized; + | ^^^^ ...because method `test` references the `Self` type in its `where` clause + = help: consider moving `test` to another trait +note: the lint level is defined here + --> $DIR/object-safety-err-where-bounds.rs:3:9 + | +LL | #![deny(where_clauses_object_safety)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs new file mode 100644 index 000000000..79e9834b5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + fn test(&self) -> [u8; N + 1]; +} + +impl<const N: usize> Foo<N> for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn(&()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr new file mode 100644 index 000000000..59e9fee1e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr @@ -0,0 +1,19 @@ +error[E0284]: type annotations needed + --> $DIR/object-safety-ok-infer-err.rs:19:5 + | +LL | use_dyn(&()); + | ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn` + | +note: required by a bound in `use_dyn` + --> $DIR/object-safety-ok-infer-err.rs:14:55 + | +LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + | ^^^^^ required by this bound in `use_dyn` +help: consider specifying the generic argument + | +LL | use_dyn::<N>(&()); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs new file mode 100644 index 000000000..f4c89f623 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + fn test(&self) -> [u8; N + 1]; +} + +impl<const N: usize> Foo<N> for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn::<3>(&()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs new file mode 100644 index 000000000..e7c8e4f66 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs @@ -0,0 +1,24 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait True {} + +struct Is<const V: bool>; + +impl True for Is<true> {} + +fn g<T>() +//~^ NOTE required by a bound in this +where + Is<{ std::mem::size_of::<T>() == 0 }>: True, + //~^ NOTE required by a bound in `g` + //~| NOTE required by this bound in `g` +{ +} + +fn main() { + g::<usize>(); + //~^ ERROR mismatched types + //~| NOTE expected `false`, found `true` + //~| NOTE expected constant `false` +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr new file mode 100644 index 000000000..a253ec676 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/obligation-cause.rs:20:5 + | +LL | g::<usize>(); + | ^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `g` + --> $DIR/obligation-cause.rs:13:44 + | +LL | fn g<T>() + | - required by a bound in this +... +LL | Is<{ std::mem::size_of::<T>() == 0 }>: True, + | ^^^^ required by this bound in `g` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.rs b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs new file mode 100644 index 000000000..cae54df4c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Arr<const N: usize> = [u8; N - 1]; +//~^ ERROR evaluation of `Arr::<0>::{constant#0}` failed + +fn test<const N: usize>() -> Arr<N> +where + [u8; N - 1]: Sized, + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed +{ + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr new file mode 100644 index 000000000..a25fa56b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:9:10 + | +LL | [u8; N - 1]: Sized, + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error[E0080]: evaluation of `Arr::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:4:33 + | +LL | type Arr<const N: usize> = [u8; N - 1]; + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs new file mode 100644 index 000000000..d6574a3aa --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn make_array<const M: usize>() -> [(); M + 1] { + [(); M + 1] +} + +fn foo<const N: usize>() -> [(); (N * 2) + 1] { + make_array::<{ N * 2 }>() +} + +fn main() { + assert_eq!(foo::<10>(), [(); 10 * 2 + 1]) +} + +// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const diff --git a/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs new file mode 100644 index 000000000..d058b3638 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs @@ -0,0 +1,14 @@ +// check-pass +// Test that we correctly substitute generic arguments for type aliases. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Alias<T, const N: usize> = [T; N + 1]; + +fn foo<const M: usize>() -> Alias<u32, M> where [u8; M + 1]: Sized { + [0; M + 1] +} + +fn main() { + foo::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 000000000..c0404d35b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -0,0 +1,35 @@ +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +#![allow(incomplete_features)] + +// test `N + N` unifies with explicit function calls for non-builtin-types +#[derive(PartialEq, Eq)] +struct Foo(u8); + +impl const std::ops::Add for Foo { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + self + } +} + +struct Evaluatable<const N: Foo>; + +fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) { + bar::<{ std::ops::Add::add(N, N) }>(); +} + +fn bar<const N: Foo>() {} + +// test that `N + N` unifies with explicit function calls for builin-types +struct Evaluatable2<const N: usize>; + +fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) { + bar2::<{ std::ops::Add::add(N, N) }>(); + //~^ error: unconstrained generic constant + // FIXME(generic_const_exprs) make this not an error +} + +fn bar2<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 000000000..d18c7916f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:28:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/unop.rs b/tests/ui/const-generics/generic_const_exprs/unop.rs new file mode 100644 index 000000000..c12fef083 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unop.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized { + Foo +} + +fn main() { + let _: Foo<false> = test::<12>(); + let _: Foo<true> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs new file mode 100644 index 000000000..9580f8a7f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs @@ -0,0 +1,6 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +struct Foo<const N: usize, const M: usize = { N + 1 }>; +struct Bar<const N: usize>(Foo<N, 3>); +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.rs b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs new file mode 100644 index 000000000..c1bf19e0f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs @@ -0,0 +1,25 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn add<const N: usize>() -> [u8; { N + 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn div<const N: usize>() -> [u8; { N / 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +const fn foo(n: usize) {} + +fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn main() { + add::<12>(); + div::<9>(); + fn_call::<14>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr new file mode 100644 index 000000000..265a3b9d2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -0,0 +1,29 @@ +error: overly complex generic constant + --> $DIR/unused_expr.rs:4:34 + | +LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:9:34 + | +LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:16:38 + | +LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] { + | ^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/ice-68875.rs b/tests/ui/const-generics/ice-68875.rs new file mode 100644 index 000000000..2ef7cfdbe --- /dev/null +++ b/tests/ui/const-generics/ice-68875.rs @@ -0,0 +1,11 @@ +// check-fail + +struct DataWrapper<'a> { + data: &'a [u8; Self::SIZE], //~ ERROR generic `Self` types are currently not permitted in anonymous constants +} + +impl DataWrapper<'_> { + const SIZE: usize = 14; +} + +pub fn main() {} diff --git a/tests/ui/const-generics/ice-68875.stderr b/tests/ui/const-generics/ice-68875.stderr new file mode 100644 index 000000000..1db62c57f --- /dev/null +++ b/tests/ui/const-generics/ice-68875.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/ice-68875.rs:4:20 + | +LL | data: &'a [u8; Self::SIZE], + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/ice-const-generic-function-return-ty.rs b/tests/ui/const-generics/ice-const-generic-function-return-ty.rs new file mode 100644 index 000000000..2bf628af8 --- /dev/null +++ b/tests/ui/const-generics/ice-const-generic-function-return-ty.rs @@ -0,0 +1,5 @@ +// #95163 +fn return_ty() -> impl Into<<() as Reexported; +//~^ ERROR expected one of `(`, `::`, `<`, or `>`, found `;` + +fn main() {} diff --git a/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr new file mode 100644 index 000000000..a72f5800a --- /dev/null +++ b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr @@ -0,0 +1,8 @@ +error: expected one of `(`, `::`, `<`, or `>`, found `;` + --> $DIR/ice-const-generic-function-return-ty.rs:2:46 + | +LL | fn return_ty() -> impl Into<<() as Reexported; + | ^ expected one of `(`, `::`, `<`, or `>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/impl-const-generic-struct.rs b/tests/ui/const-generics/impl-const-generic-struct.rs new file mode 100644 index 000000000..7eb2c6a51 --- /dev/null +++ b/tests/ui/const-generics/impl-const-generic-struct.rs @@ -0,0 +1,12 @@ +// run-pass +struct S<const X: u32>; + +impl<const X: u32> S<X> { + fn x() -> u32 { + X + } +} + +fn main() { + assert_eq!(S::<19>::x(), 19); +} diff --git a/tests/ui/const-generics/incorrect-number-of-const-args.rs b/tests/ui/const-generics/incorrect-number-of-const-args.rs new file mode 100644 index 000000000..8660cb2fb --- /dev/null +++ b/tests/ui/const-generics/incorrect-number-of-const-args.rs @@ -0,0 +1,11 @@ +fn foo<const X: usize, const Y: usize>() -> usize { + 0 +} + +fn main() { + foo::<0>(); + //~^ ERROR function takes 2 + + foo::<0, 0, 0>(); + //~^ ERROR function takes 2 +} diff --git a/tests/ui/const-generics/incorrect-number-of-const-args.stderr b/tests/ui/const-generics/incorrect-number-of-const-args.stderr new file mode 100644 index 000000000..a845454f7 --- /dev/null +++ b/tests/ui/const-generics/incorrect-number-of-const-args.stderr @@ -0,0 +1,35 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/incorrect-number-of-const-args.rs:6:5 + | +LL | foo::<0>(); + | ^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/incorrect-number-of-const-args.rs:1:4 + | +LL | fn foo<const X: usize, const Y: usize>() -> usize { + | ^^^ -------------- -------------- +help: add missing generic argument + | +LL | foo::<0, Y>(); + | +++ + +error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/incorrect-number-of-const-args.rs:9:5 + | +LL | foo::<0, 0, 0>(); + | ^^^ - help: remove this generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/incorrect-number-of-const-args.rs:1:4 + | +LL | fn foo<const X: usize, const Y: usize>() -> usize { + | ^^^ -------------- -------------- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/infer/cannot-infer-const-args.rs b/tests/ui/const-generics/infer/cannot-infer-const-args.rs new file mode 100644 index 000000000..f85a72910 --- /dev/null +++ b/tests/ui/const-generics/infer/cannot-infer-const-args.rs @@ -0,0 +1,7 @@ +fn foo<const X: usize>() -> usize { + 0 +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/cannot-infer-const-args.stderr b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr new file mode 100644 index 000000000..93e45a88a --- /dev/null +++ b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-const-args.rs:6:5 + | +LL | foo(); + | ^^^ cannot infer the value of the const parameter `X` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | foo::<X>(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/issue-77092.rs b/tests/ui/const-generics/infer/issue-77092.rs new file mode 100644 index 000000000..fcf7d3282 --- /dev/null +++ b/tests/ui/const-generics/infer/issue-77092.rs @@ -0,0 +1,14 @@ +use std::convert::TryInto; + +fn take_array_from_mut<T, const N: usize>(data: &mut [T], start: usize) -> &mut [T; N] { + (&mut data[start .. start + N]).try_into().unwrap() +} + +fn main() { + let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + + for i in 1 .. 4 { + println!("{:?}", take_array_from_mut(&mut arr, i)); + //~^ ERROR type annotations needed + } +} diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr new file mode 100644 index 000000000..1682b26ac --- /dev/null +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-77092.rs:11:26 + | +LL | println!("{:?}", take_array_from_mut(&mut arr, i)); + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` + | +help: consider specifying the generic arguments + | +LL | println!("{:?}", take_array_from_mut::<i32, N>(&mut arr, i)); + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/method-chain.rs b/tests/ui/const-generics/infer/method-chain.rs new file mode 100644 index 000000000..0c5eed489 --- /dev/null +++ b/tests/ui/const-generics/infer/method-chain.rs @@ -0,0 +1,16 @@ +struct Foo; + +impl Foo { + fn bar(self) -> Foo { + Foo + } + + fn baz<const N: usize>(self) -> Foo { + println!("baz: {}", N); + Foo + } +} + +fn main() { + Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/method-chain.stderr b/tests/ui/const-generics/infer/method-chain.stderr new file mode 100644 index 000000000..ff6da535b --- /dev/null +++ b/tests/ui/const-generics/infer/method-chain.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/method-chain.rs:15:33 + | +LL | Foo.bar().bar().bar().bar().baz(); + | ^^^ cannot infer the value of the const parameter `N` declared on the associated function `baz` + | +help: consider specifying the generic argument + | +LL | Foo.bar().bar().bar().bar().baz::<N>(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/one-param-uninferred.rs b/tests/ui/const-generics/infer/one-param-uninferred.rs new file mode 100644 index 000000000..d6018650f --- /dev/null +++ b/tests/ui/const-generics/infer/one-param-uninferred.rs @@ -0,0 +1,11 @@ +// Test that we emit an error if we cannot properly infer a constant. +fn foo<const N: usize, const M: usize>() -> [u8; N] { + todo!() +} + +fn main() { + // FIXME(const_generics): Currently this only suggests one const parameter, + // but instead it should suggest to provide all parameters. + let _: [u8; 17] = foo(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/one-param-uninferred.stderr b/tests/ui/const-generics/infer/one-param-uninferred.stderr new file mode 100644 index 000000000..cf70c2181 --- /dev/null +++ b/tests/ui/const-generics/infer/one-param-uninferred.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/one-param-uninferred.rs:9:23 + | +LL | let _: [u8; 17] = foo(); + | ^^^ cannot infer the value of the const parameter `M` declared on the function `foo` + | +help: consider specifying the generic arguments + | +LL | let _: [u8; 17] = foo::<17, M>(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/uninferred-consts.rs b/tests/ui/const-generics/infer/uninferred-consts.rs new file mode 100644 index 000000000..657f4b513 --- /dev/null +++ b/tests/ui/const-generics/infer/uninferred-consts.rs @@ -0,0 +1,11 @@ +// Test that we emit an error if we cannot properly infer a constant. + +// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893 +struct Foo; +impl Foo { + fn foo<const A: usize, const B: usize>(self) {} +} +fn main() { + Foo.foo(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/uninferred-consts.stderr b/tests/ui/const-generics/infer/uninferred-consts.stderr new file mode 100644 index 000000000..3980ecea8 --- /dev/null +++ b/tests/ui/const-generics/infer/uninferred-consts.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/uninferred-consts.rs:9:9 + | +LL | Foo.foo(); + | ^^^ cannot infer the value of the const parameter `A` declared on the associated function `foo` + | +help: consider specifying the generic arguments + | +LL | Foo.foo::<A, B>(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer_arg_from_pat.rs b/tests/ui/const-generics/infer_arg_from_pat.rs new file mode 100644 index 000000000..10317a1b9 --- /dev/null +++ b/tests/ui/const-generics/infer_arg_from_pat.rs @@ -0,0 +1,25 @@ +// run-pass +// +// see issue #70529 + +struct A<const N: usize> { + arr: [u8; N], +} + +impl<const N: usize> A<N> { + fn new() -> Self { + A { + arr: [0; N], + } + } + + fn value(&self) -> usize { + N + } +} + +fn main() { + let a = A::new(); + let [_, _] = a.arr; + assert_eq!(a.value(), 2); +} diff --git a/tests/ui/const-generics/infer_arr_len_from_pat.rs b/tests/ui/const-generics/infer_arr_len_from_pat.rs new file mode 100644 index 000000000..40f6f5b8d --- /dev/null +++ b/tests/ui/const-generics/infer_arr_len_from_pat.rs @@ -0,0 +1,11 @@ +// check-pass +// +// see issue #70529 + +fn as_chunks<const N: usize>() -> [u8; N] { + loop {} +} + +fn main() { + let [_, _] = as_chunks(); +} diff --git a/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs b/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs new file mode 100644 index 000000000..b385406b0 --- /dev/null +++ b/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs @@ -0,0 +1,28 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the inhabited check doesn't cause +// ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. + +trait Foo { + const ASSOC: usize = 1; +} + +#[allow(unused_tuple_struct_fields)] +struct Iced<T: Foo>(T, [(); T::ASSOC]) +where + [(); T::ASSOC]: ; + +impl Foo for u32 {} + +fn foo<T: Foo>() +where + [(); T::ASSOC]: , +{ + let _iced: Iced<T> = return; +} + +fn main() { + foo::<u32>(); +} diff --git a/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs b/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs new file mode 100644 index 000000000..216d29c7c --- /dev/null +++ b/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the inhabited check doesn't cause +// ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. + +trait Foo { + const ASSOC: usize = 1; +} + +#[allow(unused_tuple_struct_fields)] +struct Iced<T: Foo>(T, [(); T::ASSOC]) +where + [(); T::ASSOC]: ; + +impl Foo for u32 {} + +fn main() { + let _iced: Iced<u32> = return; +} diff --git a/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs new file mode 100644 index 000000000..2b8731ba7 --- /dev/null +++ b/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -0,0 +1,18 @@ +// check-pass + +fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) { + f([1, 2, 3]); +} + +fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) { + f([1, 2, 3]); +} + +fn returns_closure_of_array_3() -> impl Fn([i32; 3]) { + |_| {} +} + +fn main() { + takes_closure_of_array_3(returns_closure_of_array_3()); + takes_closure_of_array_3_apit(returns_closure_of_array_3()); +} diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr new file mode 100644 index 000000000..b8a1027c9 --- /dev/null +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/intrinsics-type_name-as-const-argument.rs:15:44 + | +LL | T: Trait<{std::intrinsics::type_name::<T>()}> + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22 + | +LL | trait Trait<const S: &'static str> {} + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs new file mode 100644 index 000000000..147a00cb2 --- /dev/null +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs @@ -0,0 +1,21 @@ +// [full] check-pass +// revisions: full min + +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(adt_const_params, generic_const_exprs))] + +#![feature(core_intrinsics)] +#![feature(const_type_name)] + +trait Trait<const S: &'static str> {} +//[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + +struct Bug<T> +where + T: Trait<{std::intrinsics::type_name::<T>()}> + //[min]~^ ERROR generic parameters may not be used in const operations +{ + t: T +} + +fn main() {} diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.rs b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs new file mode 100644 index 000000000..7d4dc98f3 --- /dev/null +++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs @@ -0,0 +1,14 @@ +use std::convert::TryInto; + +struct S; + +fn main() { + let _: u32 = 5i32.try_into::<32>().unwrap(); + //~^ ERROR this associated function takes + + S.f::<0>(); + //~^ ERROR no method named `f` + + S::<0>; + //~^ ERROR this struct takes 0 +} diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr new file mode 100644 index 000000000..8c76ca690 --- /dev/null +++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -0,0 +1,43 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/invalid-const-arg-for-type-param.rs:6:23 + | +LL | let _: u32 = 5i32.try_into::<32>().unwrap(); + | ^^^^^^^^ expected 0 generic arguments + | +help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument + | +LL | let _: u32 = TryInto::<32>::try_into(5i32).unwrap(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: remove these generics + | +LL - let _: u32 = 5i32.try_into::<32>().unwrap(); +LL + let _: u32 = 5i32.try_into().unwrap(); + | + +error[E0599]: no method named `f` found for struct `S` in the current scope + --> $DIR/invalid-const-arg-for-type-param.rs:9:7 + | +LL | struct S; + | -------- method `f` not found for this struct +... +LL | S.f::<0>(); + | ^ method not found in `S` + +error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/invalid-const-arg-for-type-param.rs:12:5 + | +LL | S::<0>; + | ^----- help: remove these generics + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/invalid-const-arg-for-type-param.rs:3:8 + | +LL | struct S; + | ^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0599. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/invalid-constant-in-args.rs b/tests/ui/const-generics/invalid-constant-in-args.rs new file mode 100644 index 000000000..7419d4a25 --- /dev/null +++ b/tests/ui/const-generics/invalid-constant-in-args.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +fn main() { + let _: Cell<&str, "a"> = Cell::new(""); + //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied +} diff --git a/tests/ui/const-generics/invalid-constant-in-args.stderr b/tests/ui/const-generics/invalid-constant-in-args.stderr new file mode 100644 index 000000000..993b63518 --- /dev/null +++ b/tests/ui/const-generics/invalid-constant-in-args.stderr @@ -0,0 +1,11 @@ +error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/invalid-constant-in-args.rs:4:12 + | +LL | let _: Cell<&str, "a"> = Cell::new(""); + | ^^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/invalid-enum.rs b/tests/ui/const-generics/invalid-enum.rs new file mode 100644 index 000000000..cb6d05349 --- /dev/null +++ b/tests/ui/const-generics/invalid-enum.rs @@ -0,0 +1,35 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +enum CompileFlag { + A, + B, +} + +pub fn test_1<const CF: CompileFlag>() {} +pub fn test_2<T, const CF: CompileFlag>(x: T) {} +pub struct Example<const CF: CompileFlag, T=u32>{ + x: T, +} + +impl<const CF: CompileFlag, T> Example<CF, T> { + const ASSOC_FLAG: CompileFlag = CompileFlag::A; +} + +pub fn main() { + test_1::<CompileFlag::A>(); + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + test_2::<_, CompileFlag::A>(0); + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + let _: Example<CompileFlag::A, _> = Example { x: 0 }; + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 }; + //~^ ERROR: type provided when a constant was expected +} diff --git a/tests/ui/const-generics/invalid-enum.stderr b/tests/ui/const-generics/invalid-enum.stderr new file mode 100644 index 000000000..0d3643f6f --- /dev/null +++ b/tests/ui/const-generics/invalid-enum.stderr @@ -0,0 +1,75 @@ +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:21:12 + | +LL | test_1::<CompileFlag::A>(); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:25:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:29:18 + | +LL | let _: Example<CompileFlag::A, _> = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:29:18 + | +LL | let _: Example<CompileFlag::A, _> = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; + | + + + +error[E0747]: type provided when a constant was expected + --> $DIR/invalid-enum.rs:33:18 + | +LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; + | + + + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:21:12 + | +LL | test_1::<CompileFlag::A>(); + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | test_1::<{ CompileFlag::A }>(); + | + + + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:25:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | test_2::<_, { CompileFlag::A }>(0); + | + + + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0573, E0747. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/invariant.rs b/tests/ui/const-generics/invariant.rs new file mode 100644 index 000000000..39d658be6 --- /dev/null +++ b/tests/ui/const-generics/invariant.rs @@ -0,0 +1,34 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::marker::PhantomData; + +trait SadBee { + const ASSOC: usize; +} +// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while +// we allow two different impls for these types, leading +// to different const eval results. +impl SadBee for for<'a> fn(&'a ()) { + const ASSOC: usize = 0; +} +impl SadBee for fn(&'static ()) { + //~^ WARNING conflicting implementations of trait + //~| WARNING this was previously accepted + const ASSOC: usize = 100; +} + +struct Foo<T: SadBee>([u8; <T as SadBee>::ASSOC], PhantomData<T>) +where + [(); <T as SadBee>::ASSOC]: ; + +fn covariant( + v: &'static Foo<for<'a> fn(&'a ())> +) -> &'static Foo<fn(&'static ())> { + v + //~^ ERROR mismatched types +} + +fn main() { + let y = covariant(&Foo([], PhantomData)); + println!("{:?}", y.0); +} diff --git a/tests/ui/const-generics/invariant.stderr b/tests/ui/const-generics/invariant.stderr new file mode 100644 index 000000000..aabe4c93b --- /dev/null +++ b/tests/ui/const-generics/invariant.stderr @@ -0,0 +1,26 @@ +warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())` + --> $DIR/invariant.rs:14:1 + | +LL | impl SadBee for for<'a> fn(&'a ()) { + | ---------------------------------- first implementation here +... +LL | impl SadBee for fn(&'static ()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105> + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + = note: `#[warn(coherence_leak_check)]` on by default + +error[E0308]: mismatched types + --> $DIR/invariant.rs:27:5 + | +LL | v + | ^ one type is more general than the other + | + = note: expected reference `&Foo<fn(&())>` + found reference `&Foo<for<'a> fn(&'a ())>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-102124.rs b/tests/ui/const-generics/issue-102124.rs new file mode 100644 index 000000000..a28f198e9 --- /dev/null +++ b/tests/ui/const-generics/issue-102124.rs @@ -0,0 +1,20 @@ +// run-pass +// compile-flags: -Zmir-opt-level=3 + +// regression test for #102124 + +const L: usize = 4; + +pub trait Print<const N: usize> { + fn print(&self) -> usize { + N + } +} + +pub struct Printer; +impl Print<L> for Printer {} + +fn main() { + let p = Printer; + assert_eq!(p.print(), 4); +} diff --git a/tests/ui/const-generics/issue-105689.rs b/tests/ui/const-generics/issue-105689.rs new file mode 100644 index 000000000..4237b3cad --- /dev/null +++ b/tests/ui/const-generics/issue-105689.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2021 +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs b/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs new file mode 100644 index 000000000..8363e5af4 --- /dev/null +++ b/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[derive(Clone)] +struct Bar<const A: usize, const B: usize> +where + [(); A as usize]:, + [(); B as usize]:, +{} + +fn main() {} diff --git a/tests/ui/const-generics/issue-46511.rs b/tests/ui/const-generics/issue-46511.rs new file mode 100644 index 000000000..71c50e2f3 --- /dev/null +++ b/tests/ui/const-generics/issue-46511.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo<'a> //~ ERROR parameter `'a` is never used [E0392] +{ + _a: [u8; std::mem::size_of::<&'a mut u8>()] //~ ERROR a non-static lifetime is not allowed in a `const` +} + +pub fn main() {} diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr new file mode 100644 index 000000000..b21afa56d --- /dev/null +++ b/tests/ui/const-generics/issue-46511.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-46511.rs:5:35 + | +LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0392]: parameter `'a` is never used + --> $DIR/issue-46511.rs:3:12 + | +LL | struct Foo<'a> + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0658. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issue-66451.rs b/tests/ui/const-generics/issue-66451.rs new file mode 100644 index 000000000..3335f7d59 --- /dev/null +++ b/tests/ui/const-generics/issue-66451.rs @@ -0,0 +1,28 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(Debug, PartialEq, Eq)] +struct Foo { + value: i32, + nested: &'static Bar<i32>, +} + +#[derive(Debug, PartialEq, Eq)] +struct Bar<T>(T); + +struct Test<const F: Foo>; + +fn main() { + let x: Test<{ + Foo { + value: 3, + nested: &Bar(4), + } + }> = Test; + let y: Test<{ + Foo { + value: 3, + nested: &Bar(5), + } + }> = x; //~ ERROR mismatched types +} diff --git a/tests/ui/const-generics/issue-66451.stderr b/tests/ui/const-generics/issue-66451.stderr new file mode 100644 index 000000000..e0cb0b661 --- /dev/null +++ b/tests/ui/const-generics/issue-66451.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-66451.rs:27:10 + | +LL | let y: Test<{ + | ____________- +LL | | Foo { +LL | | value: 3, +LL | | nested: &Bar(5), +LL | | } +LL | | }> = x; + | | - ^ expected `Foo { value: 3, nested: &Bar::<i32>(5) }`, found `Foo { value: 3, nested: &Bar::<i32>(4) }` + | |______| + | expected due to this + | + = note: expected struct `Test<Foo { value: 3, nested: &Bar::<i32>(5) }>` + found struct `Test<Foo { value: 3, nested: &Bar::<i32>(4) }>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-70408.rs b/tests/ui/const-generics/issue-70408.rs new file mode 100644 index 000000000..f7557cb49 --- /dev/null +++ b/tests/ui/const-generics/issue-70408.rs @@ -0,0 +1,13 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::<{ &[0x41, 0x41, 0x41, 0x41] }>(), b"AAAA"); +} diff --git a/tests/ui/const-generics/issue-80471.rs b/tests/ui/const-generics/issue-80471.rs new file mode 100644 index 000000000..d0af8a5ea --- /dev/null +++ b/tests/ui/const-generics/issue-80471.rs @@ -0,0 +1,13 @@ +#![feature(adt_const_params)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +#[derive(PartialEq, Eq)] +enum Nat { + Z, + S(Box<Nat>), +} + +fn foo<const N: Nat>() {} +//~^ ERROR `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + +fn main() {} diff --git a/tests/ui/const-generics/issue-80471.stderr b/tests/ui/const-generics/issue-80471.stderr new file mode 100644 index 000000000..b89706710 --- /dev/null +++ b/tests/ui/const-generics/issue-80471.stderr @@ -0,0 +1,18 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-80471.rs:1:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0741]: `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-80471.rs:10:17 + | +LL | fn foo<const N: Nat>() {} + | ^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issue-93647.rs b/tests/ui/const-generics/issue-93647.rs new file mode 100644 index 000000000..806540e17 --- /dev/null +++ b/tests/ui/const-generics/issue-93647.rs @@ -0,0 +1,6 @@ +struct X<const N: usize = { + (||1usize)() + //~^ ERROR cannot call non-const closure +}>; + +fn main() {} diff --git a/tests/ui/const-generics/issue-93647.stderr b/tests/ui/const-generics/issue-93647.stderr new file mode 100644 index 000000000..18370eea5 --- /dev/null +++ b/tests/ui/const-generics/issue-93647.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-93647.rs:2:5 + | +LL | (||1usize)() + | ^^^^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/issue-97007.rs b/tests/ui/const-generics/issue-97007.rs new file mode 100644 index 000000000..7036834c4 --- /dev/null +++ b/tests/ui/const-generics/issue-97007.rs @@ -0,0 +1,88 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +mod lib { + const N_ISLANDS: usize = 4; + const N_BRIDGES: usize = 7; + const BRIDGES: [(usize, usize); 7] = [(0, 1), (0, 1), (0, 2), (0, 3), (0, 3), (1, 2), (2, 3)]; + + pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS]; + + const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS]; + + const fn build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix { + matrix[to][from] += 1; + matrix[from][to] += 1; + matrix + } + + pub const fn walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix { + matrix[from][to] -= 1; + matrix[to][from] -= 1; + matrix + } + + const fn to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix { + let matrix = EMPTY_MATRIX; + + let matrix = build(matrix, bridges[0]); + let matrix = build(matrix, bridges[1]); + let matrix = build(matrix, bridges[2]); + let matrix = build(matrix, bridges[3]); + let matrix = build(matrix, bridges[4]); + let matrix = build(matrix, bridges[5]); + let matrix = build(matrix, bridges[6]); + + matrix + } + + const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(BRIDGES); + + pub struct Walk<const CURRENT: usize, const REMAINING: Matrix> { + _p: (), + } + + impl Walk<0, BRIDGE_MATRIX> { + pub const fn new() -> Self { + Self { _p: () } + } + } + + impl<const CURRENT: usize, const REMAINING: Matrix> Walk<CURRENT, REMAINING> { + pub fn proceed_to<const NEXT: usize>( + self, + ) -> Walk<NEXT, { walk(REMAINING, CURRENT, NEXT) }> { + Walk { _p: () } + } + } + + pub struct Trophy { + _p: (), + } + + impl<const CURRENT: usize> Walk<CURRENT, EMPTY_MATRIX> { + pub fn collect_prize(self) -> Trophy { + Trophy { _p: () } + } + } +} + +pub use lib::{Trophy, Walk}; + +fn main() { + // Example, taking the first step + let _ = Walk::new().proceed_to::<1>(); + + // Don't be so eager to collect the trophy + // let trophy = Walk::new() + // .proceed_to::<1>() + // .proceed_to::<0>() + // .collect_prize(); + + // Can't just make a Trophy out of thin air, you must earn it + // let trophy: Trophy = Trophy { _p: () }; + + // Can you collect the Trophy? +} diff --git a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs new file mode 100644 index 000000000..6a10ee267 --- /dev/null +++ b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// All of these three items must be in `lib2` to reproduce the error + +pub trait TypeFn { + type Output; +} + +pub struct GenericType<const B: i8>; + +// Removing the braces around `42` resolves the crash +impl TypeFn for GenericType<{ 40 + 2 }> { + type Output = (); +} diff --git a/tests/ui/const-generics/issues/auxiliary/impl-const.rs b/tests/ui/const-generics/issues/auxiliary/impl-const.rs new file mode 100644 index 000000000..de3a40860 --- /dev/null +++ b/tests/ui/const-generics/issues/auxiliary/impl-const.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] + +pub struct Num<const N: usize>; + +// Braces around const expression causes crash +impl Num<{5}> { + pub fn five(&self) { + } +} diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs new file mode 100644 index 000000000..4e9d3626a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -0,0 +1,21 @@ +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(adt_const_params)] + +struct T<const B: &'static bool>; + +impl <const B: &'static bool> T<B> { + const fn set_false(&self) { + unsafe { + *(B as *const bool as *mut bool) = false; + //~^ ERROR evaluation of constant value failed [E0080] + } + } +} + +const _: () = { + let x = T::<{&true}>; + x.set_false(); +}; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr new file mode 100644 index 000000000..d4b486376 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -0,0 +1,20 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only + | +note: inside `T::<&true>::set_false` + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `_` + --> $DIR/issue-100313.rs:18:5 + | +LL | x.set_false(); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/issues/issue-105037.rs b/tests/ui/const-generics/issues/issue-105037.rs new file mode 100644 index 000000000..f7d239499 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-105037.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![allow(dead_code)] + +trait Table<const D: usize>: Sync { + const COLUMNS: usize; +} + +struct Table1<const D: usize>; +impl<const D: usize> Table<D> for Table1<D> { + const COLUMNS: usize = 123; +} + +struct Table2<const D: usize>; +impl<const D: usize> Table<D> for Table2<D> { + const COLUMNS: usize = 456; +} + +fn process_table<T: Table<D>, const D: usize>(_table: T) +where + [(); T::COLUMNS]:, +{ +} + +fn process_all_tables<const D: usize>() +where + [(); Table2::<D>::COLUMNS]:, + [(); Table1::<D>::COLUMNS]:, +{ + process_table(Table1::<D>); + process_table(Table2::<D>); +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-1.full.stderr b/tests/ui/const-generics/issues/issue-56445-1.full.stderr new file mode 100644 index 000000000..179643a75 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.full.stderr @@ -0,0 +1,11 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/issue-56445-1.rs:9:26 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^ + | + = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr new file mode 100644 index 000000000..43a5df117 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr @@ -0,0 +1,20 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/issue-56445-1.rs:9:26 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^ + | + = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052> + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-56445-1.rs:9:25 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.rs b/tests/ui/const-generics/issues/issue-56445-1.rs new file mode 100644 index 000000000..13eb2ea9f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.rs @@ -0,0 +1,13 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995. +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] +#![crate_type = "lib"] + +use std::marker::PhantomData; + +struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); +//~^ ERROR: use of non-static lifetime `'a` in const generic +//[min]~| ERROR: `&'static str` is forbidden as the type of a const generic parameter + +impl Bug<'_, ""> {} diff --git a/tests/ui/const-generics/issues/issue-56445-2.rs b/tests/ui/const-generics/issues/issue-56445-2.rs new file mode 100644 index 000000000..e078c8487 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-2.rs @@ -0,0 +1,11 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-502095133 +struct OnDiskDirEntry<'a> { _s: &'a usize } + +impl<'a> OnDiskDirEntry<'a> { + const LFN_FRAGMENT_LEN: usize = 2; + + fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-2.stderr b/tests/ui/const-generics/issues/issue-56445-2.stderr new file mode 100644 index 000000000..770c80cbb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-2.rs:7:38 + | +LL | fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-56445-2.rs:4:10 + | +LL | impl<'a> OnDiskDirEntry<'a> { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-56445-3.rs b/tests/ui/const-generics/issues/issue-56445-3.rs new file mode 100644 index 000000000..c29df1458 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-3.rs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-524494170 +pub struct Memory<'rom> { + rom: &'rom [u8], + ram: [u8; Self::SIZE], + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +impl<'rom> Memory<'rom> { + pub const SIZE: usize = 0x8000; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-3.stderr b/tests/ui/const-generics/issues/issue-56445-3.stderr new file mode 100644 index 000000000..f1c49eecf --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-3.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-3.rs:4:15 + | +LL | ram: [u8; Self::SIZE], + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs b/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs new file mode 100644 index 000000000..0066490df --- /dev/null +++ b/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs @@ -0,0 +1,7 @@ +// check-pass + +struct Generic<const V: usize>; + +fn main() { + let _ = Generic::<0>; +} diff --git a/tests/ui/const-generics/issues/issue-61336-1.rs b/tests/ui/const-generics/issues/issue-61336-1.rs new file mode 100644 index 000000000..beb37e63b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-1.rs @@ -0,0 +1,9 @@ +// build-pass +fn f<T: Copy, const N: usize>(x: T) -> [T; N] { + [x; N] +} + +fn main() { + let x: [u32; 5] = f::<u32, 5>(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336-2.rs b/tests/ui/const-generics/issues/issue-61336-2.rs new file mode 100644 index 000000000..b7cd29f89 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-2.rs @@ -0,0 +1,13 @@ +fn f<T: Copy, const N: usize>(x: T) -> [T; N] { + [x; { N }] +} + +fn g<T, const N: usize>(x: T) -> [T; N] { + [x; { N }] + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let x: [u32; 5] = f::<u32, 5>(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr new file mode 100644 index 000000000..5bb356696 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-61336-2.rs:6:6 + | +LL | [x; { N }] + | ^ the trait `Copy` is not implemented for `T` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider restricting type parameter `T` + | +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-61336.rs b/tests/ui/const-generics/issues/issue-61336.rs new file mode 100644 index 000000000..80be1d8e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336.rs @@ -0,0 +1,13 @@ +fn f<T: Copy, const N: usize>(x: T) -> [T; N] { + [x; N] +} + +fn g<T, const N: usize>(x: T) -> [T; N] { + [x; N] + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let x: [u32; 5] = f::<u32, 5>(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr new file mode 100644 index 000000000..8d9e545b4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-61336.rs:6:6 + | +LL | [x; N] + | ^ the trait `Copy` is not implemented for `T` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider restricting type parameter `T` + | +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-61422.rs b/tests/ui/const-generics/issues/issue-61422.rs new file mode 100644 index 000000000..0b9cf40d8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61422.rs @@ -0,0 +1,24 @@ +// check-pass +use std::mem; + +// Neither of the uninits below are currently accepted as not UB, however, +// this code does not run and is merely checking that we do not ICE on this pattern, +// so this is fine. + +fn foo<const SIZE: usize>() { + let arr: [u8; SIZE] = unsafe { + #[allow(deprecated)] + let array: [u8; SIZE] = mem::uninitialized(); + array + }; +} + +fn bar<const SIZE: usize>() { + let arr: [u8; SIZE] = unsafe { + let array: [u8; SIZE] = mem::MaybeUninit::uninit().assume_init(); + array + }; +} + + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-61432.rs b/tests/ui/const-generics/issues/issue-61432.rs new file mode 100644 index 000000000..6192af82a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61432.rs @@ -0,0 +1,9 @@ +// run-pass + +fn promote<const N: i32>() { + let _ = &N; +} + +fn main() { + promote::<0>(); +} diff --git a/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs new file mode 100644 index 000000000..fa76aeae9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -0,0 +1,12 @@ +// run-pass +pub trait BitLen: Sized { + const BIT_LEN: usize; +} + +impl<const L: usize> BitLen for [u8; L] { + const BIT_LEN: usize = 8 * L; +} + +fn main() { + let _foo = <[u8; 2]>::BIT_LEN; +} diff --git a/tests/ui/const-generics/issues/issue-62878.full.stderr b/tests/ui/const-generics/issues/issue-62878.full.stderr new file mode 100644 index 000000000..3a2b291d7 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.full.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:5:38 + | +LL | fn foo<const N: usize, const A: [u8; N]>() {} + | ^ the type must not depend on the parameter `N` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr new file mode 100644 index 000000000..5a721720d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -0,0 +1,18 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:5:38 + | +LL | fn foo<const N: usize, const A: [u8; N]>() {} + | ^ the type must not depend on the parameter `N` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/issue-62878.rs:5:33 + | +LL | fn foo<const N: usize, const A: [u8; N]>() {} + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-62878.rs b/tests/ui/const-generics/issues/issue-62878.rs new file mode 100644 index 000000000..4c08a484e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params, generic_arg_infer))] +#![cfg_attr(full, allow(incomplete_features))] + +fn foo<const N: usize, const A: [u8; N]>() {} +//~^ ERROR the type of const parameters must not +//[min]~| ERROR `[u8; N]` is forbidden as the type of a const generic parameter + +fn main() { + foo::<_, { [1] }>(); +} diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr new file mode 100644 index 000000000..16fabd1e8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: `(dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-63322-forbid-dyn.rs:9:18 + | +LL | fn test<const T: &'static dyn A>() { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr new file mode 100644 index 000000000..9f6c7ccf3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -0,0 +1,11 @@ +error: `&'static (dyn A + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/issue-63322-forbid-dyn.rs:9:18 + | +LL | fn test<const T: &'static dyn A>() { + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs new file mode 100644 index 000000000..116c3fcfb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs @@ -0,0 +1,17 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +trait A {} +struct B; +impl A for B {} + +fn test<const T: &'static dyn A>() { + //[full]~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used + //[min]~^^ ERROR `&'static (dyn A + 'static)` is forbidden + unimplemented!() +} + +fn main() { + test::<{ &B }>(); +} diff --git a/tests/ui/const-generics/issues/issue-64519.rs b/tests/ui/const-generics/issues/issue-64519.rs new file mode 100644 index 000000000..969289b26 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-64519.rs @@ -0,0 +1,17 @@ +// check-pass +struct Foo<const D: usize> { + state: Option<[u8; D]>, +} + +impl<const D: usize> Iterator for Foo<{D}> { + type Item = [u8; D]; + fn next(&mut self) -> Option<Self::Item> { + if true { + return Some(self.state.unwrap().clone()); + } else { + return Some(self.state.unwrap().clone()); + } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs new file mode 100644 index 000000000..091419f0c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs @@ -0,0 +1,16 @@ +// check-pass +#![feature(adt_const_params)] +#![allow(incomplete_features)] + + +trait Trait<const NAME: &'static str> { + type Assoc; +} + +impl Trait<"0"> for () { + type Assoc = (); +} + +fn main() { + let _: <() as Trait<"0">>::Assoc = (); +} diff --git a/tests/ui/const-generics/issues/issue-66906.rs b/tests/ui/const-generics/issues/issue-66906.rs new file mode 100644 index 000000000..a0b3f9122 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-66906.rs @@ -0,0 +1,9 @@ +// check-pass + +pub struct Tuple; + +pub trait Trait<const I: usize> { + type Input: From<<Self as Trait<I>>::Input>; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67185-1.rs b/tests/ui/const-generics/issues/issue-67185-1.rs new file mode 100644 index 000000000..69425b25e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-1.rs @@ -0,0 +1,29 @@ +// check-pass + +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 3] {} +impl Bar for [[u16; 3]; 2] {} + +trait Foo + where + [<u8 as Baz>::Quaks; 2]: Bar, + <u8 as Baz>::Quaks: Bar, +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} + +fn f(_: impl Foo) {} + +fn main() { + f(FooImpl) +} diff --git a/tests/ui/const-generics/issues/issue-67185-2.rs b/tests/ui/const-generics/issues/issue-67185-2.rs new file mode 100644 index 000000000..18bb6f6bc --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-2.rs @@ -0,0 +1,31 @@ +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 4] {} +impl Bar for [[u16; 3]; 3] {} + +trait Foo +where + [<u8 as Baz>::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + <u8 as Baz>::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + +fn f(_: impl Foo) {} +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + +fn main() { + f(FooImpl) +} diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr new file mode 100644 index 000000000..c7be8e14a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -0,0 +1,99 @@ +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:15:5 + | +LL | <u8 as Baz>::Quaks: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:14:5 + | +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:21:6 + | +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:15:25 + | +LL | trait Foo + | --- required by a bound in this +... +LL | <u8 as Baz>::Quaks: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:21:6 + | +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:14:30 + | +LL | trait Foo + | --- required by a bound in this +LL | where +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:25:14 + | +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:14:30 + | +LL | trait Foo + | --- required by a bound in this +LL | where +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:25:14 + | +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:15:25 + | +LL | trait Foo + | --- required by a bound in this +... +LL | <u8 as Baz>::Quaks: Bar, + | ^^^ required by this bound in `Foo` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-67375.full.stderr b/tests/ui/const-generics/issues/issue-67375.full.stderr new file mode 100644 index 000000000..0cf69879a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.full.stderr @@ -0,0 +1,12 @@ +error: overly complex generic constant + --> $DIR/issue-67375.rs:7:17 + | +LL | inner: [(); { [|_: &T| {}; 0].len() }], + | ^^---------------------^^ + | | + | pointer casts are not allowed in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr new file mode 100644 index 000000000..5256d96c8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67375.rs:7:25 + | +LL | inner: [(); { [|_: &T| {}; 0].len() }], + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `T` is never used + --> $DIR/issue-67375.rs:5:12 + | +LL | struct Bug<T> { + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67375.rs b/tests/ui/const-generics/issues/issue-67375.rs new file mode 100644 index 000000000..8b4b276ba --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.rs @@ -0,0 +1,12 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +struct Bug<T> { + //[min]~^ ERROR parameter `T` is never used + inner: [(); { [|_: &T| {}; 0].len() }], + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR overly complex generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67739.full.stderr b/tests/ui/const-generics/issues/issue-67739.full.stderr new file mode 100644 index 000000000..f1a426c3c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.full.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-67739.rs:11:15 + | +LL | [0u8; mem::size_of::<Self::Associated>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); mem::size_of::<Self::Associated>()]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67739.min.stderr b/tests/ui/const-generics/issues/issue-67739.min.stderr new file mode 100644 index 000000000..dcbe5b94a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.min.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-67739.rs:11:15 + | +LL | [0u8; mem::size_of::<Self::Associated>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67739.rs b/tests/ui/const-generics/issues/issue-67739.rs new file mode 100644 index 000000000..de0eb7f50 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.rs @@ -0,0 +1,18 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::mem; + +pub trait Trait { + type Associated: Sized; + + fn associated_size(&self) -> usize { + [0u8; mem::size_of::<Self::Associated>()]; + //[min]~^ ERROR constant expression depends on a generic parameter + //[full]~^^ ERROR unconstrained generic constant + 0 + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr new file mode 100644 index 000000000..8e18fcdff --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-67945-1.rs:10:20 + | +LL | struct Bug<S> { + | - this type parameter +... +LL | let x: S = MaybeUninit::uninit(); + | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit` + | | + | expected due to this + | + = note: expected type parameter `S` + found union `MaybeUninit<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr new file mode 100644 index 000000000..eee04eb75 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -0,0 +1,30 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:10:16 + | +LL | let x: S = MaybeUninit::uninit(); + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:13:45 + | +LL | let b = &*(&x as *const _ as *const S); + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-1.rs:7:12 + | +LL | struct Bug<S> { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-1.rs b/tests/ui/const-generics/issues/issue-67945-1.rs new file mode 100644 index 000000000..99f88bc8e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.rs @@ -0,0 +1,19 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +use std::mem::MaybeUninit; + +struct Bug<S> { + //[min]~^ ERROR parameter `S` is never used + A: [(); { + let x: S = MaybeUninit::uninit(); + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR mismatched types + let b = &*(&x as *const _ as *const S); + //[min]~^ ERROR generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr new file mode 100644 index 000000000..47429b761 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr @@ -0,0 +1,17 @@ +error: overly complex generic constant + --> $DIR/issue-67945-2.rs:7:13 + | +LL | A: [(); { + | _____________^ +LL | | +LL | | let x: Option<Box<Self>> = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-2.min.stderr b/tests/ui/const-generics/issues/issue-67945-2.min.stderr new file mode 100644 index 000000000..6e07af1e6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.min.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-67945-2.rs:9:27 + | +LL | let x: Option<Box<Self>> = None; + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-2.rs b/tests/ui/const-generics/issues/issue-67945-2.rs new file mode 100644 index 000000000..cbb4e14ec --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.rs @@ -0,0 +1,16 @@ +// revisions: full min + +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +struct Bug<S: ?Sized> { + A: [(); { + //[full]~^ ERROR overly complex generic constant + let x: Option<Box<Self>> = None; + //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants + 0 + }], + B: S +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-3.full.stderr b/tests/ui/const-generics/issues/issue-67945-3.full.stderr new file mode 100644 index 000000000..98f9f8397 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.full.stderr @@ -0,0 +1,16 @@ +error: overly complex generic constant + --> $DIR/issue-67945-3.rs:10:13 + | +LL | A: [(); { + | _____________^ +LL | | let x: Option<S> = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr new file mode 100644 index 000000000..8e6b4b204 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-3.rs:11:23 + | +LL | let x: Option<S> = None; + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-3.rs:9:12 + | +LL | struct Bug<S> { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-3.rs b/tests/ui/const-generics/issues/issue-67945-3.rs new file mode 100644 index 000000000..fd8a393ef --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.rs @@ -0,0 +1,17 @@ +// Regression test for +// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285 +// Make sure we don't emit an E0277 error. + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bug<S> { //[min]~ ERROR: parameter `S` is never used + A: [(); { //[full]~ ERROR: overly complex generic constant + let x: Option<S> = None; + //[min]~^ ERROR: generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-4.full.stderr b/tests/ui/const-generics/issues/issue-67945-4.full.stderr new file mode 100644 index 000000000..c03d40a7b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.full.stderr @@ -0,0 +1,16 @@ +error: overly complex generic constant + --> $DIR/issue-67945-4.rs:9:13 + | +LL | A: [(); { + | _____________^ +LL | | let x: Option<Box<S>> = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr new file mode 100644 index 000000000..f9520872d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-4.rs:10:27 + | +LL | let x: Option<Box<S>> = None; + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-4.rs:8:12 + | +LL | struct Bug<S> { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-4.rs b/tests/ui/const-generics/issues/issue-67945-4.rs new file mode 100644 index 000000000..9a27bf09f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.rs @@ -0,0 +1,16 @@ +// Regression test for +// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285 + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bug<S> { //[min]~ ERROR: parameter `S` is never used + A: [(); { //[full]~ ERROR: overly complex generic constant + let x: Option<Box<S>> = None; + //[min]~^ ERROR: generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs b/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs new file mode 100644 index 000000000..ad5710baa --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs @@ -0,0 +1,13 @@ +// aux-build:impl-const.rs +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate impl_const; + +use impl_const::*; + +pub fn main() { + let n = Num::<5>; + n.five(); +} diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr new file mode 100644 index 000000000..ca9eb801d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.full.stderr @@ -0,0 +1,21 @@ +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:11:7 + | +LL | impl <const N: usize> Collatz<{Some(N)}> {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:17:6 + | +LL | impl<const N: usize> Foo {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr new file mode 100644 index 000000000..3740ced90 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -0,0 +1,30 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-68366.rs:11:37 + | +LL | impl <const N: usize> Collatz<{Some(N)}> {} + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:11:7 + | +LL | impl <const N: usize> Collatz<{Some(N)}> {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:17:6 + | +LL | impl<const N: usize> Foo {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs new file mode 100644 index 000000000..4c2741ab4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.rs @@ -0,0 +1,20 @@ +// Checks that const expressions have a useful note explaining why they can't be evaluated. +// The note should relate to the fact that it cannot be shown forall N that it maps 1-1 to a new +// type. + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Collatz<const N: Option<usize>>; + +impl <const N: usize> Collatz<{Some(N)}> {} +//~^ ERROR the const parameter +//[min]~^^ generic parameters may not be used in const operations + +struct Foo; + +impl<const N: usize> Foo {} +//~^ ERROR the const parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-68596.rs b/tests/ui/const-generics/issues/issue-68596.rs new file mode 100644 index 000000000..c3c9141e4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68596.rs @@ -0,0 +1,15 @@ +// check-pass +pub struct S(u8); + +impl S { + pub fn get<const A: u8>(&self) -> &u8 { + &self.0 + } +} + +fn main() { + const A: u8 = 5; + let s = S(0); + + s.get::<A>(); +} diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr new file mode 100644 index 000000000..df04c4896 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -0,0 +1,11 @@ +error: `[usize; 0]` is forbidden as the type of a const generic parameter + --> $DIR/issue-68615-adt.rs:6:23 + | +LL | struct Const<const V: [usize; 0]> {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-68615-adt.rs b/tests/ui/const-generics/issues/issue-68615-adt.rs new file mode 100644 index 000000000..3ef1ad45e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-adt.rs @@ -0,0 +1,13 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const<const V: [usize; 0]> {} +//[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter +type MyConst = Const<{ [] }>; + +fn main() { + let _x = Const::<{ [] }> {}; + let _y = MyConst {}; +} diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr new file mode 100644 index 000000000..1b4517087 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -0,0 +1,11 @@ +error: `[usize; 0]` is forbidden as the type of a const generic parameter + --> $DIR/issue-68615-array.rs:6:21 + | +LL | struct Foo<const V: [usize; 0] > {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-68615-array.rs b/tests/ui/const-generics/issues/issue-68615-array.rs new file mode 100644 index 000000000..93477be41 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-array.rs @@ -0,0 +1,13 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo<const V: [usize; 0] > {} +//[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter + +type MyFoo = Foo<{ [] }>; + +fn main() { + let _ = Foo::<{ [] }> {}; +} diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.rs b/tests/ui/const-generics/issues/issue-69654-run-pass.rs new file mode 100644 index 000000000..63d7fde78 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.rs @@ -0,0 +1,15 @@ +// run-pass +trait Bar<T> {} +impl<T> Bar<T> for [u8; 7] {} + +struct Foo<const N: usize> {} +impl<const N: usize> Foo<N> +where + [u8; N]: Bar<[(); N]>, +{ + fn foo() {} +} + +fn main() { + Foo::foo(); +} diff --git a/tests/ui/const-generics/issues/issue-70125-1.rs b/tests/ui/const-generics/issues/issue-70125-1.rs new file mode 100644 index 000000000..0027cd46a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70125-1.rs @@ -0,0 +1,17 @@ +// run-pass + +const L: usize = 4; + +pub trait Print<const N: usize> { + fn print(&self) -> usize { + N + } +} + +pub struct Printer; +impl Print<L> for Printer {} + +fn main() { + let p = Printer; + assert_eq!(p.print(), 4); +} diff --git a/tests/ui/const-generics/issues/issue-70125-2.rs b/tests/ui/const-generics/issues/issue-70125-2.rs new file mode 100644 index 000000000..cfd5e784e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70125-2.rs @@ -0,0 +1,12 @@ +// run-pass +fn main() { + <()>::foo(); +} + +trait Foo<const X: usize> { + fn foo() -> usize { + X + } +} + +impl Foo<3> for () {} diff --git a/tests/ui/const-generics/issues/issue-70167.rs b/tests/ui/const-generics/issues/issue-70167.rs new file mode 100644 index 000000000..3961941f8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70167.rs @@ -0,0 +1,6 @@ +// check-pass +pub trait Trait<const N: usize>: From<<Self as Trait<N>>::Item> { + type Item; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs b/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs new file mode 100644 index 000000000..2ec37cc3a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs @@ -0,0 +1,33 @@ +// build-pass + +pub fn works() { + let array/*: [_; _]*/ = default_array(); + let _: [_; 4] = array; + Foo::foo(&array); +} + +pub fn didnt_work() { + let array/*: [_; _]*/ = default_array(); + Foo::foo(&array); + let _: [_; 4] = array; +} + +trait Foo { + fn foo(&self) {} +} + +impl Foo for [i32; 4] {} +impl Foo for [i64; 8] {} + +// Only needed because `[_; _]` is not valid type syntax. +fn default_array<T, const N: usize>() -> [T; N] +where + [T; N]: Default, +{ + Default::default() +} + +fn main() { + works(); + didnt_work(); +} diff --git a/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs b/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs new file mode 100644 index 000000000..95e548428 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs @@ -0,0 +1,33 @@ +// build-pass + +fn works() { + let array/*: [u8; _]*/ = default_byte_array(); + let _: [_; 4] = array; + Foo::foo(&array); +} + +fn didnt_work() { + let array/*: [u8; _]*/ = default_byte_array(); + Foo::foo(&array); + let _: [_; 4] = array; +} + +trait Foo<T> { + fn foo(&self) {} +} + +impl Foo<i32> for [u8; 4] {} +impl Foo<i64> for [u8; 8] {} + +// Only needed because `[u8; _]` is not valid type syntax. +fn default_byte_array<const N: usize>() -> [u8; N] +where + [u8; N]: Default, +{ + Default::default() +} + +fn main() { + works(); + didnt_work(); +} diff --git a/tests/ui/const-generics/issues/issue-70225.rs b/tests/ui/const-generics/issues/issue-70225.rs new file mode 100644 index 000000000..d458d7b2e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70225.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(dead_code)] + +// We previously incorrectly linted `L` as unused here. +const L: usize = 3; + +fn main() { + let p = Printer {}; + p.print(); +} + +trait Print<const N: usize> { + fn print(&self) -> usize { + 3 + } +} + +struct Printer {} +impl Print<L> for Printer {} diff --git a/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs b/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs new file mode 100644 index 000000000..a76488249 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs @@ -0,0 +1,14 @@ +// check-pass + +trait T<const A: usize> { + fn f(); +} +struct S; + +impl T<0usize> for S { + fn f() {} +} + +fn main() { + let _err = <S as T<0usize>>::f(); +} diff --git a/tests/ui/const-generics/issues/issue-71169.full.stderr b/tests/ui/const-generics/issues/issue-71169.full.stderr new file mode 100644 index 000000000..1f5880f36 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.full.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71169.rs:5:43 + | +LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {} + | ^^^ the type must not depend on the parameter `LEN` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71169.min.stderr b/tests/ui/const-generics/issues/issue-71169.min.stderr new file mode 100644 index 000000000..998b16a79 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.min.stderr @@ -0,0 +1,18 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71169.rs:5:43 + | +LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {} + | ^^^ the type must not depend on the parameter `LEN` + +error: `[u8; LEN]` is forbidden as the type of a const generic parameter + --> $DIR/issue-71169.rs:5:38 + | +LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {} + | ^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71169.rs b/tests/ui/const-generics/issues/issue-71169.rs new file mode 100644 index 000000000..e4ec6b073 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn foo<const LEN: usize, const DATA: [u8; LEN]>() {} +//~^ ERROR the type of const parameters must not +//[min]~^^ ERROR `[u8; LEN]` is forbidden as the type of a const generic parameter +fn main() { + const DATA: [u8; 4] = *b"ABCD"; + foo::<4, DATA>(); +} diff --git a/tests/ui/const-generics/issues/issue-71202.rs b/tests/ui/const-generics/issues/issue-71202.rs new file mode 100644 index 000000000..57fd72b12 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71202.rs @@ -0,0 +1,31 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features, const_evaluatable_unchecked)] + +use std::marker::PhantomData; + +struct DataHolder<T> { + item: T, +} + +impl<T: Copy> DataHolder<T> { + const ITEM_IS_COPY: [(); 1 - { //~ ERROR unconstrained generic constant + trait NotCopy { + const VALUE: bool = false; + } + + impl<__Type: ?Sized> NotCopy for __Type {} + + struct IsCopy<__Type: ?Sized>(PhantomData<__Type>); + + impl<__Type> IsCopy<__Type> + where + __Type: Sized + Copy, + { + const VALUE: bool = true; + } + + <IsCopy<T>>::VALUE + } as usize] = []; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr new file mode 100644 index 000000000..277540610 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -0,0 +1,33 @@ +error: unconstrained generic constant + --> $DIR/issue-71202.rs:11:5 + | +LL | / const ITEM_IS_COPY: [(); 1 - { +LL | | trait NotCopy { +LL | | const VALUE: bool = false; +LL | | } +... | +LL | | <IsCopy<T>>::VALUE +LL | | } as usize] = []; + | |_____________________^ + | + = help: try adding a `where` bound using this expression: `where [(); 1 - { + trait NotCopy { + const VALUE: bool = false; + } + + impl<__Type: ?Sized> NotCopy for __Type {} + + struct IsCopy<__Type: ?Sized>(PhantomData<__Type>); + + impl<__Type> IsCopy<__Type> + where + __Type: Sized + Copy, + { + const VALUE: bool = true; + } + + <IsCopy<T>>::VALUE + } as usize]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr new file mode 100644 index 000000000..e17cf96aa --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.full.stderr @@ -0,0 +1,28 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:14:82 + | +LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) { + | ^^^^ the type must not depend on the parameter `Args` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:23:40 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^ the type must not depend on the parameter `Args` + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:14:61 + | +LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:23:19 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0741, E0770. +For more information about an error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr new file mode 100644 index 000000000..3950317b3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -0,0 +1,27 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:14:82 + | +LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) { + | ^^^^ the type must not depend on the parameter `Args` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:23:40 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^ the type must not depend on the parameter `Args` + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:14:61 + | +LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:23:19 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs new file mode 100644 index 000000000..66f819dbe --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.rs @@ -0,0 +1,36 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Test(*const usize); + +type PassArg = (); + +unsafe extern "C" fn pass(args: PassArg) { + println!("Hello, world!"); +} + +impl Test { + pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + self.0 = Self::trampiline::<Args, IDX, FN> as _ + } + + unsafe extern "C" fn trampiline< + Args: Sized, + const IDX: usize, + const FN: unsafe extern "C" fn(Args), + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + >( + args: Args, + ) { + FN(args) + } +} + +fn main() { + let x = Test(); + x.call_me::<PassArg, 30, pass>() +} diff --git a/tests/ui/const-generics/issues/issue-71382.full.stderr b/tests/ui/const-generics/issues/issue-71382.full.stderr new file mode 100644 index 000000000..ab2a4e64a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:16:23 + | +LL | fn test<const FN: fn()>(&self) { + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr new file mode 100644 index 000000000..715037bd5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:16:23 + | +LL | fn test<const FN: fn()>(&self) { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-71382.rs b/tests/ui/const-generics/issues/issue-71382.rs new file mode 100644 index 000000000..4392d72e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.rs @@ -0,0 +1,25 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Test(); + +fn pass() { + println!("Hello, world!"); +} + +impl Test { + pub fn call_me(&self) { + self.test::<pass>(); + } + + fn test<const FN: fn()>(&self) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + FN(); + } +} + +fn main() { + let x = Test(); + x.call_me() +} diff --git a/tests/ui/const-generics/issues/issue-71547.rs b/tests/ui/const-generics/issues/issue-71547.rs new file mode 100644 index 000000000..60776a1a9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71547.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub trait GetType<const N: &'static str> { + type Ty; + fn get(&self) -> &Self::Ty; +} + +pub fn get_val<T>(value: &T) -> &T::Ty +where + T: GetType<"hello">, +{ + value.get() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71611.full.stderr b/tests/ui/const-generics/issues/issue-71611.full.stderr new file mode 100644 index 000000000..656aa29e1 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.full.stderr @@ -0,0 +1,16 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71611.rs:5:31 + | +LL | fn func<A, const F: fn(inner: A)>(outer: A) { + | ^ the type must not depend on the parameter `A` + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71611.rs:5:21 + | +LL | fn func<A, const F: fn(inner: A)>(outer: A) { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0741, E0770. +For more information about an error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr new file mode 100644 index 000000000..01a85b745 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71611.rs:5:31 + | +LL | fn func<A, const F: fn(inner: A)>(outer: A) { + | ^ the type must not depend on the parameter `A` + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71611.rs:5:21 + | +LL | fn func<A, const F: fn(inner: A)>(outer: A) { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs new file mode 100644 index 000000000..fbb91ca18 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn func<A, const F: fn(inner: A)>(outer: A) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + F(outer); +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71986.rs b/tests/ui/const-generics/issues/issue-71986.rs new file mode 100644 index 000000000..6f0a98ead --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71986.rs @@ -0,0 +1,6 @@ +// check-pass + +pub trait Foo<const B: bool> {} +pub fn bar<T: Foo<{ true }>>() {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-72352.full.stderr b/tests/ui/const-generics/issues/issue-72352.full.stderr new file mode 100644 index 000000000..92580b336 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-72352.rs:7:42 + | +LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr new file mode 100644 index 000000000..eedd73c4d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-72352.rs:7:42 + | +LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-72352.rs b/tests/ui/const-generics/issues/issue-72352.rs new file mode 100644 index 000000000..2fa1d7a53 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.rs @@ -0,0 +1,22 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::ffi::{CStr, CString}; + +unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize { + //~^ ERROR: using function pointers as const generic parameters is forbidden + F(CStr::from_ptr(ptr)) +} + +fn safely_do_the_thing(s: &CStr) -> usize { + s.to_bytes().len() +} + +fn main() { + let baguette = CString::new("baguette").unwrap(); + let ptr = baguette.as_ptr(); + println!("{}", unsafe { + unsafely_do_the_thing::<safely_do_the_thing>(ptr) + }); +} diff --git a/tests/ui/const-generics/issues/issue-72845.rs b/tests/ui/const-generics/issues/issue-72845.rs new file mode 100644 index 000000000..bea5dc8ba --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72845.rs @@ -0,0 +1,49 @@ +#![feature(generic_const_exprs)] +#![feature(specialization)] +#![allow(incomplete_features)] + +//-------------------------------------------------- + +trait Depth { + const C: usize; +} + +trait Type { + type AT: Depth; +} + +//-------------------------------------------------- + +enum Predicate<const B: bool> {} + +trait Satisfied {} + +impl Satisfied for Predicate<true> {} + +//-------------------------------------------------- + +trait Spec1 {} + +impl<T: Type> Spec1 for T where Predicate<{T::AT::C > 0}>: Satisfied {} + +trait Spec2 {} + +//impl<T: Type > Spec2 for T where Predicate<{T::AT::C > 1}>: Satisfied {} +impl<T: Type > Spec2 for T where Predicate<true>: Satisfied {} + +//-------------------------------------------------- + +trait Foo { + fn Bar(); +} + +impl<T: Spec1> Foo for T { + default fn Bar() {} +} + +impl<T: Spec2> Foo for T { +//~^ ERROR conflicting implementations of trait + fn Bar() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-72845.stderr b/tests/ui/const-generics/issues/issue-72845.stderr new file mode 100644 index 000000000..631c8605f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72845.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` + --> $DIR/issue-72845.rs:44:1 + | +LL | impl<T: Spec1> Foo for T { + | ------------------------ first implementation here +... +LL | impl<T: Spec2> Foo for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/issues/issue-73120.rs b/tests/ui/const-generics/issues/issue-73120.rs new file mode 100644 index 000000000..050dc9bde --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73120.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:const_generic_issues_lib.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_generic_issues_lib as lib2; +fn unused_function( + _: <lib2::GenericType<42> as lib2::TypeFn>::Output +) {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-73260.rs b/tests/ui/const-generics/issues/issue-73260.rs new file mode 100644 index 000000000..d762f9c8b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73260.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zsave-analysis +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +struct Arr<const N: usize> +where + Assert::<{N < usize::MAX / 2}>: IsTrue, +{} + +enum Assert<const CHECK: bool> {} + +trait IsTrue {} + +impl IsTrue for Assert<true> {} + +fn main() { + let x: Arr<{usize::MAX}> = Arr {}; + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/const-generics/issues/issue-73260.stderr b/tests/ui/const-generics/issues/issue-73260.stderr new file mode 100644 index 000000000..7670032e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73260.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/issue-73260.rs:16:12 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error[E0308]: mismatched types + --> $DIR/issue-73260.rs:16:32 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr new file mode 100644 index 000000000..f03354fc4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -0,0 +1,11 @@ +error: `[u32; LEN]` is forbidden as the type of a const generic parameter + --> $DIR/issue-73491.rs:8:19 + | +LL | fn hoge<const IN: [u32; LEN]>() {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-73491.rs b/tests/ui/const-generics/issues/issue-73491.rs new file mode 100644 index 000000000..482dbb04d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73491.rs @@ -0,0 +1,11 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +const LEN: usize = 1024; + +fn hoge<const IN: [u32; LEN]>() {} +//[min]~^ ERROR `[u32; LEN]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr new file mode 100644 index 000000000..0a7db6247 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -0,0 +1,11 @@ +error: `&'static [u32]` is forbidden as the type of a const generic parameter + --> $DIR/issue-73727-static-reference-array-const-param.rs:9:15 + | +LL | fn a<const X: &'static [u32]>() {} + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs new file mode 100644 index 000000000..f0d604835 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs @@ -0,0 +1,14 @@ +// Regression test for #73727 + +// revisions: full min +//[full]check-pass + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn a<const X: &'static [u32]>() {} +//[min]~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter + +fn main() { + a::<{&[]}>(); +} diff --git a/tests/ui/const-generics/issues/issue-74101.min.stderr b/tests/ui/const-generics/issues/issue-74101.min.stderr new file mode 100644 index 000000000..134c24834 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74101.min.stderr @@ -0,0 +1,20 @@ +error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + --> $DIR/issue-74101.rs:6:18 + | +LL | fn test<const N: [u8; 1 + 2]>() {} + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + --> $DIR/issue-74101.rs:9:21 + | +LL | struct Foo<const N: [u8; 1 + 2]>; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-74101.rs b/tests/ui/const-generics/issues/issue-74101.rs new file mode 100644 index 000000000..4c9b2d3c6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74101.rs @@ -0,0 +1,12 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn test<const N: [u8; 1 + 2]>() {} +//[min]~^ ERROR `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + +struct Foo<const N: [u8; 1 + 2]>; +//[min]~^ ERROR `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr new file mode 100644 index 000000000..b462d8448 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -0,0 +1,11 @@ +error: `IceEnum` is forbidden as the type of a const generic parameter + --> $DIR/issue-74255.rs:14:31 + | +LL | fn ice_struct_fn<const I: IceEnum>() {} + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-74255.rs b/tests/ui/const-generics/issues/issue-74255.rs new file mode 100644 index 000000000..0e523926f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74255.rs @@ -0,0 +1,20 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +#[derive(PartialEq, Eq)] +enum IceEnum { + Variant +} + +struct IceStruct; + +impl IceStruct { + fn ice_struct_fn<const I: IceEnum>() {} + //[min]~^ ERROR `IceEnum` is forbidden as the type of a const generic parameter +} + +fn main() { + IceStruct::ice_struct_fn::<{IceEnum::Variant}>(); +} diff --git a/tests/ui/const-generics/issues/issue-74906.rs b/tests/ui/const-generics/issues/issue-74906.rs new file mode 100644 index 000000000..cc1f2853f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74906.rs @@ -0,0 +1,22 @@ +// edition:2018 +// check-pass + + +const SIZE: usize = 16; + +struct Bar<const H: usize> {} + +struct Foo<const H: usize> {} + +impl<const H: usize> Foo<H> { + async fn biz(_: &[[u8; SIZE]]) -> Vec<()> { + vec![] + } + + pub async fn baz(&self) -> Bar<H> { + Self::biz(&vec![]).await; + Bar {} + } +} + +fn main() { } diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr new file mode 100644 index 000000000..729ecc202 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74950.min.stderr @@ -0,0 +1,47 @@ +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer<const I: Inner>; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer<const I: Inner>; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer<const I: Inner>; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer<const I: Inner>; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer<const I: Inner>; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/const-generics/issues/issue-74950.rs b/tests/ui/const-generics/issues/issue-74950.rs new file mode 100644 index 000000000..3e1ca4735 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74950.rs @@ -0,0 +1,24 @@ +// [full] build-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + + +#[derive(PartialEq, Eq)] +struct Inner; + +// Note: We emit the error 5 times if we don't deduplicate: +// - struct definition +// - impl PartialEq +// - impl Eq +// - impl StructuralPartialEq +// - impl StructuralEq +#[derive(PartialEq, Eq)] +struct Outer<const I: Inner>; +//[min]~^ `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr new file mode 100644 index 000000000..46af19ef3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -0,0 +1,11 @@ +error: `[u8; Bar::<u32>::value()]` is forbidden as the type of a const generic parameter + --> $DIR/issue-75047.rs:14:21 + | +LL | struct Foo<const N: [u8; Bar::<u32>::value()]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-75047.rs b/tests/ui/const-generics/issues/issue-75047.rs new file mode 100644 index 000000000..7b6fb92bc --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75047.rs @@ -0,0 +1,17 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bar<T>(T); + +impl<T> Bar<T> { + const fn value() -> usize { + 42 + } +} + +struct Foo<const N: [u8; Bar::<u32>::value()]>; +//[min]~^ ERROR `[u8; Bar::<u32>::value()]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-75299.rs b/tests/ui/const-generics/issues/issue-75299.rs new file mode 100644 index 000000000..83ef09af8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75299.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zmir-opt-level=4 +// run-pass +fn main() { + fn foo<const N: usize>() -> [u8; N] { + [0; N] + } + let _x = foo::<1>(); +} diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs new file mode 100644 index 000000000..2e6b02236 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs @@ -0,0 +1,11 @@ +fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] { + //~^ ERROR generic parameters may not be used in const operations + todo!() +} + +fn const_param<const N: usize>() -> [u8; N + 1] { + //~^ ERROR generic parameters may not be used in const operations + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr new file mode 100644 index 000000000..3b53e18e6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-76701-ty-param-in-const.rs:1:46 + | +LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] { + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-76701-ty-param-in-const.rs:6:42 + | +LL | fn const_param<const N: usize>() -> [u8; N + 1] { + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-77357.rs b/tests/ui/const-generics/issues/issue-77357.rs new file mode 100644 index 000000000..3cb8d3846 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-77357.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MyTrait<T> {} + +fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + //~^ ERROR overly complex generic constant + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-77357.stderr b/tests/ui/const-generics/issues/issue-77357.stderr new file mode 100644 index 000000000..68b35a38b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-77357.stderr @@ -0,0 +1,11 @@ +error: overly complex generic constant + --> $DIR/issue-77357.rs:6:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-79674.rs b/tests/ui/const-generics/issues/issue-79674.rs new file mode 100644 index 000000000..ff141d328 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-79674.rs @@ -0,0 +1,28 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MiniTypeId { + const TYPE_ID: u64; +} + +impl<T> MiniTypeId for T { + const TYPE_ID: u64 = 0; +} + +enum Lift<const V: bool> {} + +trait IsFalse {} +impl IsFalse for Lift<false> {} + +const fn is_same_type<T: MiniTypeId, U: MiniTypeId>() -> bool { + T::TYPE_ID == U::TYPE_ID +} + +fn requires_distinct<A, B>(_a: A, _b: B) where + A: MiniTypeId, B: MiniTypeId, + Lift<{is_same_type::<A, B>()}>: IsFalse {} + +fn main() { + requires_distinct("str", 12); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/issues/issue-79674.stderr b/tests/ui/const-generics/issues/issue-79674.stderr new file mode 100644 index 000000000..02b48b55f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-79674.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-79674.rs:26:5 + | +LL | requires_distinct("str", 12); + | ^^^^^^^^^^^^^^^^^ expected `true`, found `false` + | + = note: expected constant `true` + found constant `false` +note: required by a bound in `requires_distinct` + --> $DIR/issue-79674.rs:23:37 + | +LL | fn requires_distinct<A, B>(_a: A, _b: B) where + | ----------------- required by a bound in this +LL | A: MiniTypeId, B: MiniTypeId, +LL | Lift<{is_same_type::<A, B>()}>: IsFalse {} + | ^^^^^^^ required by this bound in `requires_distinct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-80062.rs b/tests/ui/const-generics/issues/issue-80062.rs new file mode 100644 index 000000000..56dc53298 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80062.rs @@ -0,0 +1,10 @@ +// Regression test for issue #80062 (fixed by `min_const_generics`) + +fn sof<T>() -> T { unimplemented!() } + +fn test<T>() { + let _: [u8; sof::<T>()]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-80062.stderr b/tests/ui/const-generics/issues/issue-80062.stderr new file mode 100644 index 000000000..754f18d5c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80062.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80062.rs:6:23 + | +LL | let _: [u8; sof::<T>()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-80375.rs b/tests/ui/const-generics/issues/issue-80375.rs new file mode 100644 index 000000000..c906bb2c4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80375.rs @@ -0,0 +1,4 @@ +struct MyArray<const COUNT: usize>([u8; COUNT + 1]); +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-80375.stderr b/tests/ui/const-generics/issues/issue-80375.stderr new file mode 100644 index 000000000..5409002a9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80375.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80375.rs:1:41 + | +LL | struct MyArray<const COUNT: usize>([u8; COUNT + 1]); + | ^^^^^ cannot perform const operation using `COUNT` + | + = help: const parameters may only be used as standalone arguments, i.e. `COUNT` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-82956.rs b/tests/ui/const-generics/issues/issue-82956.rs new file mode 100644 index 000000000..3539e9b96 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-82956.rs @@ -0,0 +1,33 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct ConstCheck<const CHECK: bool>; + +pub trait True {} +impl True for ConstCheck<true> {} + +pub trait OrdesDec { + type Newlen; + type Output; + + fn pop(self) -> (Self::Newlen, Self::Output); +} + +impl<T, const N: usize> OrdesDec for [T; N] +where + ConstCheck<{N > 1}>: True, + [T; N - 1]: Sized, +{ + type Newlen = [T; N - 1]; + type Output = T; + + fn pop(self) -> (Self::Newlen, Self::Output) { + let mut iter = IntoIter::new(self); + //~^ ERROR: failed to resolve: use of undeclared type `IntoIter` + let end = iter.next_back().unwrap(); + let new = [(); N - 1].map(move |()| iter.next().unwrap()); + (new, end) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-82956.stderr b/tests/ui/const-generics/issues/issue-82956.stderr new file mode 100644 index 000000000..d2320293e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-82956.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type `IntoIter` + --> $DIR/issue-82956.rs:25:24 + | +LL | let mut iter = IntoIter::new(self); + | ^^^^^^^^ use of undeclared type `IntoIter` + | +help: consider importing one of these items + | +LL | use std::array::IntoIter; + | +LL | use std::collections::binary_heap::IntoIter; + | +LL | use std::collections::btree_map::IntoIter; + | +LL | use std::collections::btree_set::IntoIter; + | + and 8 other candidates + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/const-generics/issues/issue-83249.rs b/tests/ui/const-generics/issues/issue-83249.rs new file mode 100644 index 000000000..65148c55e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83249.rs @@ -0,0 +1,23 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Foo { + const N: usize; +} + +impl Foo for u8 { + const N: usize = 1; +} + +fn foo<T: Foo>(_: [u8; T::N]) -> T { + todo!() +} + +pub fn bar() { + let _: u8 = foo([0; 1]); + + let _ = foo([0; 1]); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83249.stderr b/tests/ui/const-generics/issues/issue-83249.stderr new file mode 100644 index 000000000..7491fdc8a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83249.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-83249.rs:19:9 + | +LL | let _ = foo([0; 1]); + | ^ + | +help: consider giving this pattern a type + | +LL | let _: /* Type */ = foo([0; 1]); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/issues/issue-83288.rs b/tests/ui/const-generics/issues/issue-83288.rs new file mode 100644 index 000000000..a24596d24 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83288.rs @@ -0,0 +1,69 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::{marker::PhantomData, ops::Mul}; + +pub enum Nil {} +pub struct Cons<T, L> { + _phantom: PhantomData<(T, L)>, +} + +pub trait Indices<const N: usize> { + const RANK: usize; + const NUM_ELEMS: usize; +} + +impl<const N: usize> Indices<N> for Nil { + const RANK: usize = 0; + const NUM_ELEMS: usize = 1; +} + +impl<T, I: Indices<N>, const N: usize> Indices<N> for Cons<T, I> { + const RANK: usize = I::RANK + 1; + const NUM_ELEMS: usize = I::NUM_ELEMS * N; +} + +pub trait Concat<J> { + type Output; +} + +impl<J> Concat<J> for Nil { + type Output = J; +} + +impl<T, I, J> Concat<J> for Cons<T, I> +where + I: Concat<J>, +{ + type Output = Cons<T, <I as Concat<J>>::Output>; +} + +pub struct Tensor<I: Indices<N>, const N: usize> +where + [u8; I::NUM_ELEMS]: Sized, +{ + pub data: [u8; I::NUM_ELEMS], + _phantom: PhantomData<I>, +} + +impl<I: Indices<N>, J: Indices<N>, const N: usize> Mul<Tensor<J, N>> for Tensor<I, N> +where + I: Concat<J>, + <I as Concat<J>>::Output: Indices<N>, + [u8; I::NUM_ELEMS]: Sized, + [u8; J::NUM_ELEMS]: Sized, + [u8; <I as Concat<J>>::Output::NUM_ELEMS]: Sized, +{ + type Output = Tensor<<I as Concat<J>>::Output, N>; + + fn mul(self, _rhs: Tensor<J, N>) -> Self::Output { + Tensor { + data: [0u8; <I as Concat<J>>::Output::NUM_ELEMS], + _phantom: PhantomData, + } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83466.rs b/tests/ui/const-generics/issues/issue-83466.rs new file mode 100644 index 000000000..73c930101 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83466.rs @@ -0,0 +1,17 @@ +// regression test for #83466- tests that generic arg mismatch errors between +// consts and types are not suppressed when there are explicit late bound lifetimes + +struct S; +impl S { + fn func<'a, U>(self) -> U { + todo!() + } +} +fn dont_crash<'a, U>() { + S.func::<'a, 10_u32>() + //~^ WARNING cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + //~^^ WARNING this was previously accepted by + //~^^^ ERROR constant provided when a type was expected [E0747] +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83466.stderr b/tests/ui/const-generics/issues/issue-83466.stderr new file mode 100644 index 000000000..bcfd70639 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83466.stderr @@ -0,0 +1,22 @@ +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/issue-83466.rs:11:14 + | +LL | fn func<'a, U>(self) -> U { + | -- the late bound lifetime parameter is introduced here +... +LL | S.func::<'a, 10_u32>() + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868> + = note: `#[warn(late_bound_lifetime_arguments)]` on by default + +error[E0747]: constant provided when a type was expected + --> $DIR/issue-83466.rs:11:18 + | +LL | S.func::<'a, 10_u32>() + | ^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/issues/issue-83765.rs b/tests/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 000000000..71c164ab0 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83765.rs @@ -0,0 +1,116 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; + //~^ ERROR cycle detected when resolving instance + // FIXME Given the current state of the compiler its expected that we cycle here, + // but the cycle is still wrong. + const ISSCALAR: bool = Self::DIM == 0; + fn is_scalar(&self) -> bool { + Self::ISSCALAR + } +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; + fn inbounds(&self, index: [usize; Self::DIM]) -> bool { + index.iter().zip(self.size().iter()).all(|(i, s)| i < s) + } +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>; + fn lazy_updim<const NEWDIM: usize>( + &self, + size: [usize; NEWDIM], + ) -> LazyUpdim<Self, { Self::DIM }, NEWDIM> { + assert!( + NEWDIM >= Self::DIM, + "Updimmed tensor cannot have fewer indices than the initial one." + ); + LazyUpdim { size, reference: &self } + } + fn bmap<T, F: Fn(Self::Element) -> T>(&self, foo: F) -> BMap<T, Self, F, { Self::DIM }> { + BMap { reference: self, closure: foo } + } +} + +struct LazyUpdim<'a, T: Broadcastable, const OLDDIM: usize, const DIM: usize> { + size: [usize; DIM], + reference: &'a T, +} + +impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T, { T::DIM }, DIM> { + const DIM: usize = DIM; +} + +impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> { + fn size(&self) -> [usize; DIM] { + self.size + } +} + +impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { + type Element = T::Element; + fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { + assert!(DIM >= T::DIM); + if !self.inbounds(index) { + return None; + } + let size = self.size(); + let newindex: [usize; T::DIM] = Default::default(); + self.reference.bget(newindex) + } +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + self.reference.size() + } +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcastable + for BMap<'a, R, T, F, DIM> +{ + type Element = R; + fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { + self.reference.bget(index).map(&self.closure) + } +} + +impl<T> TensorDimension for Vec<T> { + const DIM: usize = 1; +} +impl<T> TensorSize for Vec<T> { + fn size(&self) -> [usize; 1] { + [self.len()] + } +} +impl<T: Clone> Broadcastable for Vec<T> { + type Element = T; + fn bget(&self, index: [usize; 1]) -> Option<T> { + self.get(index[0]).cloned() + } +} + +fn main() { + let v = vec![1, 2, 3]; + let bv = v.lazy_updim([3, 4]); + let bbv = bv.bmap(|x| x * x); + + println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds.")); +} diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 000000000..d7b2b006c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM` + --> $DIR/issue-83765.rs:5:5 + | +LL | const DIM: usize; + | ^^^^^^^^^^^^^^^^ + | +note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>`... + --> $DIR/issue-83765.rs:4:1 + | +LL | trait TensorDimension { + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle +note: cycle used when computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>` + --> $DIR/issue-83765.rs:4:1 + | +LL | trait TensorDimension { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/issues/issue-83993.rs b/tests/ui/const-generics/issues/issue-83993.rs new file mode 100644 index 000000000..f2f05d952 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83993.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn bug<'a>() +where + for<'b> [(); { + let x: &'b (); + 0 + }]: +{} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-84659.rs b/tests/ui/const-generics/issues/issue-84659.rs new file mode 100644 index 000000000..440ca740a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-84659.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Bar<const N: usize> {} + +trait Foo<'a> { + const N: usize; + type Baz: Bar<{ Self::N }>; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-84659.stderr b/tests/ui/const-generics/issues/issue-84659.stderr new file mode 100644 index 000000000..2dfc48a34 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-84659.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-84659.rs:8:15 + | +LL | type Baz: Bar<{ Self::N }>; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-85031-2.rs b/tests/ui/const-generics/issues/issue-85031-2.rs new file mode 100644 index 000000000..50dd66da6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-85031-2.rs @@ -0,0 +1,17 @@ +// check-pass +// known-bug: unknown + +// This should not compile, as the compiler should not know +// `A - 0` is satisfied `?x - 0` if `?x` is inferred to `A`. +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct Ref<'a>(&'a i32); + +impl<'a> Ref<'a> { + pub fn foo<const A: usize>() -> [(); A - 0] { + Self::foo() + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-85031-2.stderr b/tests/ui/const-generics/issues/issue-85031-2.stderr new file mode 100644 index 000000000..896e1c7ea --- /dev/null +++ b/tests/ui/const-generics/issues/issue-85031-2.stderr @@ -0,0 +1,13 @@ +warning: function cannot return without recursing + --> $DIR/issue-85031-2.rs:12:5 + | +LL | pub fn foo<const A: usize>() -> [(); A - 0] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | Self::foo() + | ----------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/issues/issue-86033.rs b/tests/ui/const-generics/issues/issue-86033.rs new file mode 100644 index 000000000..cf08f722f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86033.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait IsTrue<const T: bool> {} +impl IsTrue<true> for () {} + +pub trait IsZST {} + +impl<T> IsZST for T +where + (): IsTrue<{ std::mem::size_of::<T>() == 0 }> +{} + +fn _func() -> impl IsZST { + || {} +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86530.rs b/tests/ui/const-generics/issues/issue-86530.rs new file mode 100644 index 000000000..b024decd4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86530.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait X { + const Y: usize; +} + +fn z<T>(t: T) +where + T: X, + [(); T::Y]: , +{ +} + +fn unit_literals() { + z(" "); + //~^ ERROR: the trait bound `&str: X` is not satisfied +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86530.stderr b/tests/ui/const-generics/issues/issue-86530.stderr new file mode 100644 index 000000000..c63857b23 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86530.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `&str: X` is not satisfied + --> $DIR/issue-86530.rs:16:7 + | +LL | z(" "); + | - ^^^ the trait `X` is not implemented for `&str` + | | + | required by a bound introduced by this call + | +note: required by a bound in `z` + --> $DIR/issue-86530.rs:10:8 + | +LL | fn z<T>(t: T) + | - required by a bound in this +LL | where +LL | T: X, + | ^ required by this bound in `z` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs new file mode 100644 index 000000000..0b535fd66 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Foo { + const ASSOC_C: usize; + fn foo() where [(); Self::ASSOC_C]:; +} + +struct Bar<const N: &'static ()>; +impl<const N: &'static ()> Foo for Bar<N> { + const ASSOC_C: usize = 3; + + fn foo() where [u8; Self::ASSOC_C]: { + let _: [u8; Self::ASSOC_C] = loop {}; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs new file mode 100644 index 000000000..5289c4e99 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features, unused_variables)] + +struct F<const S: &'static str>; +impl<const S: &'static str> X for F<{ S }> { + const W: usize = 3; + + fn d(r: &[u8; Self::W]) -> F<{ S }> { + let x: [u8; Self::W] = [0; Self::W]; + F + } +} + +pub trait X { + const W: usize; + fn d(r: &[u8; Self::W]) -> Self; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86820.rs b/tests/ui/const-generics/issues/issue-86820.rs new file mode 100644 index 000000000..ae4bd943f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86820.rs @@ -0,0 +1,24 @@ +// Regression test for the ICE described in #86820. + +#![allow(unused, dead_code)] +use std::ops::BitAnd; + +const C: fn() = || is_set(); +fn is_set() { + 0xffu8.bit::<0>(); +} + +trait Bits { + fn bit<const I: u8>(self) -> bool; +} + +impl Bits for u8 { + fn bit<const I: usize>(self) -> bool { + //~^ ERROR: method `bit` has an incompatible generic parameter for trait `Bits` [E0053] + let i = 1 << I; + let mask = u8::from(i); + mask & self == mask + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86820.stderr b/tests/ui/const-generics/issues/issue-86820.stderr new file mode 100644 index 000000000..3a9cd957f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86820.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `bit` has an incompatible generic parameter for trait `Bits` + --> $DIR/issue-86820.rs:16:12 + | +LL | trait Bits { + | ---- +LL | fn bit<const I: u8>(self) -> bool; + | ----------- expected const parameter of type `u8` +... +LL | impl Bits for u8 { + | ---------------- +LL | fn bit<const I: usize>(self) -> bool { + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/issues/issue-87076.rs b/tests/ui/const-generics/issues/issue-87076.rs new file mode 100644 index 000000000..8a567678b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87076.rs @@ -0,0 +1,20 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +pub struct UnitDims { + pub time: u8, + pub length: u8, +} + +pub struct UnitValue<const DIMS: UnitDims>; + +impl<const DIMS: UnitDims> UnitValue<DIMS> { + fn crash() {} +} + +fn main() { + UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash(); +} diff --git a/tests/ui/const-generics/issues/issue-87470.rs b/tests/ui/const-generics/issues/issue-87470.rs new file mode 100644 index 000000000..d60181a41 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87470.rs @@ -0,0 +1,24 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait TraitWithConst { + const SOME_CONST: usize; +} + +pub trait OtherTrait: TraitWithConst { + fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST]; +} + +impl TraitWithConst for f32 { + const SOME_CONST: usize = 32; +} + +impl OtherTrait for f32 { + fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST] { + [0; 32] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-87493.rs b/tests/ui/const-generics/issues/issue-87493.rs new file mode 100644 index 000000000..d8599ab22 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87493.rs @@ -0,0 +1,14 @@ +pub trait MyTrait { + type Assoc; +} + +pub fn foo<S, T>(_s: S, _t: T) +where + S: MyTrait, + T: MyTrait<Assoc == S::Assoc>, + //~^ ERROR: expected one of `,` or `>`, found `==` + //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-87493.stderr b/tests/ui/const-generics/issues/issue-87493.stderr new file mode 100644 index 000000000..653afae21 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87493.stderr @@ -0,0 +1,30 @@ +error: expected one of `,` or `>`, found `==` + --> $DIR/issue-87493.rs:8:22 + | +LL | T: MyTrait<Assoc == S::Assoc>, + | ^^ expected one of `,` or `>` + | +help: if you meant to use an associated type binding, replace `==` with `=` + | +LL | T: MyTrait<Assoc = S::Assoc>, + | ~ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-87493.rs:8:8 + | +LL | T: MyTrait<Assoc == S::Assoc>, + | ^^^^^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/issue-87493.rs:1:11 + | +LL | pub trait MyTrait { + | ^^^^^^^ +help: replace the generic bound with the associated type + | +LL | T: MyTrait<Assoc = Assoc == S::Assoc>, + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/issues/issue-87964.rs b/tests/ui/const-generics/issues/issue-87964.rs new file mode 100644 index 000000000..116686abb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87964.rs @@ -0,0 +1,29 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Target { + const LENGTH: usize; +} + + +pub struct Container<T: Target> +where + [(); T::LENGTH]: Sized, +{ + _target: T, +} + +impl<T: Target> Container<T> +where + [(); T::LENGTH]: Sized, +{ + pub fn start( + _target: T, + ) -> Container<T> { + Container { _target } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88119.rs b/tests/ui/const-generics/issues/issue-88119.rs new file mode 100644 index 000000000..647b0eea8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88119.rs @@ -0,0 +1,36 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(const_trait_impl, generic_const_exprs)] + +#[const_trait] +trait ConstName { + const NAME_BYTES: &'static [u8]; +} + +impl const ConstName for u8 { + const NAME_BYTES: &'static [u8] = b"u8"; +} + +const fn name_len<T: ?Sized + ConstName>() -> usize { + T::NAME_BYTES.len() +} + +impl<T: ?Sized + ConstName> const ConstName for &T +where + [(); name_len::<T>()]:, +{ + const NAME_BYTES: &'static [u8] = b"&T"; +} + +impl<T: ?Sized + ConstName> const ConstName for &mut T +where + [(); name_len::<T>()]:, +{ + const NAME_BYTES: &'static [u8] = b"&mut T"; +} + +pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES; +pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88468.rs b/tests/ui/const-generics/issues/issue-88468.rs new file mode 100644 index 000000000..914047236 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88468.rs @@ -0,0 +1,13 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct Assert<const COND: bool>(); +pub trait IsTrue {} +impl IsTrue for Assert<true> {} + +pub trait IsNotZST {} +impl<T> IsNotZST for T where Assert<{ std::mem::size_of::<T>() > 0 }>: IsTrue {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88997.rs b/tests/ui/const-generics/issues/issue-88997.rs new file mode 100644 index 000000000..7666a5141 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88997.rs @@ -0,0 +1,14 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +struct ConstAssert<const COND: bool>; +trait True {} +impl True for ConstAssert<true> {} + +struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +//~| ERROR the type of const parameters must not depend on other generic parameters +where + ConstAssert<{ MIN <= MAX }>: True; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88997.stderr b/tests/ui/const-generics/issues/issue-88997.stderr new file mode 100644 index 000000000..505ba0da2 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88997.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:40 + | +LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) + | ^ the type must not depend on the parameter `T` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:54 + | +LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-89146.rs b/tests/ui/const-generics/issues/issue-89146.rs new file mode 100644 index 000000000..e3540f46f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89146.rs @@ -0,0 +1,26 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub trait Foo { + const SIZE: usize; + + fn to_bytes(&self) -> [u8; Self::SIZE]; +} + +pub fn bar<G: Foo>(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + deeper_bar(a) +} + +fn deeper_bar<G: Foo>(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + a.to_bytes()[0] +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-89304.rs b/tests/ui/const-generics/issues/issue-89304.rs new file mode 100644 index 000000000..d544d637c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89304.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct GenericStruct<const T: usize> { val: i64 } + +impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> { + fn from(other: GenericStruct<T>) -> Self { + Self { val: other.val } + } +} + +impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> { + fn from(other: GenericStruct<{T + 1}>) -> Self { + Self { val: other.val } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-89320.rs b/tests/ui/const-generics/issues/issue-89320.rs new file mode 100644 index 000000000..afa5c8fab --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89320.rs @@ -0,0 +1,19 @@ +// build-pass + +#![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/ui/const-generics/issues/issue-89334.rs b/tests/ui/const-generics/issues/issue-89334.rs new file mode 100644 index 000000000..b15b7428c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89334.rs @@ -0,0 +1,16 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait AnotherTrait{ + const ARRAY_SIZE: usize; +} +pub trait Shard<T: AnotherTrait>: + AsMut<[[u8; T::ARRAY_SIZE]]> +where + [(); T::ARRAY_SIZE]: Sized +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs new file mode 100644 index 000000000..909997340 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -0,0 +1,30 @@ +#![feature(const_type_id)] +#![feature(generic_const_exprs)] +#![feature(core_intrinsics)] +#![allow(incomplete_features)] + +use std::any::TypeId; + +struct If<const B: bool>; +pub trait True {} +impl True for If<true> {} + +fn consume<T: 'static>(_val: T) +where + If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + //~^ overly complex generic constant +{ +} + +fn test<T: 'static>() +where + If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + //~^ overly complex generic constant +{ +} + +fn main() { + let a = (); + consume(0i32); + consume(a); +} diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr new file mode 100644 index 000000000..f13fd795d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -0,0 +1,24 @@ +error: overly complex generic constant + --> $DIR/issue-90318.rs:14:8 + | +LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | borrowing is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/issue-90318.rs:21:8 + | +LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | borrowing is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-90364.rs b/tests/ui/const-generics/issues/issue-90364.rs new file mode 100644 index 000000000..b11b07b50 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90364.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<T, const H: T>(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +where + [(); 1]:; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90364.stderr b/tests/ui/const-generics/issues/issue-90364.stderr new file mode 100644 index 000000000..e85bd136e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90364.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-90364.rs:4:28 + | +LL | pub struct Foo<T, const H: T>(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-90455.rs b/tests/ui/const-generics/issues/issue-90455.rs new file mode 100644 index 000000000..a580410cf --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90455.rs @@ -0,0 +1,12 @@ +#![feature(generic_const_exprs, adt_const_params)] +#![allow(incomplete_features)] + +struct FieldElement<const N: &'static str> { + n: [u64; num_limbs(N)], + //~^ ERROR unconstrained generic constant +} +const fn num_limbs(_: &str) -> usize { + 0 +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90455.stderr b/tests/ui/const-generics/issues/issue-90455.stderr new file mode 100644 index 000000000..724d7f42e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90455.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-90455.rs:5:8 + | +LL | n: [u64; num_limbs(N)], + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); num_limbs(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-92186.rs b/tests/ui/const-generics/issues/issue-92186.rs new file mode 100644 index 000000000..9ced4667d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-92186.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<const N: usize>; +pub trait Bar<T> {} + +impl<T> Bar<T> for Foo<{ 1 }> {} +impl<T> Bar<T> for Foo<{ 2 }> {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-96654.rs b/tests/ui/const-generics/issues/issue-96654.rs new file mode 100644 index 000000000..8cf786dbe --- /dev/null +++ b/tests/ui/const-generics/issues/issue-96654.rs @@ -0,0 +1,15 @@ +// check-pass + +struct A<const M: u32> {} + +struct B<const M: u32> {} + +impl<const M: u32> B<M> { + const M: u32 = M; +} + +struct C<const M: u32> { + a: A<{ B::<1>::M }>, +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-97278.rs b/tests/ui/const-generics/issues/issue-97278.rs new file mode 100644 index 000000000..da0a9776f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97278.rs @@ -0,0 +1,14 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::sync::Arc; + +#[derive(PartialEq, Eq)] +enum Bar { + Bar(Arc<i32>) +} + +fn test<const BAR: Bar>() {} +//~^ ERROR `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]` + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-97278.stderr b/tests/ui/const-generics/issues/issue-97278.stderr new file mode 100644 index 000000000..ff13cb505 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97278.stderr @@ -0,0 +1,9 @@ +error[E0741]: `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-97278.rs:11:20 + | +LL | fn test<const BAR: Bar>() {} + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-97634.rs b/tests/ui/const-generics/issues/issue-97634.rs new file mode 100644 index 000000000..422e8de68 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97634.rs @@ -0,0 +1,10 @@ +// build-pass + +pub enum Register<const N: u16> { + Field0 = 40, + Field1, +} + +fn main() { + let _b = Register::<0>::Field1 as u16; +} diff --git a/tests/ui/const-generics/issues/issue-98629.rs b/tests/ui/const-generics/issues/issue-98629.rs new file mode 100644 index 000000000..1d2d3012a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-98629.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Trait { + const N: usize; +} + +impl const Trait for i32 {} +//~^ ERROR not all trait items implemented, missing: `N` + +fn f() +where + [(); <i32 as Trait>::N]:, +{} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-98629.stderr b/tests/ui/const-generics/issues/issue-98629.stderr new file mode 100644 index 000000000..4a248be76 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-98629.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `N` + --> $DIR/issue-98629.rs:8:1 + | +LL | const N: usize; + | -------------- `N` from trait +... +LL | impl const Trait for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing `N` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/issues/issue-99641.rs b/tests/ui/const-generics/issues/issue-99641.rs new file mode 100644 index 000000000..fae6d3fc4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-99641.rs @@ -0,0 +1,18 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +fn main() { + pub struct Color<const WHITE: (fn(),)>; + //~^ ERROR using function pointers + + impl<const WHITE: (fn(),)> Color<WHITE> { + //~^ ERROR using function pointers + pub fn new() -> Self { + Color::<WHITE> + } + } + + pub const D65: (fn(),) = (|| {},); + + Color::<D65>::new(); +} diff --git a/tests/ui/const-generics/issues/issue-99641.stderr b/tests/ui/const-generics/issues/issue-99641.stderr new file mode 100644 index 000000000..349ebba08 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-99641.stderr @@ -0,0 +1,15 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-99641.rs:5:35 + | +LL | pub struct Color<const WHITE: (fn(),)>; + | ^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-99641.rs:8:23 + | +LL | impl<const WHITE: (fn(),)> Color<WHITE> { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/late-bound-vars/in_closure.rs b/tests/ui/const-generics/late-bound-vars/in_closure.rs new file mode 100644 index 000000000..5294cc3b5 --- /dev/null +++ b/tests/ui/const-generics/late-bound-vars/in_closure.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _ = || { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; + }; +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/late-bound-vars/simple.rs b/tests/ui/const-generics/late-bound-vars/simple.rs new file mode 100644 index 000000000..6da5395ef --- /dev/null +++ b/tests/ui/const-generics/late-bound-vars/simple.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/legacy-const-generics-bad.rs b/tests/ui/const-generics/legacy-const-generics-bad.rs new file mode 100644 index 000000000..538eee337 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics-bad.rs @@ -0,0 +1,16 @@ +// aux-build:legacy-const-generics.rs + +extern crate legacy_const_generics; + +fn foo<const N: usize>() { + let a = 1; + legacy_const_generics::foo(0, a, 2); + //~^ ERROR attempt to use a non-constant value in a constant + + legacy_const_generics::foo(0, N, 2); + + legacy_const_generics::foo(0, N + 1, 2); + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/legacy-const-generics-bad.stderr b/tests/ui/const-generics/legacy-const-generics-bad.stderr new file mode 100644 index 000000000..3c78dd6c7 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics-bad.stderr @@ -0,0 +1,20 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/legacy-const-generics-bad.rs:7:35 + | +LL | let a = 1; + | ----- help: consider using `const` instead of `let`: `const a` +LL | legacy_const_generics::foo(0, a, 2); + | ^ non-constant value + +error: generic parameters may not be used in const operations + --> $DIR/legacy-const-generics-bad.rs:12:35 + | +LL | legacy_const_generics::foo(0, N + 1, 2); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/const-generics/legacy-const-generics.rs b/tests/ui/const-generics/legacy-const-generics.rs new file mode 100644 index 000000000..9abc72d98 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics.rs @@ -0,0 +1,18 @@ +// aux-build:legacy-const-generics.rs +// run-pass + +#![feature(rustc_attrs)] + +extern crate legacy_const_generics; + +#[rustc_legacy_const_generics(1)] +pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] { + [x, Y, z] +} + +fn main() { + assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]); + assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]); + // FIXME: Only works cross-crate + //assert_eq!(bar(0, 1, 2), [0, 1, 2]); +} diff --git a/tests/ui/const-generics/min_const_generics/assoc_const.rs b/tests/ui/const-generics/min_const_generics/assoc_const.rs new file mode 100644 index 000000000..27e971b5b --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/assoc_const.rs @@ -0,0 +1,16 @@ +// check-pass +struct Foo<const N: usize>; + +impl<const N: usize> Foo<N> { + const VALUE: usize = N * 2; +} + +trait Bar { + const ASSOC: usize; +} + +impl<const N: usize> Bar for Foo<N> { + const ASSOC: usize = N * 3; +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.rs b/tests/ui/const-generics/min_const_generics/complex-expression.rs new file mode 100644 index 000000000..8e667aeba --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-expression.rs @@ -0,0 +1,48 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +use std::mem::size_of; + +fn test<const N: usize>() {} + +fn ok<const M: usize>() -> [u8; M] { + [0; { M }] +} + +struct Break0<const N: usize>([u8; { N + 1 }]); +//~^ ERROR generic parameters may not be used in const operations + +struct Break1<const N: usize>([u8; { { N } }]); +//~^ ERROR generic parameters may not be used in const operations + +fn break2<const N: usize>() { + let _: [u8; N + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn break3<const N: usize>() { + let _ = [0; N + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]); +//~^ ERROR generic parameters may not be used in const operations + +struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]); +//~^ ERROR generic parameters may not be used in const operations + +fn break_ty2<T>() { + let _: [u8; size_of::<*mut T>() + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn break_ty3<T>() { + let _ = [0; size_of::<*mut T>() + 1]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + + +trait Foo { + const ASSOC: usize; +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.stderr b/tests/ui/const-generics/min_const_generics/complex-expression.stderr new file mode 100644 index 000000000..deabd05a6 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-expression.stderr @@ -0,0 +1,75 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:10:38 + | +LL | struct Break0<const N: usize>([u8; { N + 1 }]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:13:40 + | +LL | struct Break1<const N: usize>([u8; { { N } }]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:17:17 + | +LL | let _: [u8; N + 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:22:17 + | +LL | let _ = [0; N + 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:26:45 + | +LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:29:47 + | +LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:33:32 + | +LL | let _: [u8; size_of::<*mut T>() + 1]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/complex-expression.rs:38:17 + | +LL | let _ = [0; size_of::<*mut T>() + 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted + diff --git a/tests/ui/const-generics/min_const_generics/complex-types.rs b/tests/ui/const-generics/min_const_generics/complex-types.rs new file mode 100644 index 000000000..057bd5af8 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-types.rs @@ -0,0 +1,27 @@ +#![feature(never_type)] + +struct Foo<const N: [u8; 0]>; +//~^ ERROR `[u8; 0]` is forbidden + +struct Bar<const N: ()>; +//~^ ERROR `()` is forbidden +#[derive(PartialEq, Eq)] +struct No; + +struct Fez<const N: No>; +//~^ ERROR `No` is forbidden + +struct Faz<const N: &'static u8>; +//~^ ERROR `&'static u8` is forbidden + +struct Fiz<const N: !>; +//~^ ERROR `!` is forbidden + +enum Goo<const N: ()> { A, B } +//~^ ERROR `()` is forbidden + +union Boo<const N: ()> { a: () } +//~^ ERROR `()` is forbidden + + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr new file mode 100644 index 000000000..4ddbadb54 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr @@ -0,0 +1,65 @@ +error: `[u8; 0]` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:3:21 + | +LL | struct Foo<const N: [u8; 0]>; + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:6:21 + | +LL | struct Bar<const N: ()>; + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `No` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:11:21 + | +LL | struct Fez<const N: No>; + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:14:21 + | +LL | struct Faz<const N: &'static u8>; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `!` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:17:21 + | +LL | struct Fiz<const N: !>; + | ^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:20:19 + | +LL | enum Goo<const N: ()> { A, B } + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:23:20 + | +LL | union Boo<const N: ()> { a: () } + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs new file mode 100644 index 000000000..e9d868093 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs @@ -0,0 +1,35 @@ +// check-pass +// compile-flags: -Zdeduplicate-diagnostics=yes +#![allow(dead_code)] + +fn foo<T>() { + [0; std::mem::size_of::<*mut T>()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +struct Foo<T>(T); + +impl<T> Foo<T> { + const ASSOC: usize = 4; + + fn test() { + let _ = [0; Self::ASSOC]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out + } +} + +struct Bar<const N: usize>; + +impl<const N: usize> Bar<N> { + const ASSOC: usize = 4; + + fn test() { + let _ = [0; Self::ASSOC]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr new file mode 100644 index 000000000..8003dfa40 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr @@ -0,0 +1,30 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:6:9 + | +LL | [0; std::mem::size_of::<*mut T>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:17:21 + | +LL | let _ = [0; Self::ASSOC]; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:29:21 + | +LL | let _ = [0; Self::ASSOC]; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + +warning: 3 warnings emitted + diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs new file mode 100644 index 000000000..fac3777cf --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs @@ -0,0 +1,47 @@ +fn foo<const C: usize>() {} + +const BAR: usize = 42; + +fn a() { + foo<BAR + 3>(); //~ ERROR comparison operators cannot be chained +} +fn b() { + foo<BAR + BAR>(); //~ ERROR comparison operators cannot be chained +} +fn c() { + foo<3 + 3>(); //~ ERROR comparison operators cannot be chained +} +fn d() { + foo<BAR - 3>(); //~ ERROR comparison operators cannot be chained +} +fn e() { + foo<BAR - BAR>(); //~ ERROR comparison operators cannot be chained +} +fn f() { + foo<100 - BAR>(); //~ ERROR comparison operators cannot be chained +} +fn g() { + foo<bar<i32>()>(); //~ ERROR comparison operators cannot be chained + //~^ ERROR expected one of `;` or `}`, found `>` +} +fn h() { + foo<bar::<i32>()>(); //~ ERROR comparison operators cannot be chained +} +fn i() { + foo<bar::<i32>() + BAR>(); //~ ERROR comparison operators cannot be chained +} +fn j() { + foo<bar::<i32>() - BAR>(); //~ ERROR comparison operators cannot be chained +} +fn k() { + foo<BAR - bar::<i32>()>(); //~ ERROR comparison operators cannot be chained +} +fn l() { + foo<BAR - bar::<i32>()>(); //~ ERROR comparison operators cannot be chained +} + +const fn bar<const C: usize>() -> usize { + C +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr new file mode 100644 index 000000000..a6825b845 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr @@ -0,0 +1,140 @@ +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:6:8 + | +LL | foo<BAR + 3>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR + 3>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:9:8 + | +LL | foo<BAR + BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR + BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:12:8 + | +LL | foo<3 + 3>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<3 + 3>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:15:8 + | +LL | foo<BAR - 3>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR - 3>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:18:8 + | +LL | foo<BAR - BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR - BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:21:8 + | +LL | foo<100 - BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<100 - BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:8 + | +LL | foo<bar<i32>()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<bar<i32>()>(); + | ++ + +error: expected one of `;` or `}`, found `>` + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:19 + | +LL | foo<bar<i32>()>(); + | ^ expected one of `;` or `}` + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:28:8 + | +LL | foo<bar::<i32>()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<bar::<i32>()>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:31:8 + | +LL | foo<bar::<i32>() + BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<bar::<i32>() + BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:34:8 + | +LL | foo<bar::<i32>() - BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<bar::<i32>() - BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:37:8 + | +LL | foo<BAR - bar::<i32>()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR - bar::<i32>()>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:40:8 + | +LL | foo<BAR - bar::<i32>()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<BAR - bar::<i32>()>(); + | ++ + +error: aborting due to 13 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs new file mode 100644 index 000000000..e12e07a28 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs @@ -0,0 +1,51 @@ +fn foo<const C: usize>() {} + +const BAR: usize = 42; + +fn a() { + foo::<BAR + 3>(); //~ ERROR expected one of +} +fn b() { + // FIXME(const_generics): these diagnostics are awful, because trait objects without `dyn` were + // a terrible mistake. + foo::<BAR + BAR>(); + //~^ ERROR expected trait, found constant `BAR` + //~| ERROR expected trait, found constant `BAR` + //~| ERROR type provided when a constant was expected +} +fn c() { + foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces +} +fn d() { + foo::<BAR - 3>(); //~ ERROR expected one of +} +fn e() { + foo::<BAR - BAR>(); //~ ERROR expected one of +} +fn f() { + foo::<100 - BAR>(); //~ ERROR expressions must be enclosed in braces +} +fn g() { + foo::<bar<i32>()>(); //~ ERROR expected one of +} +fn h() { + foo::<bar::<i32>()>(); //~ ERROR expected one of +} +fn i() { + foo::<bar::<i32>() + BAR>(); //~ ERROR expected one of +} +fn j() { + foo::<bar::<i32>() - BAR>(); //~ ERROR expected one of +} +fn k() { + foo::<BAR - bar::<i32>()>(); //~ ERROR expected one of +} +fn l() { + foo::<BAR - bar::<i32>()>(); //~ ERROR expected one of +} + +const fn bar<const C: usize>() -> usize { + C +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr new file mode 100644 index 000000000..d9bcc523b --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr @@ -0,0 +1,143 @@ +error: expected one of `,` or `>`, found `3` + --> $DIR/const-expression-suggest-missing-braces.rs:6:17 + | +LL | foo::<BAR + 3>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR + 3 }>(); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-suggest-missing-braces.rs:17:11 + | +LL | foo::<3 + 3>(); + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | foo::<{ 3 + 3 }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:20:15 + | +LL | foo::<BAR - 3>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - 3 }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:23:15 + | +LL | foo::<BAR - BAR>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - BAR }>(); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-suggest-missing-braces.rs:26:11 + | +LL | foo::<100 - BAR>(); + | ^^^^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | foo::<{ 100 - BAR }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:29:19 + | +LL | foo::<bar<i32>()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar<i32>() }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:32:21 + | +LL | foo::<bar::<i32>()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::<i32>() }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:35:21 + | +LL | foo::<bar::<i32>() + BAR>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::<i32>() + BAR }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:38:21 + | +LL | foo::<bar::<i32>() - BAR>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::<i32>() - BAR }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:41:15 + | +LL | foo::<BAR - bar::<i32>()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - bar::<i32>() }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:44:15 + | +LL | foo::<BAR - bar::<i32>()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - bar::<i32>() }>(); + | + + + +error[E0404]: expected trait, found constant `BAR` + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 + | +LL | foo::<BAR + BAR>(); + | ^^^ not a trait + +error[E0404]: expected trait, found constant `BAR` + --> $DIR/const-expression-suggest-missing-braces.rs:11:17 + | +LL | foo::<BAR + BAR>(); + | ^^^ not a trait + +error[E0747]: type provided when a constant was expected + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 + | +LL | foo::<BAR + BAR>(); + | ^^^^^^^^^ + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0404, E0747. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/const-generics/min_const_generics/const_default_first.rs b/tests/ui/const-generics/min_const_generics/const_default_first.rs new file mode 100644 index 000000000..eafafb8a2 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_default_first.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] +#![allow(dead_code)] + +struct Both<const N: usize=3, T> { +//~^ ERROR: generic parameters with a default must be + v: T +} diff --git a/tests/ui/const-generics/min_const_generics/const_default_first.stderr b/tests/ui/const-generics/min_const_generics/const_default_first.stderr new file mode 100644 index 000000000..0d5a393cb --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_default_first.stderr @@ -0,0 +1,8 @@ +error: generic parameters with a default must be trailing + --> $DIR/const_default_first.rs:4:19 + | +LL | struct Both<const N: usize=3, T> { + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs b/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs new file mode 100644 index 000000000..0c10af6c4 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs @@ -0,0 +1,15 @@ +// run-pass + +const fn identity<const T: u32>() -> u32 { T } + +#[derive(Eq, PartialEq, Debug)] +pub struct ConstU32<const U: u32>; + +pub fn new() -> ConstU32<{ identity::<3>() }> { + ConstU32::<{ identity::<3>() }> +} + +fn main() { + let v = new(); + assert_eq!(v, ConstU32::<3>); +} diff --git a/tests/ui/const-generics/min_const_generics/default_function_param.rs b/tests/ui/const-generics/min_const_generics/default_function_param.rs new file mode 100644 index 000000000..92d495ef6 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_function_param.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +fn foo<const SIZE: usize = 5usize>() {} +//~^ ERROR defaults for const parameters are diff --git a/tests/ui/const-generics/min_const_generics/default_function_param.stderr b/tests/ui/const-generics/min_const_generics/default_function_param.stderr new file mode 100644 index 000000000..dedad2880 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_function_param.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_function_param.rs:3:8 + | +LL | fn foo<const SIZE: usize = 5usize>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/default_trait_param.rs b/tests/ui/const-generics/min_const_generics/default_trait_param.rs new file mode 100644 index 000000000..9cd5e3279 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_trait_param.rs @@ -0,0 +1,4 @@ +// check-pass +trait Foo<const KIND: bool = true> {} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs new file mode 100644 index 000000000..6215b7d93 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs @@ -0,0 +1,25 @@ +// This test checks that non-static lifetimes are prohibited under `min_const_generics`. It +// currently emits an error with `min_const_generics`. + +fn test<const N: usize>() {} + +fn issue_75323_and_74447_1<'a>() -> &'a () { + test::<{ let _: &'a (); 3 },>(); + //~^ ERROR a non-static lifetime is not allowed in a `const` + &() +} + +fn issue_75323_and_74447_2() { + test::<{ let _: &(); 3 },>(); +} + +fn issue_75323_and_74447_3() { + test::<{ let _: &'static (); 3 },>(); +} + +fn issue_73375<'a>() { + [(); (|_: &'a u8| (), 0).1]; + //~^ ERROR a non-static lifetime is not allowed in a `const` +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr new file mode 100644 index 000000000..5f641b070 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/forbid-non-static-lifetimes.rs:7:22 + | +LL | test::<{ let _: &'a (); 3 },>(); + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/forbid-non-static-lifetimes.rs:21:16 + | +LL | [(); (|_: &'a u8| (), 0).1]; + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs new file mode 100644 index 000000000..e1cf7b579 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs @@ -0,0 +1,15 @@ +trait AlwaysApplicable { + type Assoc; +} +impl<T: ?Sized> AlwaysApplicable for T { + type Assoc = usize; +} + +trait BindsParam<T> { + type ArrayTy; +} +impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc { + type ArrayTy = [u8; Self::MAX]; //~ ERROR generic `Self` types +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr new file mode 100644 index 000000000..bda885970 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/forbid-self-no-normalize.rs:12:25 + | +LL | type ArrayTy = [u8; Self::MAX]; + | ^^^^ + | +note: not a concrete type + --> $DIR/forbid-self-no-normalize.rs:11:27 + | +LL | impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/inferred_const.rs b/tests/ui/const-generics/min_const_generics/inferred_const.rs new file mode 100644 index 000000000..57d694158 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/inferred_const.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer)] +// run-pass + +fn foo<const N: usize, const K: usize>(_data: [u32; N]) -> [u32; K] { + [0; K] +} +fn main() { + let _a = foo::<_, 2>([0, 1, 2]); +} diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr new file mode 100644 index 000000000..be92429e3 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:29:21 + | +LL | get_flag::<false, 0xFF>(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:38:32 + | +LL | get_flag::<false, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:41:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:43:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:43:58 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr new file mode 100644 index 000000000..be92429e3 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:29:21 + | +LL | get_flag::<false, 0xFF>(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:38:32 + | +LL | get_flag::<false, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:41:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:43:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:43:58 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.rs b/tests/ui/const-generics/min_const_generics/invalid-patterns.rs new file mode 100644 index 000000000..13b2cca2f --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.rs @@ -0,0 +1,47 @@ +// stderr-per-bitwidth +use std::mem::transmute; + +fn get_flag<const FlagSet: bool, const ShortName: char>() -> Option<char> { + if FlagSet { + Some(ShortName) + } else { + None + } +} + +union CharRaw { + byte: u8, + character: char, +} + +union BoolRaw { + byte: u8, + boolean: bool, +} + +const char_raw: CharRaw = CharRaw { byte: 0xFF }; +const bool_raw: BoolRaw = BoolRaw { byte: 0x42 }; + +fn main() { + // Test that basic cases don't work + assert!(get_flag::<true, 'c'>().is_some()); + assert!(get_flag::<false, 'x'>().is_none()); + get_flag::<false, 0xFF>(); + //~^ ERROR mismatched types + get_flag::<7, 'c'>(); + //~^ ERROR mismatched types + get_flag::<42, 0x5ad>(); + //~^ ERROR mismatched types + //~| ERROR mismatched types + + + get_flag::<false, { unsafe { char_raw.character } }>(); + //~^ ERROR evaluation of constant value failed + //~| uninitialized + get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + //~^ ERROR it is undefined behavior + get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + //~^ ERROR evaluation of constant value failed + //~| uninitialized + //~| ERROR it is undefined behavior +} diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.rs b/tests/ui/const-generics/min_const_generics/macro-fail.rs new file mode 100644 index 000000000..7fb69032e --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro-fail.rs @@ -0,0 +1,39 @@ +struct Example<const N: usize>; + +macro_rules! external_macro { + () => {{ + //~^ ERROR expected type + const X: usize = 1337; + X + }} +} + +trait Marker<const N: usize> {} +impl<const N: usize> Marker<N> for Example<N> {} + +fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + //~^ ERROR: type provided when a constant was expected + Example::<gimme_a_const!(marker)> +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} }; inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + //~^ ERROR expected type + //~| ERROR expected type + }; + gimme_a_const!(run) + }>; + + let _fail = Example::<external_macro!()>; + + let _fail = Example::<gimme_a_const!()>; + //~^ ERROR unexpected end of macro invocation +} diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr new file mode 100644 index 000000000..9f73b91aa --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr @@ -0,0 +1,71 @@ +error: expected type, found `{` + --> $DIR/macro-fail.rs:28:27 + | +LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:28:27 + | +LL | Example::<gimme_a_const!(marker)> + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:4:10 + | +LL | () => {{ + | __________^ +LL | | +LL | | const X: usize = 1337; +LL | | X +LL | | }} + | |___^ expected type +... +LL | let _fail = Example::<external_macro!()>; + | ----------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation + | + = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected end of macro invocation + --> $DIR/macro-fail.rs:37:25 + | +LL | macro_rules! gimme_a_const { + | -------------------------- when calling this macro +... +LL | let _fail = Example::<gimme_a_const!()>; + | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$rusty:ident` + --> $DIR/macro-fail.rs:28:8 + | +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^ + +error[E0747]: type provided when a constant was expected + --> $DIR/macro-fail.rs:14:33 + | +LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/min_const_generics/macro.rs b/tests/ui/const-generics/min_const_generics/macro.rs new file mode 100644 index 000000000..9b63f7698 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro.rs @@ -0,0 +1,55 @@ +// run-pass +struct Example<const N: usize>; + +macro_rules! external_macro { + () => {{ + const X: usize = 1337; + X + }} +} + +trait Marker<const N: usize> {} +impl<const N: usize> Marker<N> for Example<N> {} + +fn make_marker() -> impl Marker<{ + #[macro_export] + macro_rules! const_macro { () => {{ 3 }} } inline!() +}> { + Example::<{ const_macro!() }> +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} } inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + } + gimme_a_const!(run) + }>; + + let _ok = Example::<{ external_macro!() }>; + + let _ok: [_; gimme_a_const!(blah)] = [0,0,0]; + let _ok: [[u8; gimme_a_const!(blah)]; gimme_a_const!(blah)]; + let _ok: [u8; gimme_a_const!(blah)]; + + let _ok: [u8; { + #[macro_export] + macro_rules! const_two { () => {{ 2 }} } + const_two!() + }]; + + let _ok = [0; { + #[macro_export] + macro_rules! const_three { () => {{ 3 }} } + const_three!() + }]; + let _ok = [0; const_three!()]; + + from_marker(make_marker()); +} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs new file mode 100644 index 000000000..9ef619365 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs @@ -0,0 +1,25 @@ +trait Foo { + fn t1() -> [u8; std::mem::size_of::<Self>()]; //~ERROR generic parameters +} + +struct Bar<T>(T); + +impl Bar<u8> { + fn t2() -> [u8; std::mem::size_of::<Self>()] { todo!() } // ok +} + +impl<T> Bar<T> { + fn t3() -> [u8; std::mem::size_of::<Self>()] {} //~ERROR generic `Self` +} + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; // ok + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr new file mode 100644 index 000000000..16a7687c0 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -0,0 +1,23 @@ +error: generic parameters may not be used in const operations + --> $DIR/self-ty-in-const-1.rs:2:41 + | +LL | fn t1() -> [u8; std::mem::size_of::<Self>()]; + | ^^^^ cannot perform const operation using `Self` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-1.rs:12:41 + | +LL | fn t3() -> [u8; std::mem::size_of::<Self>()] {} + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-1.rs:11:9 + | +LL | impl<T> Bar<T> { + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs new file mode 100644 index 000000000..286ec2d24 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs @@ -0,0 +1,19 @@ +struct Bar<T>(T); + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; // ok + } +} + +impl<T> Baz for Bar<T> { + fn hey() { + let _: [u8; std::mem::size_of::<Self>()]; //~ERROR generic `Self` + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr new file mode 100644 index 000000000..41546292c --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-2.rs:15:41 + | +LL | let _: [u8; std::mem::size_of::<Self>()]; + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-2.rs:13:17 + | +LL | impl<T> Baz for Bar<T> { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs new file mode 100644 index 000000000..fa119c59f --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] + +struct Both<T=u32, const N: usize=3> { + arr: [T; N] +} + +trait BothTrait<T=u32, const N: usize=3> {} + +enum BothEnum<T=u32, const N: usize=3> { + Dummy([T; N]) +} + +struct OppOrder<const N: usize=3, T=u32> { + arr: [T; N] +} + +fn main() { + let _ = OppOrder::<3, u32> { + arr: [0,0,0], + }; + let _ = Both::<u8, 1> { + arr: [0], + }; +} diff --git a/tests/ui/const-generics/nested-type.full.stderr b/tests/ui/const-generics/nested-type.full.stderr new file mode 100644 index 000000000..6d9f44065 --- /dev/null +++ b/tests/ui/const-generics/nested-type.full.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants + --> $DIR/nested-type.rs:15:5 + | +LL | Foo::<17>::value() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr new file mode 100644 index 000000000..cff02b0d4 --- /dev/null +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -0,0 +1,28 @@ +error: `[u8; { + struct Foo<const N: usize>; + + impl<const N: usize> Foo<N> { + fn value() -> usize { + N + } + } + + Foo::<17>::value() + }]` is forbidden as the type of a const generic parameter + --> $DIR/nested-type.rs:6:21 + | +LL | struct Foo<const N: [u8; { + | _____________________^ +LL | | struct Foo<const N: usize>; +LL | | +LL | | impl<const N: usize> Foo<N> { +... | +LL | | +LL | | }]>; + | |__^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/nested-type.rs b/tests/ui/const-generics/nested-type.rs new file mode 100644 index 000000000..742340f43 --- /dev/null +++ b/tests/ui/const-generics/nested-type.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden + struct Foo<const N: usize>; + + impl<const N: usize> Foo<N> { + fn value() -> usize { + N + } + } + + Foo::<17>::value() + //[full]~^ ERROR cannot call non-const fn +}]>; + +fn main() {} diff --git a/tests/ui/const-generics/occurs-check/bind-param.rs b/tests/ui/const-generics/occurs-check/bind-param.rs new file mode 100644 index 000000000..ee4244051 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/bind-param.rs @@ -0,0 +1,17 @@ +// build-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test does not use any "unevaluated" consts, so it should compile just fine. + +fn bind<const N: usize>(value: [u8; N]) -> [u8; N] { + todo!() +} + +fn sink(_: [u8; 5]) {} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); + sink(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.rs b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs new file mode 100644 index 000000000..e6f8e4ad3 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete + + +fn bind<const N: usize>(value: [u8; N + 2]) -> [u8; N * 2] { + todo!() +} + +fn main() { + let mut arr = Default::default(); + arr = bind::<2>(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr b/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr new file mode 100644 index 000000000..fe3f24a67 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unify-fixpoint.rs:2:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs b/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs new file mode 100644 index 000000000..c6324bca1 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs @@ -0,0 +1,16 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test would tries to unify `N` with `N + 1` which must fail the occurs check. + +fn bind<const N: usize>(value: [u8; N]) -> [u8; N + 1] { + todo!() +} + +fn sink(_: [u8; 5]) {} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); //~ ERROR mismatched types + sink(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr new file mode 100644 index 000000000..6b8e688fb --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unify-n-nplusone.rs:14:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.rs b/tests/ui/const-generics/occurs-check/unused-substs-1.rs new file mode 100644 index 000000000..9d12250c9 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.rs @@ -0,0 +1,13 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Bar<const M: usize> {} +impl<const N: usize> Bar<N> for A<{ 6 + 1 }> {} + +struct A<const N: usize> +where + A<N>: Bar<N>; + +fn main() { + let _ = A; //~ERROR the trait bound +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr new file mode 100644 index 000000000..a3c011d92 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied + --> $DIR/unused-substs-1.rs:12:13 + | +LL | let _ = A; + | ^ the trait `Bar<_>` is not implemented for `A<_>` + | + = help: the trait `Bar<N>` is implemented for `A<7>` +note: required by a bound in `A` + --> $DIR/unused-substs-1.rs:9:11 + | +LL | struct A<const N: usize> + | - required by a bound in this +LL | where +LL | A<N>: Bar<N>; + | ^^^^^^ required by this bound in `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.rs b/tests/ui/const-generics/occurs-check/unused-substs-2.rs new file mode 100644 index 000000000..9b1212694 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.rs @@ -0,0 +1,28 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// +// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty<ct>` we introduced an +// artificial inference cycle. +struct Foo<const N: usize>; + +trait Bind<T> { + fn bind() -> (T, Self); +} + +// `N` has to be `ConstKind::Unevaluated`. +impl<T> Bind<T> for Foo<{ 6 + 1 }> { + fn bind() -> (T, Self) { + (panic!(), Foo) + } +} + +fn main() { + let (mut t, foo) = Foo::bind(); + // `t` is `ty::Infer(TyVar(_#1t))` + // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr new file mode 100644 index 000000000..9532fc21a --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-2.rs:25:9 + | +LL | t = foo; + | ^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.rs b/tests/ui/const-generics/occurs-check/unused-substs-3.rs new file mode 100644 index 000000000..d5aeab47e --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// +// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty<ct>` we introduced an +// artificial inference cycle. +fn bind<T>() -> (T, [u8; 6 + 1]) { + todo!() +} + +fn main() { + let (mut t, foo) = bind(); + // `t` is `ty::Infer(TyVar(_#1t))` + // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr new file mode 100644 index 000000000..fd8f8b269 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-3.rs:16:9 + | +LL | t = foo; + | ^^^- help: try using a conversion method: `.to_vec()` + | | + | cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-4.rs b/tests/ui/const-generics/occurs-check/unused-substs-4.rs new file mode 100644 index 000000000..03c2f5486 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-4.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] { + todo!() +} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); //~ ERROR mismatched type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-4.stderr b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr new file mode 100644 index 000000000..5685eedbd --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-4.rs:10:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.rs b/tests/ui/const-generics/occurs-check/unused-substs-5.rs new file mode 100644 index 000000000..383ab4cd8 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// `N + 1` also depends on `T` here even if it doesn't use it. +fn q<T, const N: usize>(_: T) -> [u8; N + 1] { + todo!() +} + +fn supplier<T>() -> T { + todo!() +} + +fn catch_me<const N: usize>() where [u8; N + 1]: Default { + let mut x = supplier(); + x = q::<_, N>(x); //~ ERROR mismatched types +} + +fn main() { + catch_me::<3>(); +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr new file mode 100644 index 000000000..be289f44f --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-5.rs:15:9 + | +LL | x = q::<_, N>(x); + | ^^^^^^^^^^^^- help: try using a conversion method: `.to_vec()` + | | + | cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs new file mode 100644 index 000000000..3018439af --- /dev/null +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs @@ -0,0 +1,10 @@ +struct Foo< + 'a, + const N: usize = { + let x: &'a (); + //~^ ERROR use of non-static lifetime `'a` in const generic + 3 + }, +>(&'a ()); + +fn main() {} diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr new file mode 100644 index 000000000..9d9555d3f --- /dev/null +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr @@ -0,0 +1,11 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/outer-lifetime-in-const-generic-default.rs:4:17 + | +LL | let x: &'a (); + | ^^ + | + = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/overlapping_impls.rs b/tests/ui/const-generics/overlapping_impls.rs new file mode 100644 index 000000000..e599eadd8 --- /dev/null +++ b/tests/ui/const-generics/overlapping_impls.rs @@ -0,0 +1,36 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] +use std::marker::PhantomData; + +struct Foo<const I: i32, const J: i32> {} + +const ONE: i32 = 1; +const TWO: i32 = 2; + +impl<const I: i32> Foo<I, ONE> { + pub fn foo() {} +} + +impl<const I: i32> Foo<I, TWO> { + pub fn foo() {} +} + + +pub struct Foo2<const P: Protocol, T> { + _marker: PhantomData<T>, +} + +#[derive(PartialEq, Eq)] +pub enum Protocol { + Variant1, + Variant2, +} + +pub trait Bar {} + +impl<T> Bar for Foo2<{ Protocol::Variant1 }, T> {} +impl<T> Bar for Foo2<{ Protocol::Variant2 }, T> {} + +fn main() {} diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr new file mode 100644 index 000000000..9f0b2efae --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -0,0 +1,15 @@ +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 + | +LL | struct Bar<T = [u8; N], const N: usize>(T); + | ^ + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 + | +LL | struct Bar<T = [u8; N], const N: usize>(T); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr new file mode 100644 index 000000000..a5e70f6b9 --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -0,0 +1,24 @@ +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 + | +LL | struct Bar<T = [u8; N], const N: usize>(T); + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 + | +LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 + | +LL | struct Bar<T = [u8; N], const N: usize>(T); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs new file mode 100644 index 000000000..b24a7afab --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -0,0 +1,12 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); +//[min]~^ ERROR generic parameters may not be used in const operations + +struct Bar<T = [u8; N], const N: usize>(T); +//~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR generic parameters with a default + +fn main() {} diff --git a/tests/ui/const-generics/parent_generics_of_encoding.rs b/tests/ui/const-generics/parent_generics_of_encoding.rs new file mode 100644 index 000000000..b87e3960f --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding.rs @@ -0,0 +1,25 @@ +// aux-build:generics_of_parent.rs +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate generics_of_parent; + +use generics_of_parent::{Foo, S}; + +fn main() { + // regression test for #87603 + const N: usize = 2; + let x: S<u8, N> = S::test(); +} + +// regression test for #87674 +fn new<U>(a: U) -> U { + a +} +fn foo<const N: usize>(bar: &mut Foo<N>) +where + [(); N + 1]: , +{ + *bar = new(loop {}); +} diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs new file mode 100644 index 000000000..7a78e0f10 --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs @@ -0,0 +1,11 @@ +// aux-build:generics_of_parent_impl_trait.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate generics_of_parent_impl_trait; + +fn main() { + // check for `impl Trait<{ const }>` which has a parent of a `DefKind::TyParam` + generics_of_parent_impl_trait::foo([()]); + //~^ error: type annotations needed +} diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr new file mode 100644 index 000000000..87ff7babe --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -0,0 +1,15 @@ +error[E0284]: type annotations needed + --> $DIR/parent_generics_of_encoding_impl_trait.rs:9:5 + | +LL | generics_of_parent_impl_trait::foo([()]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` + | +note: required by a bound in `foo` + --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:6:48 + | +LL | pub fn foo<const N: usize>(foo: impl Into<[(); N + 1]>) { + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs new file mode 100644 index 000000000..99d8e9dea --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs @@ -0,0 +1,16 @@ +trait Foo<const N: usize> { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo<const 3> for Bar { +//~^ERROR expected lifetime, type, or constant, found keyword `const` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr new file mode 100644 index 000000000..1de24bff4 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr @@ -0,0 +1,14 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013-no-assoc.rs:9:10 + | +LL | impl Foo<const 3> for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo<const 3> for Bar { +LL + impl Foo<3> for Bar { + | + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs new file mode 100644 index 000000000..b126b2485 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -0,0 +1,18 @@ +trait Foo<const N: usize> { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo<N = 3> for Bar { +//~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied +//~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr new file mode 100644 index 000000000..acfdde8e1 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -0,0 +1,35 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo<N = 3> for Bar { + | ^^^^^ + | + = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013-no-kw.rs:9:6 + | +LL | impl Foo<N = 3> for Bar { + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013-no-kw.rs:1:7 + | +LL | trait Foo<const N: usize> { + | ^^^ -------------- +help: add missing generic argument + | +LL | impl Foo<N, N = 3> for Bar { + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo<N = 3> for Bar { + | ^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0229, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs new file mode 100644 index 000000000..0ec6762b6 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs @@ -0,0 +1,16 @@ +trait Foo<const N: usize> { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo<N = type 3> for Bar { +//~^ERROR missing type to the right of `=` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr new file mode 100644 index 000000000..f0d0d90c7 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr @@ -0,0 +1,8 @@ +error: missing type to the right of `=` + --> $DIR/issue-89013-type.rs:9:13 + | +LL | impl Foo<N = type 3> for Bar { + | ^---- expected type, found keyword `type` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs new file mode 100644 index 000000000..9431779fa --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -0,0 +1,19 @@ +trait Foo<const N: usize> { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo<N = const 3> for Bar { +//~^ ERROR expected lifetime, type, or constant, found keyword `const` +//~| ERROR this trait takes 1 generic +//~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr new file mode 100644 index 000000000..583749a85 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -0,0 +1,47 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013.rs:9:14 + | +LL | impl Foo<N = const 3> for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo<N = const 3> for Bar { +LL + impl Foo<N = 3> for Bar { + | + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo<N = const 3> for Bar { + | ^^^^^^^^^^^ + | + = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013.rs:9:6 + | +LL | impl Foo<N = const 3> for Bar { + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013.rs:1:7 + | +LL | trait Foo<const N: usize> { + | ^^^ -------------- +help: add missing generic argument + | +LL | impl Foo<N, N = const 3> for Bar { + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo<N = const 3> for Bar { + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0229, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/projection-as-arg-const.rs b/tests/ui/const-generics/projection-as-arg-const.rs new file mode 100644 index 000000000..903548c75 --- /dev/null +++ b/tests/ui/const-generics/projection-as-arg-const.rs @@ -0,0 +1,20 @@ +// This is currently not possible to use projections as const generics. +// More information about this available here: +// https://github.com/rust-lang/rust/pull/104443#discussion_r1029375633 + +pub trait Identity { + type Identity; +} + +impl<T> Identity for T { + type Identity = Self; +} + +pub fn foo<const X: <i32 as Identity>::Identity>() { +//~^ ERROR + assert!(X == 12); +} + +fn main() { + foo::<12>(); +} diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr new file mode 100644 index 000000000..803ed9c95 --- /dev/null +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -0,0 +1,11 @@ +error: `<i32 as Identity>::Identity` is forbidden as the type of a const generic parameter + --> $DIR/projection-as-arg-const.rs:13:21 + | +LL | pub fn foo<const X: <i32 as Identity>::Identity>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/promotion.rs b/tests/ui/const-generics/promotion.rs new file mode 100644 index 000000000..ce9a1a0fe --- /dev/null +++ b/tests/ui/const-generics/promotion.rs @@ -0,0 +1,9 @@ +// run-pass +// tests that promoting expressions containing const parameters is allowed. +fn promotion_test<const N: usize>() -> &'static usize { + &(3 + N) +} + +fn main() { + assert_eq!(promotion_test::<13>(), &16); +} diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr new file mode 100644 index 000000000..657eee2be --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr @@ -0,0 +1,15 @@ +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:9:23 + | +LL | struct Const<const P: *const u32>; + | ^^^^^^^^^^ + +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:11:15 + | +LL | impl<const P: *const u32> Const<P> { + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr new file mode 100644 index 000000000..04bc46cb4 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -0,0 +1,14 @@ +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:9:23 + | +LL | struct Const<const P: *const u32>; + | ^^^^^^^^^^ + +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:11:15 + | +LL | impl<const P: *const u32> Const<P> { + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.rs b/tests/ui/const-generics/raw-ptr-const-param-deref.rs new file mode 100644 index 000000000..65595f07d --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.rs @@ -0,0 +1,21 @@ +// Checks that pointers must not be used as the type of const params. +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +const A: u32 = 3; + +struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters + +impl<const P: *const u32> Const<P> { //~ ERROR: using raw pointers as const generic parameters + fn get() -> u32 { + unsafe { + *P + } + } +} + +fn main() { + assert_eq!(Const::<{&A as *const _}>::get(), 3) +} diff --git a/tests/ui/const-generics/raw-ptr-const-param.full.stderr b/tests/ui/const-generics/raw-ptr-const-param.full.stderr new file mode 100644 index 000000000..69f1aae56 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:6:23 + | +LL | struct Const<const P: *const u32>; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr new file mode 100644 index 000000000..310422aaf --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -0,0 +1,8 @@ +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:6:23 + | +LL | struct Const<const P: *const u32>; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/raw-ptr-const-param.rs b/tests/ui/const-generics/raw-ptr-const-param.rs new file mode 100644 index 000000000..27ef9e7d9 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.rs @@ -0,0 +1,11 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters + +fn main() { + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; + let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; +} diff --git a/tests/ui/const-generics/slice-const-param-mismatch.full.stderr b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr new file mode 100644 index 000000000..80dd1be33 --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:14:35 + | +LL | let _: ConstString<"Hello"> = ConstString::<"World">; + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"` + | | + | expected due to this + | + = note: expected struct `ConstString<"Hello">` + found struct `ConstString<"World">` + +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:16:33 + | +LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"` + | | + | expected due to this + | + = note: expected struct `ConstString<"ℇ㇈↦">` + found struct `ConstString<"ℇ㇈↥">` + +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:18:33 + | +LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; + | ------------------ ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"` + | | + | expected due to this + | + = note: expected struct `ConstBytes<b"AAA">` + found struct `ConstBytes<b"BBB">` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr new file mode 100644 index 000000000..fed802f6a --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -0,0 +1,20 @@ +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/slice-const-param-mismatch.rs:7:29 + | +LL | struct ConstString<const T: &'static str>; + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static [u8]` is forbidden as the type of a const generic parameter + --> $DIR/slice-const-param-mismatch.rs:9:28 + | +LL | struct ConstBytes<const T: &'static [u8]>; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/slice-const-param-mismatch.rs b/tests/ui/const-generics/slice-const-param-mismatch.rs new file mode 100644 index 000000000..7127323e5 --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + + +struct ConstString<const T: &'static str>; +//[min]~^ ERROR +struct ConstBytes<const T: &'static [u8]>; +//[min]~^ ERROR + +pub fn main() { + let _: ConstString<"Hello"> = ConstString::<"Hello">; + let _: ConstString<"Hello"> = ConstString::<"World">; //[full]~ ERROR mismatched types + let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">; + let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //[full]~ ERROR mismatched types + let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>; + let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //[full]~ ERROR mismatched types +} diff --git a/tests/ui/const-generics/slice-const-param.rs b/tests/ui/const-generics/slice-const-param.rs new file mode 100644 index 000000000..05d21e08d --- /dev/null +++ b/tests/ui/const-generics/slice-const-param.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub fn function_with_str<const STRING: &'static str>() -> &'static str { + STRING +} + +pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_str::<"Rust">(), "Rust"); + assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦"); + assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA"); +} diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.rs b/tests/ui/const-generics/sneaky-array-repeat-expr.rs new file mode 100644 index 000000000..b147c246b --- /dev/null +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.rs @@ -0,0 +1,32 @@ +trait Trait<const N: usize> { + const Assoc: usize; +} + +impl<const N: usize> Trait<N> for () { + const Assoc: usize = 1; +} + + +pub const fn foo<const N: usize>() where (): Trait<N> { + let bar = [(); <()>::Assoc]; + //~^ error: constant expression depends on a generic parameter +} + +trait Trait2<const N: usize> { + const Assoc2: usize; +} + +impl<const N: usize> Trait2<N> for () { + const Assoc2: usize = N - 1; +} + + +pub const fn foo2<const N: usize>() where (): Trait2<N> { + let bar2 = [(); <()>::Assoc2]; + //~^ error: constant expression depends on a generic parameter +} + +fn main() { + foo::<0>(); + foo2::<0>(); +} diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr new file mode 100644 index 000000000..5c77375d3 --- /dev/null +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr @@ -0,0 +1,18 @@ +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:11:20 + | +LL | let bar = [(); <()>::Assoc]; + | ^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:25:21 + | +LL | let bar2 = [(); <()>::Assoc2]; + | ^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr new file mode 100644 index 000000000..d4b2ad6fd --- /dev/null +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -0,0 +1,56 @@ +error: `std::ops::Range<usize>` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:7:24 + | +LL | struct _Range<const R: std::ops::Range<usize>>; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:12:28 + | +LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeFull` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:17:28 + | +LL | struct _RangeFull<const R: std::ops::RangeFull>; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:23:33 + | +LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeTo<usize>` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:28:26 + | +LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:33:35 + | +LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs new file mode 100644 index 000000000..46c06f312 --- /dev/null +++ b/tests/ui/const-generics/std/const-generics-range.rs @@ -0,0 +1,37 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// `Range` should be usable within const generics: +struct _Range<const R: std::ops::Range<usize>>; +//[min]~^ ERROR `std::ops::Range<usize>` is forbidden +const RANGE : _Range<{ 0 .. 1000 }> = _Range; + +// `RangeFrom` should be usable within const generics: +struct _RangeFrom<const R: std::ops::RangeFrom<usize>>; +//[min]~^ ERROR `RangeFrom<usize>` is forbidden +const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom; + +// `RangeFull` should be usable within const generics: +struct _RangeFull<const R: std::ops::RangeFull>; +//[min]~^ ERROR `RangeFull` is forbidden +const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull; + +// Regression test for #70155 +// `RangeInclusive` should be usable within const generics: +struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>; +//[min]~^ ERROR `RangeInclusive<usize>` is forbidden +const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive; + +// `RangeTo` should be usable within const generics: +struct _RangeTo<const R: std::ops::RangeTo<usize>>; +//[min]~^ ERROR `RangeTo<usize>` is forbidden +const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo; + +// `RangeToInclusive` should be usable within const generics: +struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>; +//[min]~^ ERROR `RangeToInclusive<usize>` is forbidden +const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive; + +pub fn main() {} diff --git a/tests/ui/const-generics/struct-with-invalid-const-param.rs b/tests/ui/const-generics/struct-with-invalid-const-param.rs new file mode 100644 index 000000000..be1c4b0e8 --- /dev/null +++ b/tests/ui/const-generics/struct-with-invalid-const-param.rs @@ -0,0 +1,5 @@ +// Checks that a const param cannot be stored in a struct. + +struct S<const C: u8>(C); //~ ERROR expected type, found const parameter + +fn main() {} diff --git a/tests/ui/const-generics/struct-with-invalid-const-param.stderr b/tests/ui/const-generics/struct-with-invalid-const-param.stderr new file mode 100644 index 000000000..67f497af5 --- /dev/null +++ b/tests/ui/const-generics/struct-with-invalid-const-param.stderr @@ -0,0 +1,9 @@ +error[E0573]: expected type, found const parameter `C` + --> $DIR/struct-with-invalid-const-param.rs:3:23 + | +LL | struct S<const C: u8>(C); + | ^ not a type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/suggest_const_for_array.rs b/tests/ui/const-generics/suggest_const_for_array.rs new file mode 100644 index 000000000..f3e5a3186 --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +fn example<const N: usize>() {} + +fn other() { + example::<[usize; 3]>(); + //~^ ERROR type provided when a const + example::<[usize; 4+5]>(); + //~^ ERROR type provided when a const +} diff --git a/tests/ui/const-generics/suggest_const_for_array.stderr b/tests/ui/const-generics/suggest_const_for_array.stderr new file mode 100644 index 000000000..a617bf2bb --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.stderr @@ -0,0 +1,15 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:6:13 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:8:13 + | +LL | example::<[usize; 4+5]>(); + | ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/trait-const-args.rs b/tests/ui/const-generics/trait-const-args.rs new file mode 100644 index 000000000..2cdef3fb4 --- /dev/null +++ b/tests/ui/const-generics/trait-const-args.rs @@ -0,0 +1,27 @@ +// check-pass + +struct Const<const N: usize>; +trait Foo<const N: usize> {} + +impl<const N: usize> Foo<N> for Const<N> {} + +fn foo_impl(_: impl Foo<3>) {} + +fn foo_explicit<T: Foo<3>>(_: T) {} + +fn foo_where<T>(_: T) +where + T: Foo<3>, +{ +} + +fn main() { + foo_impl(Const); + foo_impl(Const::<3>); + + foo_explicit(Const); + foo_explicit(Const::<3>); + + foo_where(Const); + foo_where(Const::<3>); +} diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr new file mode 100644 index 000000000..039c4276c --- /dev/null +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -0,0 +1,11 @@ +error: `&'static ()` is forbidden as the type of a const generic parameter + --> $DIR/transmute-const-param-static-reference.rs:7:23 + | +LL | struct Const<const P: &'static ()>; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.rs b/tests/ui/const-generics/transmute-const-param-static-reference.rs new file mode 100644 index 000000000..6b443c8bd --- /dev/null +++ b/tests/ui/const-generics/transmute-const-param-static-reference.rs @@ -0,0 +1,16 @@ +// revisions: full min +//[full] check-pass + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const<const P: &'static ()>; +//[min]~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter + +fn main() { + const A: &'static () = unsafe { + std::mem::transmute(10 as *const ()) + }; + + let _ = Const::<{A}>; +} diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs new file mode 100644 index 000000000..926e807fe --- /dev/null +++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -0,0 +1,12 @@ +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::mem::MaybeUninit; + +#[repr(transparent)] +pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>); + +fn main() {} diff --git a/tests/ui/const-generics/try_unify_ignore_lifetimes.rs b/tests/ui/const-generics/try_unify_ignore_lifetimes.rs new file mode 100644 index 000000000..2ae0ae70d --- /dev/null +++ b/tests/ui/const-generics/try_unify_ignore_lifetimes.rs @@ -0,0 +1,33 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Num<const N: usize>; + +trait NumT { + const VALUE: usize; +} + +impl<const N: usize> NumT for Num<N> { + const VALUE: usize = N; +} + +struct Foo<'a, N: NumT>(&'a [u32; N::VALUE]) where [(); N::VALUE]:; + +trait Bar { + type Size: NumT; + + fn bar<'a>(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +trait Baz<'a> { + type Size: NumT; + + fn baz(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/two_matching_preds.rs b/tests/ui/const-generics/two_matching_preds.rs new file mode 100644 index 000000000..de608f73e --- /dev/null +++ b/tests/ui/const-generics/two_matching_preds.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const N: usize>() +where + [(); N + 1]:, + [(); N + 1]:, +{ + bar::<N>(); +} + +fn bar<const N: usize>() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/type-after-const-ok.rs b/tests/ui/const-generics/type-after-const-ok.rs new file mode 100644 index 000000000..f37b0b102 --- /dev/null +++ b/tests/ui/const-generics/type-after-const-ok.rs @@ -0,0 +1,6 @@ +// run-pass +// Verifies that having generic parameters after constants is permitted +#[allow(dead_code)] +struct A<const N: usize, T>(T); + +fn main() {} diff --git a/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs b/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs new file mode 100644 index 000000000..5dfcbba0e --- /dev/null +++ b/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs @@ -0,0 +1,33 @@ +pub struct Struct<const N: usize>(()); + +impl<const N: usize> Struct<N> { + pub fn new() -> Self { + Struct(()) + } + + pub fn same_ty<const M: usize>(&self) -> (usize, usize) { + (N, M) + } + + pub fn different_ty<const M: u8>(&self) -> (usize, u8) { + (N, M) + } + + pub fn containing_ty<T, const M: u8>(&self) -> (usize, u8) { + (std::mem::size_of::<T>() + N, M) + } + + pub fn we_have_to_go_deeper<const M: usize>(&self) -> Struct<M> { + Struct(()) + } +} + +pub trait Foo { + fn foo<const M: usize>(&self) -> usize; +} + +impl Foo for Struct<7> { + fn foo<const M: usize>(&self) -> usize { + M + } +} diff --git a/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs b/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs new file mode 100644 index 000000000..e84414834 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs @@ -0,0 +1,26 @@ +// run-pass +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + fn foo<const N: usize>(&self) -> usize { + let f = self; + f.bar::<{ + let f = Foo; + f.bar::<7>() + }>() + N + } + + const fn bar<const M: usize>(&self) -> usize { + M + } +} + +fn main() { + let f = Foo; + + assert_eq!(f.foo::<13>(), 20) +} diff --git a/tests/ui/const-generics/type-dependent/issue-61936.rs b/tests/ui/const-generics/type-dependent/issue-61936.rs new file mode 100644 index 000000000..7216b25f0 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-61936.rs @@ -0,0 +1,47 @@ +// run-pass + +trait SliceExt<T: Clone> { + fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>; +} + +impl <T: Clone> SliceExt<T> for [T] { + fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N> { + ArrayWindowsExample{ idx: 0, slice: &self } + } +} + +struct ArrayWindowsExample<'a, T, const N: usize> { + slice: &'a [T], + idx: usize, +} + +impl <'a, T: Clone, const N: usize> Iterator for ArrayWindowsExample<'a, T, N> { + type Item = [T; N]; + fn next(&mut self) -> Option<Self::Item> { + // Note: this is unsound for some `T` and not meant as an example + // on how to implement `ArrayWindows`. + let mut res = unsafe{ std::mem::zeroed() }; + let mut ptr = &mut res as *mut [T; N] as *mut T; + + for i in 0..N { + match self.slice[self.idx..].get(i) { + None => return None, + Some(elem) => unsafe { std::ptr::write_volatile(ptr, elem.clone())}, + }; + ptr = ptr.wrapping_add(1); + self.idx += 1; + } + + Some(res) + } +} + +const FOUR: usize = 4; + +fn main() { + let v: Vec<usize> = vec![0; 100]; + + for array in v.as_slice().array_windows_example::<FOUR>() { + assert_eq!(array, [0, 0, 0, 0]) + } +} diff --git a/tests/ui/const-generics/type-dependent/issue-63695.rs b/tests/ui/const-generics/type-dependent/issue-63695.rs new file mode 100644 index 000000000..08b6d4bf5 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-63695.rs @@ -0,0 +1,15 @@ +// run-pass + +trait T { + fn test<const A: i32>(&self) -> i32 { A } +} + +struct S(); + +impl T for S {} + +fn main() { + let foo = S(); + assert_eq!(foo.test::<8i32>(), 8); + assert_eq!(foo.test::<16i32>(), 16); +} diff --git a/tests/ui/const-generics/type-dependent/issue-67144-1.rs b/tests/ui/const-generics/type-dependent/issue-67144-1.rs new file mode 100644 index 000000000..27dd51de2 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-67144-1.rs @@ -0,0 +1,25 @@ +// check-pass +struct X; + +impl X { + pub fn getn<const N: usize>(&self) -> [u8; N] { + getn::<N>() + } +} + +fn getn<const N: usize>() -> [u8; N] { + unsafe { + std::mem::zeroed() + } +} + +fn main() { + // works + let [a,b,c] = getn::<3>(); + + // cannot pattern-match on an array without a fixed length + let [a,b,c] = X.getn::<3>(); + + // mismatched types, expected array `[u8; 3]` found array `[u8; _]` + let arr: [u8; 3] = X.getn::<3>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-67144-2.rs b/tests/ui/const-generics/type-dependent/issue-67144-2.rs new file mode 100644 index 000000000..b26f551eb --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-67144-2.rs @@ -0,0 +1,19 @@ +// check-pass +struct A<const N: usize>; + +struct X; + +impl X { + fn inner<const N: usize>() -> A<N> { + outer::<N>() + } +} + +fn outer<const N: usize>() -> A<N> { + A +} + +fn main() { + let i: A<3usize> = outer::<3usize>(); + let o: A<3usize> = X::inner::<3usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-69816.rs b/tests/ui/const-generics/type-dependent/issue-69816.rs new file mode 100644 index 000000000..cbb6b398e --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-69816.rs @@ -0,0 +1,17 @@ +// run-pass +trait IterExt: Sized + Iterator { + fn default_for_size<const N: usize>(self) -> [Self::Item; N] + where + [Self::Item; N]: Default, + { + Default::default() + } +} + +impl<T: Iterator> IterExt for T {} + +fn main(){ + const N: usize = 10; + let arr = (0u32..10).default_for_size::<N>(); + assert_eq!(arr, [0; 10]); +} diff --git a/tests/ui/const-generics/type-dependent/issue-70217.rs b/tests/ui/const-generics/type-dependent/issue-70217.rs new file mode 100644 index 000000000..933ca0276 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70217.rs @@ -0,0 +1,14 @@ +// check-pass + +struct Struct<const N: usize>; + +impl<const N: usize> Struct<N> { + fn method<const M: usize>(&self) {} +} + +fn test<const N: usize, const M: usize>(x: Struct<N>) { + Struct::<N>::method::<M>(&x); + x.method::<N>(); +} + +fn main() {} diff --git a/tests/ui/const-generics/type-dependent/issue-70507.rs b/tests/ui/const-generics/type-dependent/issue-70507.rs new file mode 100644 index 000000000..c72d9fbec --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70507.rs @@ -0,0 +1,45 @@ +// run-pass + +trait ConstChunksExactTrait<T> { + fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, {N}>; +} + +impl <T> ConstChunksExactTrait<T> for [T] { + fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, {N}> { + assert!(N != 0); + let rem = self.len() % N; + let len = self.len() - rem; + let (fst, _) = self.split_at(len); + ConstChunksExact { v: fst, } + } +} + +struct ConstChunksExact<'a, T: 'a, const N: usize> { + v: &'a [T], +} + +impl <'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, {N}> { + type Item = &'a [T; N]; + + fn next(&mut self) -> Option<Self::Item> { + if self.v.len() < N { + None + } else { + let (fst, snd) = self.v.split_at(N); + + self.v = snd; + let ptr = fst.as_ptr() as *const _; + Some(unsafe { &*ptr}) + } + } +} + +fn main() { + let slice = &[1i32, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter(); + + for a in slice.const_chunks_exact::<3>() { + assert_eq!(a, iter.next().unwrap()); + } +} diff --git a/tests/ui/const-generics/type-dependent/issue-70586.rs b/tests/ui/const-generics/type-dependent/issue-70586.rs new file mode 100644 index 000000000..346ac4b72 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70586.rs @@ -0,0 +1,30 @@ +// check-pass +use std::marker::PhantomData; + +// This namespace is necessary for the ICE to trigger +struct Namespace; + +impl Namespace { + pub fn const_chunks_exact<T, const N: usize>() -> ConstChunksExact<'static, T, N> { + ConstChunksExact { inner: PhantomData } + } +} + + +#[derive(Debug)] +pub struct ConstChunksExact<'a, T, const N: usize> { + inner: PhantomData<&'a T> +} + +impl <'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, { N }> { + type Item = &'a [T; N]; + + fn next(&mut self) -> Option<Self::Item> { + unreachable!() + } +} + +fn main() { + let mut chunks = Namespace::const_chunks_exact::<i32, 3usize>(); + let _next: &[i32; 3] = chunks.next().unwrap(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr new file mode 100644 index 000000000..b8fbb3979 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -0,0 +1,20 @@ +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-71348.rs:10:24 + | +LL | trait Get<'a, const N: &'static str> { + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-71348.rs:18:25 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs new file mode 100644 index 000000000..2ef2f066a --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -0,0 +1,38 @@ +// [full] run-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo { + i: i32, +} + +trait Get<'a, const N: &'static str> { + //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + type Target: 'a; + + fn get(&'a self) -> &'a Self::Target; +} + +impl Foo { + fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target + //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + where + Self: Get<'a, N>, + { + self.get() + } +} + +impl<'a> Get<'a, "int"> for Foo { + type Target = i32; + + fn get(&'a self) -> &'a Self::Target { + &self.i + } +} + +fn main() { + let foo = Foo { i: 123 }; + assert_eq!(foo.ask::<"int">(), &123); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71382.rs b/tests/ui/const-generics/type-dependent/issue-71382.rs new file mode 100644 index 000000000..1c4073e36 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71382.rs @@ -0,0 +1,21 @@ +struct Test; + +fn pass() -> u8 { + 42 +} + +impl Test { + pub fn call_me(&self) -> u8 { + self.test::<pass>() + } + + fn test<const FN: fn() -> u8>(&self) -> u8 { + //~^ ERROR using function pointers as const generic parameters is forbidden + FN() + } +} + +fn main() { + let x = Test; + assert_eq!(x.call_me(), 42); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr new file mode 100644 index 000000000..ad522aead --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:12:23 + | +LL | fn test<const FN: fn() -> u8>(&self) -> u8 { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/type-dependent/issue-71805.rs b/tests/ui/const-generics/type-dependent/issue-71805.rs new file mode 100644 index 000000000..060b89964 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71805.rs @@ -0,0 +1,38 @@ +// run-pass +use std::mem::MaybeUninit; + +trait CollectSlice<'a>: Iterator { + fn inner_array<const N: usize>(&mut self) -> [Self::Item; N]; + + fn collect_array<const N: usize>(&mut self) -> [Self::Item; N] { + let result = self.inner_array(); + assert!(self.next().is_none()); + result + } +} + +impl<'a, I: ?Sized> CollectSlice<'a> for I +where + I: Iterator, +{ + fn inner_array<const N: usize>(&mut self) -> [Self::Item; N] { + let mut result: [MaybeUninit<Self::Item>; N] = + unsafe { MaybeUninit::uninit().assume_init() }; + + let mut count = 0; + for (dest, item) in result.iter_mut().zip(self) { + *dest = MaybeUninit::new(item); + count += 1; + } + + assert_eq!(N, count); + + let temp_ptr: *const [MaybeUninit<Self::Item>; N] = &result; + unsafe { std::ptr::read(temp_ptr as *const [Self::Item; N]) } + } +} + +fn main() { + let mut foos = [0u64; 9].iter().cloned(); + let _bar: [u64; 9] = foos.collect_array::<9_usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-73730.rs b/tests/ui/const-generics/type-dependent/issue-73730.rs new file mode 100644 index 000000000..5e1b8c635 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-73730.rs @@ -0,0 +1,14 @@ +// check-pass +trait Foo<'a, A>: Iterator<Item=A> { + fn bar<const N: usize>(&mut self) -> *const [A; N]; +} + +impl<'a, A, I: ?Sized> Foo<'a, A> for I where I: Iterator<Item=A> { + fn bar<const N: usize>(&mut self) -> *const [A; N] { + std::ptr::null() + } +} + +fn main() { + (0_u8 .. 10).bar::<10_usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/non-local.rs b/tests/ui/const-generics/type-dependent/non-local.rs new file mode 100644 index 000000000..b755de30b --- /dev/null +++ b/tests/ui/const-generics/type-dependent/non-local.rs @@ -0,0 +1,21 @@ +// aux-build:type_dependent_lib.rs +// run-pass +extern crate type_dependent_lib; + +use type_dependent_lib::*; + +fn main() { + let s = Struct::<42>::new(); + assert_eq!(s.same_ty::<7>(), (42, 7)); + assert_eq!(s.different_ty::<19>(), (42, 19)); + assert_eq!(Struct::<1337>::new().different_ty::<96>(), (1337, 96)); + assert_eq!( + Struct::<18>::new() + .we_have_to_go_deeper::<19>() + .containing_ty::<Option<u32>, 3>(), + (27, 3), + ); + + let s = Struct::<7>::new(); + assert_eq!(s.foo::<18>(), 18); +} diff --git a/tests/ui/const-generics/type-dependent/qpath.rs b/tests/ui/const-generics/type-dependent/qpath.rs new file mode 100644 index 000000000..2d678d0ac --- /dev/null +++ b/tests/ui/const-generics/type-dependent/qpath.rs @@ -0,0 +1,9 @@ +// run-pass +struct A; +impl A { + fn foo<const N: usize>() -> usize { N + 1 } +} + +fn main() { + assert_eq!(A::foo::<7>(), 8); +} diff --git a/tests/ui/const-generics/type-dependent/simple.rs b/tests/ui/const-generics/type-dependent/simple.rs new file mode 100644 index 000000000..1b13133b5 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/simple.rs @@ -0,0 +1,9 @@ +// run-pass +struct R; + +impl R { + fn method<const N: u8>(&self) -> u8 { N } +} +fn main() { + assert_eq!(R.method::<1u8>(), 1); +} diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr new file mode 100644 index 000000000..70bc64057 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +help: change the type of the numeric literal from `u16` to `u8` + | +LL | assert_eq!(R.method::<1u8>(), 1); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr new file mode 100644 index 000000000..70bc64057 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +help: change the type of the numeric literal from `u16` to `u8` + | +LL | assert_eq!(R.method::<1u8>(), 1); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.rs b/tests/ui/const-generics/type-dependent/type-mismatch.rs new file mode 100644 index 000000000..3335ab870 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.rs @@ -0,0 +1,10 @@ +// revisions: full min +struct R; + +impl R { + fn method<const N: u8>(&self) -> u8 { N } +} +fn main() { + assert_eq!(R.method::<1u16>(), 1); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs new file mode 100644 index 000000000..4a7534e37 --- /dev/null +++ b/tests/ui/const-generics/type_mismatch.rs @@ -0,0 +1,9 @@ +fn foo<const N: usize>() -> [u8; N] { + bar::<N>() //~ ERROR mismatched types +} + +fn bar<const N: u8>() -> [u8; N] {} +//~^ ERROR mismatched types +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr new file mode 100644 index 000000000..8d779bee2 --- /dev/null +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::<N>() + | ^ expected `u8`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:26 + | +LL | fn bar<const N: u8>() -> [u8; N] {} + | --- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:31 + | +LL | fn bar<const N: u8>() -> [u8; N] {} + | ^ expected `usize`, found `u8` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_not_in_scope.rs b/tests/ui/const-generics/type_not_in_scope.rs new file mode 100644 index 000000000..593370180 --- /dev/null +++ b/tests/ui/const-generics/type_not_in_scope.rs @@ -0,0 +1,11 @@ +impl X { + //~^ ERROR cannot find type + fn getn<const N: usize>() -> [u8; N] { + getn::<N>() + } +} +fn getn<const N: cfg_attr>() -> [u8; N] {} +//~^ ERROR expected type, found built-in attribute `cfg_attr` +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr new file mode 100644 index 000000000..16796acb3 --- /dev/null +++ b/tests/ui/const-generics/type_not_in_scope.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `X` in this scope + --> $DIR/type_not_in_scope.rs:1:6 + | +LL | impl X { + | ^ not found in this scope + +error[E0573]: expected type, found built-in attribute `cfg_attr` + --> $DIR/type_not_in_scope.rs:7:18 + | +LL | fn getn<const N: cfg_attr>() -> [u8; N] {} + | ^^^^^^^^ not a type + +error[E0308]: mismatched types + --> $DIR/type_not_in_scope.rs:7:33 + | +LL | fn getn<const N: cfg_attr>() -> [u8; N] {} + | ---- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0412, E0573. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_of_anon_const.rs b/tests/ui/const-generics/type_of_anon_const.rs new file mode 100644 index 000000000..fb0d688a8 --- /dev/null +++ b/tests/ui/const-generics/type_of_anon_const.rs @@ -0,0 +1,17 @@ +// run-pass +trait T<const A: usize> { + fn l<const N: bool>() -> usize; + fn r<const N: bool>() -> bool; +} + +struct S; + +impl<const N: usize> T<N> for S { + fn l<const M: bool>() -> usize { N } + fn r<const M: bool>() -> bool { M } +} + +fn main() { + assert_eq!(<S as T<123>>::l::<true>(), 123); + assert!(<S as T<123>>::r::<true>()); +} diff --git a/tests/ui/const-generics/types-mismatch-const-args.full.stderr b/tests/ui/const-generics/types-mismatch-const-args.full.stderr new file mode 100644 index 000000000..b6a22df74 --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.full.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:14:41 + | +LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` + | + = note: expected constant `2` + found constant `4` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:16:41 + | +LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, _, _>` + found struct `A<'b, u32, _, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:18:41 + | +LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/types-mismatch-const-args.min.stderr b/tests/ui/const-generics/types-mismatch-const-args.min.stderr new file mode 100644 index 000000000..6ac93a08d --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.min.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:14:41 + | +LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` + | | + | expected due to this + | + = note: expected struct `A<'_, _, 2, _>` + found struct `A<'_, _, 4, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:16:41 + | +LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, _, _>` + found struct `A<'b, u32, _, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:18:41 + | +LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/types-mismatch-const-args.rs b/tests/ui/const-generics/types-mismatch-const-args.rs new file mode 100644 index 000000000..43ef28b26 --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.rs @@ -0,0 +1,22 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +// tests the diagnostic output of type mismatches for types that have const generics arguments. + +use std::marker::PhantomData; + +struct A<'a, T, const X: u32, const Y: u32> { + data: PhantomData<&'a T> +} + +fn a<'a, 'b>() { + let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types + let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types + let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types +} + +pub fn main() {} diff --git a/tests/ui/const-generics/unify_with_nested_expr.rs b/tests/ui/const-generics/unify_with_nested_expr.rs new file mode 100644 index 000000000..1271e0902 --- /dev/null +++ b/tests/ui/const-generics/unify_with_nested_expr.rs @@ -0,0 +1,18 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const N: usize>() +where + [(); N + 1 + 1]:, +{ + bar(); + //~^ ERROR: type annotations +} + +fn bar<const N: usize>() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/unify_with_nested_expr.stderr b/tests/ui/const-generics/unify_with_nested_expr.stderr new file mode 100644 index 000000000..8bab0dff7 --- /dev/null +++ b/tests/ui/const-generics/unify_with_nested_expr.stderr @@ -0,0 +1,22 @@ +error[E0284]: type annotations needed + --> $DIR/unify_with_nested_expr.rs:8:5 + | +LL | bar(); + | ^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a bound in `bar` + --> $DIR/unify_with_nested_expr.rs:14:10 + | +LL | fn bar<const N: usize>() + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` +help: consider specifying the generic argument + | +LL | bar::<N>(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs b/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs new file mode 100644 index 000000000..c7270e835 --- /dev/null +++ b/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs @@ -0,0 +1,15 @@ +// run-pass + +use std::fmt; + +struct Array<T, const N: usize>([T; N]); + +impl<T: fmt::Debug, const N: usize> fmt::Debug for Array<T, N> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.0.iter()).finish() + } +} + +fn main() { + assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]"); +} diff --git a/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs b/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs new file mode 100644 index 000000000..191caa78f --- /dev/null +++ b/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs @@ -0,0 +1,15 @@ +// run-pass + +use std::fmt; + +struct Array<T>(T); + +impl<T: fmt::Debug, const N: usize> fmt::Debug for Array<[T; N]> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries((&self.0 as &[T]).iter()).finish() + } +} + +fn main() { + assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]"); +} diff --git a/tests/ui/const-generics/unknown_adt.rs b/tests/ui/const-generics/unknown_adt.rs new file mode 100644 index 000000000..8cdd28a8c --- /dev/null +++ b/tests/ui/const-generics/unknown_adt.rs @@ -0,0 +1,4 @@ +fn main() { + let _: UnknownStruct<7>; + //~^ ERROR cannot find type `UnknownStruct` +} diff --git a/tests/ui/const-generics/unknown_adt.stderr b/tests/ui/const-generics/unknown_adt.stderr new file mode 100644 index 000000000..0f462dd47 --- /dev/null +++ b/tests/ui/const-generics/unknown_adt.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `UnknownStruct` in this scope + --> $DIR/unknown_adt.rs:2:12 + | +LL | let _: UnknownStruct<7>; + | ^^^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/unused-const-param.rs b/tests/ui/const-generics/unused-const-param.rs new file mode 100644 index 000000000..c7f74cfac --- /dev/null +++ b/tests/ui/const-generics/unused-const-param.rs @@ -0,0 +1,5 @@ +// check-pass + +struct A<const N: usize>; // ok + +fn main() {} diff --git a/tests/ui/const-generics/unused-type-param-suggestion.rs b/tests/ui/const-generics/unused-type-param-suggestion.rs new file mode 100644 index 000000000..2251512c4 --- /dev/null +++ b/tests/ui/const-generics/unused-type-param-suggestion.rs @@ -0,0 +1,4 @@ +#![crate_type="lib"] + +struct Example<N>; +//~^ ERROR parameter diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr new file mode 100644 index 000000000..807065ca1 --- /dev/null +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0392]: parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:3:16 + | +LL | struct Example<N>; + | ^ unused parameter + | + = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `N` to be a const parameter, use `const N: usize` instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/unused_braces.fixed b/tests/ui/const-generics/unused_braces.fixed new file mode 100644 index 000000000..4c1926387 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.fixed @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +#![warn(unused_braces)] + +macro_rules! make_1 { + () => { + 1 + } +} + +struct A<const N: usize>; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.full.fixed b/tests/ui/const-generics/unused_braces.full.fixed new file mode 100644 index 000000000..46d57e0dc --- /dev/null +++ b/tests/ui/const-generics/unused_braces.full.fixed @@ -0,0 +1,16 @@ +// check-pass +// run-rustfix +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![warn(unused_braces)] + + +struct A<const N: usize>; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.min.fixed b/tests/ui/const-generics/unused_braces.min.fixed new file mode 100644 index 000000000..46d57e0dc --- /dev/null +++ b/tests/ui/const-generics/unused_braces.min.fixed @@ -0,0 +1,16 @@ +// check-pass +// run-rustfix +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![warn(unused_braces)] + + +struct A<const N: usize>; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.rs b/tests/ui/const-generics/unused_braces.rs new file mode 100644 index 000000000..e9f15b401 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.rs @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +#![warn(unused_braces)] + +macro_rules! make_1 { + () => { + 1 + } +} + +struct A<const N: usize>; + +fn main() { + let _: A<7>; // ok + let _: A<{ 7 }>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.stderr b/tests/ui/const-generics/unused_braces.stderr new file mode 100644 index 000000000..2c8031c43 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.stderr @@ -0,0 +1,19 @@ +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:15:14 + | +LL | let _: A<{ 7 }>; + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:3:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - let _: A<{ 7 }>; +LL + let _: A<7>; + | + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/where-clauses.rs b/tests/ui/const-generics/where-clauses.rs new file mode 100644 index 000000000..aa3ca1cf6 --- /dev/null +++ b/tests/ui/const-generics/where-clauses.rs @@ -0,0 +1,30 @@ +// check-pass +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>(); +} |