diff options
Diffstat (limited to 'src/test/ui/const-generics/generic_const_exprs')
107 files changed, 2498 insertions, 0 deletions
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs new file mode 100644 index 000000000..06f00de13 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs new file mode 100644 index 000000000..3b5b87b2b --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr new file mode 100644 index 000000000..5ca04d25e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs new file mode 100644 index 000000000..7561ae2fe --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr new file mode 100644 index 000000000..ababb27a8 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -0,0 +1,147 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` + --> $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 `use_trait_impl::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 type `{ N as u128 }` + found type `{ O as u128 }` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` + --> $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 `use_trait_impl::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 type `{ N as _ }` + found type `{ O as u128 }` + +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 type `12` + found type `13` + +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 type `13` + found type `14` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` + --> $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 `use_trait_impl_2::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 type `{ N as u128 }` + found type `{ O as u128 }` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` + --> $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 `use_trait_impl_2::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 type `{ N as _ }` + found type `{ O as u128 }` + +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 type `12` + found type `13` + +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 type `13` + found type `14` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs new file mode 100644 index 000000000..184263f89 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 000000000..916d60c0e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 000000000..d48b639db --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr new file mode 100644 index 000000000..041232e86 --- /dev/null +++ b/src/test/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 constant + | + = 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/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr new file mode 100644 index 000000000..18e9135d0 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs new file mode 100644 index 000000000..7d3fe413c --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/associated-const.rs b/src/test/ui/const-generics/generic_const_exprs/associated-const.rs new file mode 100644 index 000000000..a67776322 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs b/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs new file mode 100644 index 000000000..b839008d4 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/src/test/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs new file mode 100644 index 000000000..15d618cae --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs new file mode 100644 index 000000000..df454dae7 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/closures.rs b/src/test/ui/const-generics/generic_const_exprs/closures.rs new file mode 100644 index 000000000..1ea310d06 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr new file mode 100644 index 000000000..a15dd2016 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 000000000..5874625ad --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/cross_crate.rs b/src/test/ui/const-generics/generic_const_exprs/cross_crate.rs new file mode 100644 index 000000000..dfc69e0b0 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs b/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs new file mode 100644 index 000000000..b08fffd69 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr new file mode 100644 index 000000000..7b4d46b82 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr new file mode 100644 index 000000000..4cd86fecd --- /dev/null +++ b/src/test/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:13: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:20: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:9:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = 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/dependence_lint.rs:16: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/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr new file mode 100644 index 000000000..b13bcdb2c --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -0,0 +1,34 @@ +error: overly complex generic constant + --> $DIR/dependence_lint.rs:16: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:20: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:13: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:9: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/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs new file mode 100644 index 000000000..dcdfd75de --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs @@ -0,0 +1,25 @@ +// revisions: full gce + +#![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/src/test/ui/const-generics/generic_const_exprs/different-fn.rs b/src/test/ui/const-generics/generic_const_exprs/different-fn.rs new file mode 100644 index 000000000..e8bc703bd --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr b/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr new file mode 100644 index 000000000..2aeb9b961 --- /dev/null +++ b/src/test/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 type `size_of::<T>()` + found type `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/src/test/ui/const-generics/generic_const_exprs/division.rs b/src/test/ui/const-generics/generic_const_exprs/division.rs new file mode 100644 index 000000000..098fa9e04 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs b/src/test/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 000000000..3543960c3 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/drop_impl.rs b/src/test/ui/const-generics/generic_const_exprs/drop_impl.rs new file mode 100644 index 000000000..077f77aa0 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs b/src/test/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs new file mode 100644 index 000000000..e4111157e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs new file mode 100644 index 000000000..8023b998a --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr new file mode 100644 index 000000000..2d9de8805 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.rs b/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.rs new file mode 100644 index 000000000..c59d62e57 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr new file mode 100644 index 000000000..b5719b3fe --- /dev/null +++ b/src/test/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: `#[warn(incomplete_features)]` on by default + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs b/src/test/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs new file mode 100644 index 000000000..340e35e1c --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs b/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs new file mode 100644 index 000000000..10ab2fd86 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr new file mode 100644 index 000000000..2d60ebaa8 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/fn_call.rs b/src/test/ui/const-generics/generic_const_exprs/fn_call.rs new file mode 100644 index 000000000..cbe4277df --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs new file mode 100644 index 000000000..b8f9827ec --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr new file mode 100644 index 000000000..bd71b49ee --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/from-sig.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig.rs new file mode 100644 index 000000000..28de4f864 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/function-call.rs b/src/test/ui/const-generics/generic_const_exprs/function-call.rs new file mode 100644 index 000000000..b5de66621 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/function-call.rs @@ -0,0 +1,19 @@ +// check-pass + +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/src/test/ui/const-generics/generic_const_exprs/function-call.stderr b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr new file mode 100644 index 000000000..0d8463714 --- /dev/null +++ b/src/test/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:14:17 + | +LL | let _ = [0; foo::<T>()]; + | ^^^^^^^^^^ + | + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = 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: 1 warning emitted + diff --git a/src/test/ui/const-generics/generic_const_exprs/impl-bounds.rs b/src/test/ui/const-generics/generic_const_exprs/impl-bounds.rs new file mode 100644 index 000000000..7120d6ee2 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/infer-too-generic.rs b/src/test/ui/const-generics/generic_const_exprs/infer-too-generic.rs new file mode 100644 index 000000000..b8058c252 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr new file mode 100644 index 000000000..f2ae361dc --- /dev/null +++ b/src/test/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 type `X` + found type `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/src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr new file mode 100644 index 000000000..9bea4105d --- /dev/null +++ b/src/test/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; _]` +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/src/test/ui/const-generics/generic_const_exprs/issue-62504.rs b/src/test/ui/const-generics/generic_const_exprs/issue-62504.rs new file mode 100644 index 000000000..a97f4b8ff --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-69654.rs b/src/test/ui/const-generics/generic_const_exprs/issue-69654.rs new file mode 100644 index 000000000..9b36699bb --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr new file mode 100644 index 000000000..7a083733a --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -0,0 +1,22 @@ +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 + +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: the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +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/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr new file mode 100644 index 000000000..4d0d0253f --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -0,0 +1,55 @@ +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:25: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:25: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[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True` + --> $DIR/issue-72787.rs:21:26 + | +LL | IsLessOrEqual<I, 8>: True, + | ^^^^ + | + = note: cannot satisfy `IsLessOrEqual<I, 8>: True` + +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True` + --> $DIR/issue-72787.rs:21:26 + | +LL | IsLessOrEqual<I, 8>: True, + | ^^^^ + | + = note: cannot satisfy `IsLessOrEqual<I, 8>: True` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs new file mode 100644 index 000000000..c651bf1c8 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -0,0 +1,35 @@ +// [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, +//[min]~^ Error type annotations needed +//[min]~| Error type annotations needed + 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/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr new file mode 100644 index 000000000..d536f6fd1 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -0,0 +1,21 @@ +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 type `false` + found type `true` + +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 type `false` + found type `true` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr new file mode 100644 index 000000000..42671412f --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs new file mode 100644 index 000000000..7a5aa9e47 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-73899.rs b/src/test/ui/const-generics/generic_const_exprs/issue-73899.rs new file mode 100644 index 000000000..d1ab1be04 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-74634.rs b/src/test/ui/const-generics/generic_const_exprs/issue-74634.rs new file mode 100644 index 000000000..cd1f7a9da --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-74713.rs b/src/test/ui/const-generics/generic_const_exprs/issue-74713.rs new file mode 100644 index 000000000..0bcb997d9 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-74713.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-74713.stderr new file mode 100644 index 000000000..e7673df0a --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs b/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs new file mode 100644 index 000000000..faa8b3d10 --- /dev/null +++ b/src/test/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 this function takes 2 generic arguments +} diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr new file mode 100644 index 000000000..c587a7e15 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs new file mode 100644 index 000000000..2fa9a71fb --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr new file mode 100644 index 000000000..c90774e94 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr @@ -0,0 +1,14 @@ +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 `[(); _]` + | + = note: expected associated type `<Self as Foo>::Assoc` + found array `[(); _]` + = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` 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/src/test/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs new file mode 100644 index 000000000..77d3c98da --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs b/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs new file mode 100644 index 000000000..275f69953 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr new file mode 100644 index 000000000..1b502642e --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -0,0 +1,66 @@ +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | intrinsics::size_of::<T>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | size_of called on unsized type `dyn Debug` + | inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + ::: $DIR/issue-80742.rs:22:10 + | +LL | [u8; size_of::<T>() + 1]: , + | -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:22:10 + +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 + | +LL | pub trait Debug { + | --------------- doesn't satisfy `dyn Debug: Sized` + | + = note: the following trait bounds were not satisfied: + `dyn Debug: Sized` + +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | intrinsics::size_of::<T>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | size_of called on unsized type `dyn Debug` + | inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + ::: $DIR/issue-80742.rs:14:10 + | +LL | [u8; size_of::<T>() + 1]: , + | -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:14:10 + +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/src/test/ui/const-generics/generic_const_exprs/issue-83765.rs b/src/test/ui/const-generics/generic_const_exprs/issue-83765.rs new file mode 100644 index 000000000..fac811d13 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr new file mode 100644 index 000000000..0332e82fe --- /dev/null +++ b/src/test/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 type `Self::DIM` + found type `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 type `DIM` + found type `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-84408.rs b/src/test/ui/const-generics/generic_const_exprs/issue-84408.rs new file mode 100644 index 000000000..fb2e5590d --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-85848.rs b/src/test/ui/const-generics/generic_const_exprs/issue-85848.rs new file mode 100644 index 000000000..3a7f4c618 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr new file mode 100644 index 000000000..d45dfde9a --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -0,0 +1,63 @@ +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 because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ +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 because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ +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 type `true` + found type `{ 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/src/test/ui/const-generics/generic_const_exprs/issue-90847.rs b/src/test/ui/const-generics/generic_const_exprs/issue-90847.rs new file mode 100644 index 000000000..ebc6fe141 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-94287.rs b/src/test/ui/const-generics/generic_const_exprs/issue-94287.rs new file mode 100644 index 000000000..643126a46 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr new file mode 100644 index 000000000..7390a0077 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs new file mode 100644 index 000000000..67e30232e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr new file mode 100644 index 000000000..b5b2b0e40 --- /dev/null +++ b/src/test/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: `#[warn(incomplete_features)]` on by default + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + +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/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs new file mode 100644 index 000000000..00568a089 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr new file mode 100644 index 000000000..5dfbd87cc --- /dev/null +++ b/src/test/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: `#[warn(incomplete_features)]` on by default + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + +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/src/test/ui/const-generics/generic_const_exprs/less_than.rs b/src/test/ui/const-generics/generic_const_exprs/less_than.rs new file mode 100644 index 000000000..2e9af1bf4 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/let-bindings.rs b/src/test/ui/const-generics/generic_const_exprs/let-bindings.rs new file mode 100644 index 000000000..cd5d76dd9 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr new file mode 100644 index 000000000..5ebb4c399 --- /dev/null +++ b/src/test/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 constant + | + = 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 constant + | + = 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/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.rs b/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.rs new file mode 100644 index 000000000..2bd3c801f --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.stderr new file mode 100644 index 000000000..7b41e39b7 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs b/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs new file mode 100644 index 000000000..7e5022817 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs b/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs new file mode 100644 index 000000000..769e3ae68 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs b/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs new file mode 100644 index 000000000..316887e5e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs new file mode 100644 index 000000000..d45a6465b --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/no_dependence.rs b/src/test/ui/const-generics/generic_const_exprs/no_dependence.rs new file mode 100644 index 000000000..db8dc6ed4 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/no_where_clause.rs b/src/test/ui/const-generics/generic_const_exprs/no_where_clause.rs new file mode 100644 index 000000000..9c5de0317 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/src/test/ui/const-generics/generic_const_exprs/no_where_clause.stderr new file mode 100644 index 000000000..3e5c2f5ca --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs new file mode 100644 index 000000000..24d333aba --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr new file mode 100644 index 000000000..4e1d71f15 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs new file mode 100644 index 000000000..42c1cc507 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr new file mode 100644 index 000000000..45c7d835f --- /dev/null +++ b/src/test/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; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/object-safety-err-where-bounds.rs:3:9 + | +LL | #![deny(where_clauses_object_safety)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs new file mode 100644 index 000000000..79e9834b5 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr new file mode 100644 index 000000000..59e9fee1e --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok.rs new file mode 100644 index 000000000..f4c89f623 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs new file mode 100644 index 000000000..cae54df4c --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr new file mode 100644 index 000000000..a25fa56b7 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs b/src/test/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs new file mode 100644 index 000000000..d6574a3aa --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs b/src/test/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs new file mode 100644 index 000000000..d058b3638 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 000000000..c0404d35b --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 000000000..d18c7916f --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unop.rs b/src/test/ui/const-generics/generic_const_exprs/unop.rs new file mode 100644 index 000000000..c12fef083 --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs b/src/test/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs new file mode 100644 index 000000000..9580f8a7f --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unused_expr.rs b/src/test/ui/const-generics/generic_const_exprs/unused_expr.rs new file mode 100644 index 000000000..c1bf19e0f --- /dev/null +++ b/src/test/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/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr new file mode 100644 index 000000000..df73acf53 --- /dev/null +++ b/src/test/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 constant + | + = 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 constant + | + = 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 constant + | + = 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 + |