diff options
Diffstat (limited to 'tests/ui/const-generics/generic_const_exprs')
140 files changed, 3312 insertions, 0 deletions
diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs new file mode 100644 index 000000000..06f00de13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: u8>([u8; N as usize]) +where + [(); N as usize]:; + +struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:; + +// unifying with subtrees +struct Evaluatable<const N: u16>; +fn foo<const N: u8>() where Evaluatable<{N as usize as u16 }>: { + let _ = Foo::<N>([1; N as usize]); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs new file mode 100644 index 000000000..3b5b87b2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Evaluatable<const N: u128> {} + +struct Foo<const N: u8>([u8; N as usize]) +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:` +where + Evaluatable<{N as u128}>:; + +struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr new file mode 100644 index 000000000..5ca04d25e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr @@ -0,0 +1,26 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:6:25 + | +LL | struct Foo<const N: u8>([u8; N as usize]) + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N as usize]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:12:26 + | +LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:16:25 + | +LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs new file mode 100644 index 000000000..7561ae2fe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs @@ -0,0 +1,47 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128<const N: u128>; + +struct HasCastInTraitImpl<const N: usize, const M: u128>; +impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + +pub fn use_trait_impl<const N: usize>() +where + [(); { N + 1}]:, + EvaluatableU128<{N as u128}>:, { + fn assert_impl<T: Trait>() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + //~^ Error: mismatched types + assert_impl::<HasCastInTraitImpl<14, 13>>(); + //~^ Error: mismatched types +} +pub fn use_trait_impl_2<const N: usize>() +where + [(); { N + 1}]:, + EvaluatableU128<{N as _}>:, { + fn assert_impl<T: Trait>() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + //~^ Error: mismatched types + assert_impl::<HasCastInTraitImpl<14, 13>>(); + //~^ Error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr new file mode 100644 index 000000000..cdf97bd88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -0,0 +1,187 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:17:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:20:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:23:5 + | +LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:25:5 + | +LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:35:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:38:19 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:41:5 + | +LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:43:5 + | +LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl<T: Trait>() {} + | ^^^^^ required by this bound in `assert_impl` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs new file mode 100644 index 000000000..184263f89 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs @@ -0,0 +1,29 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128<const N: u128>; + +struct HasCastInTraitImpl<const N: usize, const M: u128>; +impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {} + +pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, { + fn assert_impl<T: Trait>() {} + + assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>(); + assert_impl::<HasCastInTraitImpl<N, { N as _ }>>(); + assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>(); + assert_impl::<HasCastInTraitImpl<13, 13>>(); +} +pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, { + fn assert_impl<T: Trait>() {} + + assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>(); + assert_impl::<HasCastInTraitImpl<N, { N as _ }>>(); + assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>(); + assert_impl::<HasCastInTraitImpl<13, 13>>(); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 000000000..916d60c0e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const N: u8>(a: [(); N as usize]) { + bar::<{ N as usize as usize }>(); + //~^ error: unconstrained generic constant +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 000000000..d48b639db --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-consts-as-cast-5.rs:5:11 + | +LL | bar::<{ N as usize as usize }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr new file mode 100644 index 000000000..1d10dfdf1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -0,0 +1,19 @@ +error: unconstrained generic constant + --> $DIR/array-size-in-generic-struct-param.rs:8:38 + | +LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); 0 + N]:` + +error: overly complex generic constant + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^^^^^^^^^^ field access is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr new file mode 100644 index 000000000..18e9135d0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -0,0 +1,29 @@ +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:8:48 + | +LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^ cannot perform const operation using `CFG` + | + = help: const parameters may only be used as standalone arguments, i.e. `CFG` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: `Config` is forbidden as the type of a const generic parameter + --> $DIR/array-size-in-generic-struct-param.rs:17:21 + | +LL | struct B<const CFG: Config> { + | ^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs new file mode 100644 index 000000000..7d3fe413c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs @@ -0,0 +1,29 @@ +// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`. +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs, adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +#[allow(dead_code)] +struct ArithArrayLen<const N: usize>([u32; 0 + N]); +//[full]~^ ERROR unconstrained generic constant +//[min]~^^ ERROR generic parameters may not be used in const operations + +#[derive(PartialEq, Eq)] +struct Config { + arr_size: usize, +} + +struct B<const CFG: Config> { + //[min]~^ ERROR `Config` is forbidden + arr: [u8; CFG.arr_size], + //[full]~^ ERROR overly complex generic constant + //[min]~^^ ERROR generic parameters may not be used in const operations +} + +const C: Config = Config { arr_size: 5 }; + +fn main() { + let b = B::<C> { arr: [1, 2, 3, 4, 5] }; + assert_eq!(b.arr.len(), 5); +} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs new file mode 100644 index 000000000..e8f89cb1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs @@ -0,0 +1,27 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} +impl<T> Trait for T { + const ASSOC: usize = std::mem::size_of::<T>(); +} + +struct Foo<T: Trait>([u8; T::ASSOC]) +where + [(); T::ASSOC]:; + +fn bar<T: Trait>() +where + [(); T::ASSOC]:, +{ + let _: Foo<T> = Foo::<_>(make()); +} + +fn make() -> ! { + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs new file mode 100644 index 000000000..c8f7553da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, { + bar::<{ T::ASSOC }>(); + //~^ ERROR: unconstrained generic constant +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr new file mode 100644 index 000000000..e4a0cabe5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/doesnt_unify_evaluatable.rs:9:11 + | +LL | bar::<{ T::ASSOC }>(); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs new file mode 100644 index 000000000..274caa1e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +struct Foo<T: Trait>(T) +where + [(); T::ASSOC]:; + +impl<T: Trait> Drop for Foo<T> +where + [(); T::ASSOC]:, +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs new file mode 100644 index 000000000..6597b9f2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo<T: Trait, U: Trait>() where [(); T::ASSOC]:, { + bar::<{ T::ASSOC }>(); +} + +fn bar<const N: usize>() -> [(); N] { + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-const.rs b/tests/ui/const-generics/generic_const_exprs/associated-const.rs new file mode 100644 index 000000000..a67776322 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-const.rs @@ -0,0 +1,11 @@ +// check-pass +struct Foo<T>(T); +impl<T> Foo<T> { + const VALUE: usize = std::mem::size_of::<T>(); +} + +fn test<T>() { + let _ = [0; Foo::<u8>::VALUE]; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs new file mode 100644 index 000000000..b839008d4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait BlockCipher { + const BLOCK_SIZE: usize; +} + +struct FooCipher; +impl BlockCipher for FooCipher { + const BLOCK_SIZE: usize = 64; +} + +struct BarCipher; +impl BlockCipher for BarCipher { + const BLOCK_SIZE: usize = 32; +} + +pub struct Block<C>(#[allow(unused_tuple_struct_fields)] C); + +pub fn test<C: BlockCipher, const M: usize>() +where + [u8; M - C::BLOCK_SIZE]: Sized, +{ + let _ = [0; M - C::BLOCK_SIZE]; +} + +fn main() { + test::<FooCipher, 128>(); + test::<BarCipher, 64>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs new file mode 100644 index 000000000..97be07493 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs @@ -0,0 +1,8 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<const N: usize>; + +pub fn foo<const N: usize>() -> Foo<{ N + 1 }> { + Foo +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs new file mode 100644 index 000000000..15d618cae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] +where + [u8; std::mem::size_of::<T>() - 1]: Sized, +{ + [0; std::mem::size_of::<T>() - 1] +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs new file mode 100644 index 000000000..df454dae7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] + +use std::str::FromStr; + +pub struct If<const CONDITION: bool>; + +pub trait True {} + +impl True for If<true> {} + +pub struct FixedI32<const FRAC: u32>; + +impl<const FRAC: u32> FromStr for FixedI32<FRAC> +where + If<{ FRAC <= 32 }>: True, +{ + type Err = (); + fn from_str(_s: &str) -> Result<Self, Self::Err> { + unimplemented!() + } +} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.rs b/tests/ui/const-generics/generic_const_exprs/closures.rs new file mode 100644 index 000000000..1ea310d06 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.rs @@ -0,0 +1,6 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +fn test<const N: usize>() -> [u8; N + (|| 42)()] {} +//~^ ERROR cycle detected when building an abstract representation + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.stderr b/tests/ui/const-generics/generic_const_exprs/closures.stderr new file mode 100644 index 000000000..a7d891d77 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.stderr @@ -0,0 +1,26 @@ +error[E0391]: cycle detected when building an abstract representation for `test::{constant#0}` + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + | +note: ...which requires building THIR for `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + = note: ...which again requires building an abstract representation for `test::{constant#0}`, completing the cycle +note: cycle used when checking that `test` is well-formed + --> $DIR/closures.rs:3:1 + | +LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs new file mode 100644 index 000000000..7332a8f03 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs @@ -0,0 +1,11 @@ +#![feature(inline_const, generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +fn foo<T>() { + let _ = [0u8; const { std::mem::size_of::<T>() }]; + //~^ ERROR: overly complex generic constant +} + +fn main() { + foo::<i32>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr new file mode 100644 index 000000000..f26259908 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -0,0 +1,20 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-block-is-poly.rs:1:26 + | +LL | #![feature(inline_const, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: overly complex generic constant + --> $DIR/const-block-is-poly.rs:5:19 + | +LL | let _ = [0u8; const { std::mem::size_of::<T>() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 000000000..5874625ad --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + type Assoc: Default; +} + +impl Foo<0> for () { + type Assoc = u32; +} + +impl Foo<3> for () { + type Assoc = i64; +} + +fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc +where + (): Foo<{ N + 1 }>, +{ + Default::default() +} + +fn main() { + let mut _q = Default::default(); + _q = foo::<_, 2>(_q); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs new file mode 100644 index 000000000..6093fc70b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs, generic_arg_infer)] +#![allow(incomplete_features)] + +// minimized repro for #105205 +// +// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a +// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter +// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed` +// obligation into `WellFormed(Expr(L - 1))` + +fn foo<const N: usize, const M: usize>(_: [(); N + 1 + M]) {} + +fn ice<const L: usize>() +where + [(); (L - 1) + 1 + L]:, +{ + foo::<_, L>([(); L + 1 + L]); + //~^ ERROR: mismatched types + //~^^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr new file mode 100644 index 000000000..da5194696 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/wf_obligation.rs:17:17 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L` + | + = note: expected constant `N + 1 + M` + found constant `L + 1 + L` + +error: unconstrained generic constant + --> $DIR/wf_obligation.rs:17:22 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs new file mode 100644 index 000000000..dfc69e0b0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs @@ -0,0 +1,15 @@ +// aux-build:const_evaluatable_lib.rs +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized { + assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]); +} + +fn main() { + assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]); + user::<u32>(); + user::<u64>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs new file mode 100644 index 000000000..b08fffd69 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs @@ -0,0 +1,14 @@ +// aux-build:const_evaluatable_lib.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user<T>() { + let _ = const_evaluatable_lib::test1::<T>(); + //~^ ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr new file mode 100644 index 000000000..7b4d46b82 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -0,0 +1,54 @@ +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::<T>() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::<T>() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::<T>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr new file mode 100644 index 000000000..d674e3acd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -0,0 +1,39 @@ +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:14:32 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:21:37 + | +LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + +error: aborting due to 2 previous errors; 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr new file mode 100644 index 000000000..74111ef1d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -0,0 +1,34 @@ +error: overly complex generic constant + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: overly complex generic constant + --> $DIR/dependence_lint.rs:21:17 + | +LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:14:12 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs new file mode 100644 index 000000000..b715e07f8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs @@ -0,0 +1,26 @@ +// revisions: full gce +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![cfg_attr(gce, feature(generic_const_exprs))] +#![allow(incomplete_features)] + +use std::mem::size_of; + +fn foo<T>() { + [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + //[gce]~^ ERROR unconstrained + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR unconstrained generic + [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce + //[gce]~^ ERROR overly complex + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR overly complex +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.rs b/tests/ui/const-generics/generic_const_exprs/different-fn.rs new file mode 100644 index 000000000..e8bc703bd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; +use std::marker::PhantomData; + +struct Foo<T>(PhantomData<T>); + +fn test<T>() -> [u8; size_of::<T>()] { + [0; size_of::<Foo<T>>()] + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types +} + +fn main() { + test::<u32>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.stderr b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr new file mode 100644 index 000000000..83a2f3740 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/different-fn.rs:10:5 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()` + | + = note: expected constant `size_of::<T>()` + found constant `size_of::<Foo<T>>()` + +error: unconstrained generic constant + --> $DIR/different-fn.rs:10:9 + | +LL | [0; size_of::<Foo<T>>()] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/division.rs b/tests/ui/const-generics/generic_const_exprs/division.rs new file mode 100644 index 000000000..098fa9e04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/division.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn with_bound<const N: usize>() where [u8; N / 2]: Sized { + let _: [u8; N / 2] = [0; N / 2]; +} + +fn main() { + with_bound::<4>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 000000000..3543960c3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a repro for #82279. It checks that we don't error +// when calling is_const_evaluatable on `std::mem::size_of::<T>()` +// when looking for candidates that may prove `T: Foo` in `foo` + +trait Foo {} + +#[allow(dead_code)] +fn foo<T: Foo>() {} + +impl<T> Foo for T where [(); std::mem::size_of::<T>()]: {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/drop_impl.rs b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs new file mode 100644 index 000000000..077f77aa0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs @@ -0,0 +1,16 @@ +//check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: usize> +where + [(); N + 1]: ; + +impl<const N: usize> Drop for Foo<N> +where + [(); N + 1]: , +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs new file mode 100644 index 000000000..e4111157e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we use the elaborated predicates from traits +// to satisfy const evaluatable predicates. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::mem::size_of; + +trait Foo: Sized +where + [(); size_of::<Self>()]: Sized, +{ +} + +impl Foo for u64 {} +impl Foo for u32 {} + +fn foo<T: Foo>() -> [u8; size_of::<T>()] { + [0; size_of::<T>()] +} + +fn main() { + assert_eq!(foo::<u32>(), [0; 4]); + assert_eq!(foo::<u64>(), [0; 8]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs new file mode 100644 index 000000000..8023b998a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -0,0 +1,26 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Const<const U: u8>; + +pub trait Trait { + type AssocTy; + fn assoc_fn() -> Self::AssocTy; +} + +impl<const U: u8> Trait for Const<U> // OK, trait impl predicates +where + Const<{ my_const_fn(U) }>: , +{ + type AssocTy = Const<{ my_const_fn(U) }>; + //~^ ERROR private type + fn assoc_fn() -> Self::AssocTy { + Const + } +} + +const fn my_const_fn(val: u8) -> u8 { + // body of this function doesn't matter + val +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr new file mode 100644 index 000000000..2d9de8805 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:16:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs new file mode 100644 index 000000000..c59d62e57 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs @@ -0,0 +1,26 @@ +// build-pass + +#![feature(generic_const_exprs)] +//~^ WARNING the feature `generic_const_exprs` is incomplete + +trait Generic { + const ASSOC: usize; +} + +impl Generic for u8 { + const ASSOC: usize = 17; +} +impl Generic for u16 { + const ASSOC: usize = 13; +} + + +fn uses_assoc_type<T: Generic, const N: usize>() -> [u8; N + T::ASSOC] { + [0; N + T::ASSOC] +} + +fn only_generic_n<const N: usize>() -> [u8; N + 13] { + uses_assoc_type::<u16, N>() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr new file mode 100644 index 000000000..8eb1fccc5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/eval-try-unify.rs:3:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs new file mode 100644 index 000000000..340e35e1c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs @@ -0,0 +1,22 @@ +// check-pass + +// We previously always returned ambiguity when equating generic consts, even if they +// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1` +// should fail. +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +enum Assert<const COND: bool> {} +trait IsTrue {} +impl IsTrue for Assert<true> {} + +struct Foo<const N: usize, const M: usize>; +trait Bar<const N: usize, const M: usize> {} +impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M> +where + Assert<{ N > 1 }>: IsTrue, + Assert<{ M > 1 }>: IsTrue, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs new file mode 100644 index 000000000..10ab2fd86 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs @@ -0,0 +1,11 @@ +type Arr<const N: usize> = [u8; N - 1]; +//~^ ERROR generic parameters may not be used in const operations + +fn test<const N: usize>() -> Arr<N> where Arr<N>: Default { + Default::default() +} + +fn main() { + let x = test::<33>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr new file mode 100644 index 000000000..2d60ebaa8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/feature-gate-generic_const_exprs.rs:1:33 + | +LL | type Arr<const N: usize> = [u8; N - 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/fn_call.rs b/tests/ui/const-generics/generic_const_exprs/fn_call.rs new file mode 100644 index 000000000..cbe4277df --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/fn_call.rs @@ -0,0 +1,30 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn test_me<T>(a: usize, b: usize) -> usize { + if a < b { + std::mem::size_of::<T>() + } else { + usize::MAX + } +} + +fn test_simple<T>() -> [u8; std::mem::size_of::<T>()] +where + [u8; std::mem::size_of::<T>()]: Sized, +{ + [0; std::mem::size_of::<T>()] +} + +fn test_with_args<T, const N: usize>() -> [u8; test_me::<T>(N, N + 1) + N] +where + [u8; test_me::<T>(N, N + 1) + N]: Sized, +{ + [0; test_me::<T>(N, N + 1) + N] +} + +fn main() { + assert_eq!([0; 8], test_simple::<u64>()); + assert_eq!([0; 12], test_with_args::<u64, 4>()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs new file mode 100644 index 000000000..b8f9827ec --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn test<const N: usize>() -> [u8; N - 1] { + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr new file mode 100644 index 000000000..bd71b49ee --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/from-sig-fail.rs:4:35 + | +LL | fn test<const N: usize>() -> [u8; N - 1] { + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig.rs b/tests/ui/const-generics/generic_const_exprs/from-sig.rs new file mode 100644 index 000000000..28de4f864 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ N > 10 }> { + Foo +} + +fn main() { + let _: Foo<true> = test::<12>(); + let _: Foo<false> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.rs b/tests/ui/const-generics/generic_const_exprs/function-call.rs new file mode 100644 index 000000000..3c866333d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zdeduplicate-diagnostics=yes + +const fn foo<T>() -> usize { + // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here, + // which would cause this function to fail on 32 bit systems. + if false { + std::mem::size_of::<T>() + } else { + 8 + } +} + +fn test<T>() { + let _ = [0; foo::<T>()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.stderr b/tests/ui/const-generics/generic_const_exprs/function-call.stderr new file mode 100644 index 000000000..84abfe578 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.stderr @@ -0,0 +1,12 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/function-call.rs:15:17 + | +LL | let _ = [0; foo::<T>()]; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200> + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs new file mode 100644 index 000000000..7120d6ee2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; + +struct Foo<T, const N: usize>(T); + +impl<T> Foo<T, { size_of::<T>() }> { + fn test() { + let _: [u8; std::mem::size_of::<T>()]; + } +} + +trait Bar<const N: usize> { + fn test_me(); +} + +impl<T> Bar<{ size_of::<T>() }> for Foo<T, 3> { + fn test_me() { + let _: [u8; std::mem::size_of::<T>()]; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs new file mode 100644 index 000000000..b8058c252 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::{mem, ptr}; + +fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1]) +where + [T; N - 1]: Sized, +{ + let arr = mem::ManuallyDrop::new(arr); + unsafe { + let head = ptr::read(&arr[0]); + let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]); + (head, tail) + } +} + +fn main() { + let arr = [0, 1, 2, 3, 4]; + let (head, tail) = split_first(arr); + assert_eq!(head, 0); + assert_eq!(tail, [1, 2, 3, 4]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100217.rs b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs new file mode 100644 index 000000000..acdc348a3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs @@ -0,0 +1,42 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait TraitOne { + const MY_NUM: usize; + type MyErr: std::fmt::Debug; + + fn do_one_stuff(arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr>; +} + +trait TraitTwo { + fn do_two_stuff(); +} + +impl<O: TraitOne> TraitTwo for O +where + [(); Self::MY_NUM]:, +{ + fn do_two_stuff() { + O::do_one_stuff([5; Self::MY_NUM]).unwrap() + } +} + +struct Blargotron; + +#[derive(Debug)] +struct ErrTy<const N: usize>([(); N]); + +impl TraitOne for Blargotron { + const MY_NUM: usize = 3; + type MyErr = ErrTy<{ Self::MY_NUM }>; + + fn do_one_stuff(_arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr> { + Ok(()) + } +} + +fn main() { + Blargotron::do_two_stuff(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100360.rs b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs new file mode 100644 index 000000000..5572f1f88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs @@ -0,0 +1,13 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +fn foo<const B: &'static bool>(arg: &'static bool) -> bool { + B == arg +} + +fn main() { + foo::<{ &true }>(&false); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102074.rs b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs new file mode 100644 index 000000000..66d15cf12 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs @@ -0,0 +1,23 @@ +// check-pass +// Checks that the NoopMethodCall lint doesn't call Instance::resolve on unresolved consts + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[derive(Debug, Clone)] +pub struct Aes128CipherKey([u8; Aes128Cipher::KEY_LEN]); + +impl Aes128CipherKey { + pub fn new(key: &[u8; Aes128Cipher::KEY_LEN]) -> Self { + Self(key.clone()) + } +} + +#[derive(Debug, Clone)] +pub struct Aes128Cipher; + +impl Aes128Cipher { + const KEY_LEN: usize = 16; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs new file mode 100644 index 000000000..7aea0d30d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait X { + type Y<'a>; +} + +const _: () = { + fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument +}; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr new file mode 100644 index 000000000..8278edabe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr @@ -0,0 +1,33 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} + | ^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.rs b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs new file mode 100644 index 000000000..d8b23bc01 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait<T> { + fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr new file mode 100644 index 000000000..ed7a8cb19 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr @@ -0,0 +1,14 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:5:12 + | +LL | fn fnc<const N: usize = "">(&self) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:6:12 + | +LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.rs b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs new file mode 100644 index 000000000..e28ba3b1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Combination<const STRATEGIES: usize>; + +impl<const STRATEGIES: usize> Combination<STRATEGIES> { + fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> { + Combination + } +} + +pub fn main() { + Combination::<0>.and::<_>().and::<_>(); + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr new file mode 100644 index 000000000..0be4c43da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-105608.rs:13:22 + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ^^^ cannot infer type of the type parameter `M` declared on the associated function `and` + | +help: consider specifying the generic argument + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr new file mode 100644 index 000000000..0742db398 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | + = note: expected constant `X` + found constant `Self::SIZE` + +error: unconstrained generic constant + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr new file mode 100644 index 000000000..65822856e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -0,0 +1,27 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | | + | arguments to this struct are incorrect + | + = note: expected array `[u32; X]` + found array `[u32; Self::SIZE]` +note: tuple struct defined here + --> $DIR/issue-62504.rs:14:8 + | +LL | struct ArrayHolder<const X: usize>([u32; X]); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs new file mode 100644 index 000000000..a97f4b8ff --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs @@ -0,0 +1,27 @@ +// revisions: full min +#![allow(incomplete_features)] +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +trait HasSize { + const SIZE: usize; +} + +impl<const X: usize> HasSize for ArrayHolder<X> { + const SIZE: usize = X; +} + +struct ArrayHolder<const X: usize>([u32; X]); + +impl<const X: usize> ArrayHolder<X> { + pub const fn new() -> Self { + ArrayHolder([0; Self::SIZE]) + //~^ ERROR mismatched types + //[full]~^^ ERROR unconstrained generic constant + //[min]~^^^ ERROR constant expression depends on a generic parameter + } +} + +fn main() { + let mut array = ArrayHolder::new(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.rs b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs new file mode 100644 index 000000000..9b36699bb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Bar<T> {} +impl<T> Bar<T> for [u8; T] {} +//~^ ERROR expected value, found type parameter `T` + +struct Foo<const N: usize> {} +impl<const N: usize> Foo<N> +where + [u8; N]: Bar<[(); N]>, +{ + fn foo() {} +} + +fn main() { + Foo::foo(); + //~^ ERROR the function or associated item +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr new file mode 100644 index 000000000..eb4ff8305 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -0,0 +1,30 @@ +error[E0423]: expected value, found type parameter `T` + --> $DIR/issue-69654.rs:5:25 + | +LL | impl<T> Bar<T> for [u8; T] {} + | - ^ not a value + | | + | found this type parameter + +error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo<const N: usize> {} + | -------------------------- function or associated item `foo` not found for this struct +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds + | +note: trait bound `[u8; _]: Bar<[(); _]>` was not satisfied + --> $DIR/issue-69654.rs:11:14 + | +LL | impl<const N: usize> Foo<N> + | ------ +LL | where +LL | [u8; N]: Bar<[(); N]>, + | ^^^^^^^^^^^^ unsatisfied trait bound introduced here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr new file mode 100644 index 000000000..ea6f5f692 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -0,0 +1,38 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:17 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `LHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `LHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:24 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `RHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `RHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:25 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `I` + | + = help: const parameters may only be used as standalone arguments, i.e. `I` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:36 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `J` + | + = help: const parameters may only be used as standalone arguments, i.e. `J` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs new file mode 100644 index 000000000..657fec2e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -0,0 +1,33 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +pub struct IsLessOrEqual<const LHS: u32, const RHS: u32>; +pub struct Condition<const CONDITION: bool>; +pub trait True {} + +impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where + Condition<{ LHS <= RHS }>: True +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations +{ +} +impl True for Condition<true> {} + +struct S<const I: u32, const J: u32>; +impl<const I: u32, const J: u32> S<I, J> +where + IsLessOrEqual<I, 8>: True, + IsLessOrEqual<J, 8>: True, + IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations + // Condition<{ 8 - I <= 8 - J }>: True, +{ + fn print() { + println!("I {} J {}", I, J); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr new file mode 100644 index 000000000..f2fddfbfb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:12 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:32 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr<const N: usize> + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr new file mode 100644 index 000000000..42671412f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72819-generic-in-const-eval.rs:8:17 + | +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs new file mode 100644 index 000000000..7a5aa9e47 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs @@ -0,0 +1,23 @@ +// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type +// bounds. +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Arr<const N: usize> +where Assert::<{N < usize::MAX / 2}>: IsTrue, +//[min]~^ ERROR generic parameters may not be used in const operations +{ +} + +enum Assert<const CHECK: bool> {} + +trait IsTrue {} + +impl IsTrue for Assert<true> {} + +fn main() { + let x: Arr<{usize::MAX}> = Arr {}; + //[full]~^ ERROR mismatched types + //[full]~| ERROR mismatched types +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73298.rs b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs new file mode 100644 index 000000000..3c59e1b79 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs @@ -0,0 +1,23 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::convert::AsMut; +use std::default::Default; + +trait Foo: Sized { + type Baz: Default + AsMut<[u8]>; + fn bar() { + Self::Baz::default().as_mut(); + } +} + +impl Foo for () { + type Baz = [u8; 1 * 1]; + //type Baz = [u8; 1]; +} + +fn main() { + <() as Foo>::bar(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73899.rs b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs new file mode 100644 index 000000000..d1ab1be04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo {} + +impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + +trait FooImpl<const IS_ZERO: bool> {} + +impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} + +impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {} + +fn foo<T: Foo>(_v: T) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74634.rs b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs new file mode 100644 index 000000000..cd1f7a9da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs @@ -0,0 +1,28 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait If<const COND: bool> {} +impl If<true> for () {} + +trait IsZero<const N: u8> { + type Answer; +} + +struct True; +struct False; + +impl<const N: u8> IsZero<N> for () +where (): If<{N == 0}> { + type Answer = True; +} + +trait Foobar<const N: u8> {} + +impl<const N: u8> Foobar<N> for () +where (): IsZero<N, Answer = True> {} + +impl<const N: u8> Foobar<N> for () +where (): IsZero<N, Answer = False> {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.rs b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs new file mode 100644 index 000000000..0bcb997d9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs @@ -0,0 +1,8 @@ +fn bug<'a>() +where + [(); { //~ ERROR mismatched types + let _: &'a (); //~ ERROR a non-static lifetime is not allowed in a `const` + }]: +{} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr new file mode 100644 index 000000000..e7673df0a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr @@ -0,0 +1,22 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-74713.rs:4:17 + | +LL | let _: &'a (); + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-74713.rs:3:10 + | +LL | [(); { + | __________^ +LL | | let _: &'a (); +LL | | }]: + | |_____^ expected `usize`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.rs b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs new file mode 100644 index 000000000..10247ce6b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Bool<const B: bool>; + +trait True {} + +impl True for Bool<true> {} + +fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True { + todo!() +} + +fn main() { + test::<2>(); + //~^ ERROR function takes 2 generic arguments +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr new file mode 100644 index 000000000..c587a7e15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-76595.rs:15:5 + | +LL | test::<2>(); + | ^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `T`, `P` + --> $DIR/issue-76595.rs:10:4 + | +LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True { + | ^^^^ - -------------- +help: add missing generic argument + | +LL | test::<2, P>(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs new file mode 100644 index 000000000..2fa9a71fb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a minimized reproduction for #79518 where +// during error handling for the type mismatch we would try +// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE + +trait Foo { + type Assoc: PartialEq; + const AssocInstance: Self::Assoc; + + fn foo() + where + [(); std::mem::size_of::<Self::Assoc>()]: , + { + Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()]; + //~^ Error: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr new file mode 100644 index 000000000..9baf9790e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32 + | +LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()]; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); std::mem::size_of::<Self::Assoc>()]` + | | + | expected because this is `<Self as Foo>::Assoc` + | + = note: expected associated type `<Self as Foo>::Assoc` + found array `[(); std::mem::size_of::<Self::Assoc>()]` + = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); std::mem::size_of::<Self::Assoc>()]` or calling a method that returns `<Self as Foo>::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs new file mode 100644 index 000000000..77d3c98da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the correct `param_env` is used so that +// attempting to normalize `Self::N` does not cause an ICE. + +pub struct Foo<const N: usize>; + +impl<const N: usize> Foo<N> { + pub fn foo() {} +} + +pub trait Bar { + const N: usize; + fn bar() + where + [(); Self::N]: , + { + Foo::<{ Self::N }>::foo(); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.rs b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs new file mode 100644 index 000000000..275f69953 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs @@ -0,0 +1,32 @@ +// check-fail + +// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::size_of; + +struct Inline<T> +where + [u8; size_of::<T>() + 1]: , +{ + _phantom: PhantomData<T>, + buf: [u8; size_of::<T>() + 1], +} + +impl<T> Inline<T> +where + [u8; size_of::<T>() + 1]: , +{ + pub fn new(val: T) -> Inline<T> { + todo!() + } +} + +fn main() { + let dst = Inline::<dyn Debug>::new(0); //~ ERROR + //~^ ERROR +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr new file mode 100644 index 000000000..6aa8ee13b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -0,0 +1,71 @@ +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::<dyn Debug>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::<dyn Debug>::{constant#0}` + --> $DIR/issue-80742.rs:22:10 + | +LL | [u8; size_of::<T>() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied + --> $DIR/issue-80742.rs:30:36 + | +LL | struct Inline<T> + | ---------------- function or associated item `new` not found for this struct +... +LL | let dst = Inline::<dyn Debug>::new(0); + | ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | + = note: doesn't satisfy `dyn Debug: Sized` + | +note: trait bound `dyn Debug: Sized` was not satisfied + --> $DIR/issue-80742.rs:20:6 + | +LL | impl<T> Inline<T> + | ^ --------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl<T: ?Sized> Inline<T> + | ++++++++ + +error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::<dyn Debug>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::<dyn Debug>::{constant#0}` + --> $DIR/issue-80742.rs:14:10 + | +LL | [u8; size_of::<T>() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::<dyn Debug>::new(0); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:12:15 + | +LL | struct Inline<T> + | ^ required by this bound in `Inline` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Inline<T: ?Sized> + | ++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0599. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-82268.rs b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs new file mode 100644 index 000000000..d08fc5beb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Collate<Op> { + type Pass; + type Fail; + + fn collate(self) -> (Self::Pass, Self::Fail); +} + +impl<Op> Collate<Op> for () { + type Pass = (); + type Fail = (); + + fn collate(self) -> ((), ()) { + ((), ()) + } +} + +trait CollateStep<X, Prev> { + type Pass; + type Fail; + fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail); +} + +impl<X, P, F> CollateStep<X, (P, F)> for () { + type Pass = (X, P); + type Fail = F; + + fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) { + ((x, p), f) + } +} + +struct CollateOpImpl<const MASK: u32>; +trait CollateOpStep { + type NextOp; + type Apply; +} + +impl<const MASK: u32> CollateOpStep for CollateOpImpl<MASK> +where + CollateOpImpl<{ MASK >> 1 }>: Sized, +{ + type NextOp = CollateOpImpl<{ MASK >> 1 }>; + type Apply = (); +} + +impl<H, T, Op: CollateOpStep> Collate<Op> for (H, T) +where + T: Collate<Op::NextOp>, + Op::Apply: CollateStep<H, (T::Pass, T::Fail)>, +{ + type Pass = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Pass; + type Fail = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Fail; + + fn collate(self) -> (Self::Pass, Self::Fail) { + <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::collate_step(self.0, self.1.collate()) + } +} + +fn collate<X, const MASK: u32>(x: X) -> (X::Pass, X::Fail) +where + X: Collate<CollateOpImpl<MASK>>, +{ + x.collate() +} + +fn main() { + dbg!(collate::<_, 5>(("Hello", (42, ('!', ()))))); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.rs b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs new file mode 100644 index 000000000..fac811d13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs @@ -0,0 +1,38 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {} +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR: method not compatible with trait [E0308] + self.reference.size() + //~^ ERROR: unconstrained generic constant + //~| ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr new file mode 100644 index 000000000..b693023f1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr @@ -0,0 +1,34 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:30:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error: unconstrained generic constant + --> $DIR/issue-83765.rs:32:24 + | +LL | self.reference.size() + | ^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` +note: required by a bound in `TensorSize::size` + --> $DIR/issue-83765.rs:9:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` + +error[E0308]: mismatched types + --> $DIR/issue-83765.rs:32:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected constant `DIM` + found constant `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83972.rs b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs new file mode 100644 index 000000000..0063719b8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs @@ -0,0 +1,38 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub trait Foo { + fn foo(&self); +} + +pub struct FooImpl<const N: usize>; +impl<const N: usize> Foo for FooImpl<N> { + fn foo(&self) {} +} + +pub trait Bar: 'static { + type Foo: Foo; + fn get() -> &'static Self::Foo; +} + +struct BarImpl; +impl Bar for BarImpl { + type Foo = FooImpl< + { + { 4 } + }, + >; + fn get() -> &'static Self::Foo { + &FooImpl + } +} + +pub fn boom<B: Bar>() { + B::get().foo(); +} + +fn main() { + boom::<BarImpl>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84408.rs b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs new file mode 100644 index 000000000..fb2e5590d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs @@ -0,0 +1,38 @@ +// Regression test for #84408. +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Melon<const X: usize> { + fn new(arr: [i32; X]) -> Self; + fn change<T: Melon<X>>(self) -> T; +} + +struct Foo([i32; 5]); +struct Bar<const A: usize, const B: usize>([i32; A + B]) +where + [(); A + B]: ; + +impl Melon<5> for Foo { + fn new(arr: [i32; 5]) -> Self { + Foo(arr) + } + fn change<T: Melon<5>>(self) -> T { + T::new(self.0) + } +} + +impl<const A: usize, const B: usize> Melon<{ A + B }> for Bar<A, B> +where + [(); A + B]: , +{ + fn new(arr: [i32; A + B]) -> Self { + Bar(arr) + } + fn change<T: Melon<{ A + B }>>(self) -> T { + T::new(self.0) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84669.rs b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs new file mode 100644 index 000000000..3933ff20a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs @@ -0,0 +1,30 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Output; + + fn foo() -> Self::Output; +} + +impl Foo for [u8; 3] { + type Output = [u8; 1 + 2]; + + fn foo() -> [u8; 3] { + [1u8; 3] + } +} + +fn bug<const N: usize>() +where + [u8; N]: Foo, + <[u8; N] as Foo>::Output: AsRef<[u8]>, +{ + <[u8; N]>::foo().as_ref(); +} + +fn main() { + bug::<3>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.rs b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs new file mode 100644 index 000000000..3a7f4c618 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs @@ -0,0 +1,32 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait _Contains<T> { + const does_contain: bool; +} + +trait Contains<T, const Satisfied: bool> {} + +trait Delegates<T> {} + +impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + +const fn contains<A, B>() -> bool +where + A: _Contains<B>, +{ + A::does_contain +} + +impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + +fn writes_to_path<C>(cap: &C) { + writes_to_specific_path(&cap); + //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277] + //~| ERROR: unconstrained generic constant + //~| ERROR: mismatched types [E0308] +} + +fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr new file mode 100644 index 000000000..e50ac671e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `Delegates<U>` is implemented for `T` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ------------ unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ + | | + | required by a bound introduced by this call + | + = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^----------------------^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error[E0308]: mismatched types + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::<T, U>() }` + | + = note: expected constant `true` + found constant `{ contains::<T, U>() }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-86710.rs b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs new file mode 100644 index 000000000..bdd8a21b3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::marker::PhantomData; + +fn main() { + let x = FooImpl::<BarImpl<1>> { phantom: PhantomData }; + let _ = x.foo::<BarImpl<1>>(); +} + +trait Foo<T> +where + T: Bar, +{ + fn foo<U>(&self) + where + T: Operation<U>, + <T as Operation<U>>::Output: Bar; +} + +struct FooImpl<T> +where + T: Bar, +{ + phantom: PhantomData<T>, +} + +impl<T> Foo<T> for FooImpl<T> +where + T: Bar, +{ + fn foo<U>(&self) + where + T: Operation<U>, + <T as Operation<U>>::Output: Bar, + { + <<T as Operation<U>>::Output as Bar>::error_occurs_here(); + } +} + +trait Bar { + fn error_occurs_here(); +} + +struct BarImpl<const N: usize>; + +impl<const N: usize> Bar for BarImpl<N> { + fn error_occurs_here() {} +} + +trait Operation<Rhs> { + type Output; +} + +//// Part-A: This causes error. +impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> +where + BarImpl<{ N + M }>: Sized, +{ + type Output = BarImpl<{ N + M }>; +} + +//// Part-B: This doesn't cause error. +// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> { +// type Output = BarImpl<M>; +// } + +//// Part-C: This also doesn't cause error. +// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> { +// type Output = BarImpl<{ M }>; +// } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-89851.rs b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs new file mode 100644 index 000000000..cde849d90 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs @@ -0,0 +1,12 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub const BAR: () = ice::<"">(); +pub const fn ice<const N: &'static str>() { + &10; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-90847.rs b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs new file mode 100644 index 000000000..ebc6fe141 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs @@ -0,0 +1,9 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(adt_const_params)] + +struct Foo<const A: [(); 0 + 0]> where [(); 0 + 0]: Sized; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs new file mode 100644 index 000000000..643126a46 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs @@ -0,0 +1,10 @@ +// aux-build:issue-94287-aux.rs +// build-fail + +extern crate issue_94287_aux; + +use std::str::FromStr; + +fn main() { + let _ = <issue_94287_aux::FixedI32<16>>::from_str(""); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr new file mode 100644 index 000000000..7390a0077 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr @@ -0,0 +1,15 @@ +error: failed to evaluate generic const expression + --> $DIR/auxiliary/issue-94287-aux.rs:15:8 + | +LL | If<{ FRAC <= 32 }>: True, + | ^^^^^^^^^^^^^^ + | + = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]` +help: consider enabling this feature + --> $DIR/issue-94287.rs:1:1 + | +LL | #![feature(generic_const_exprs)] + | + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94293.rs b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs new file mode 100644 index 000000000..713c5d89a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(const_evaluatable_unchecked)] + +pub struct If<const CONDITION: bool>; +pub trait True {} +impl True for If<true> {} + +pub struct FixedI8<const FRAC: u32> { + pub bits: i8, +} + +impl<const FRAC_LHS: u32, const FRAC_RHS: u32> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> +where + If<{ FRAC_RHS <= 8 }>: True, +{ + fn eq(&self, _rhs: &FixedI8<FRAC_RHS>) -> bool { + unimplemented!() + } +} + +impl<const FRAC: u32> PartialEq<i8> for FixedI8<FRAC> { + fn eq(&self, rhs: &i8) -> bool { + let rhs_as_fixed = FixedI8::<0> { bits: *rhs }; + PartialEq::eq(self, &rhs_as_fixed) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs new file mode 100644 index 000000000..67e30232e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub const fn new() -> Self { + Self { + changes: [0; CHANGES.len()], + } + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr new file mode 100644 index 000000000..1cceaece7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs new file mode 100644 index 000000000..00568a089 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub fn combine(&mut self, other: &Self) { + for _change in &self.changes {} + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr new file mode 100644 index 000000000..774e842bc --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99647.rs b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs new file mode 100644 index 000000000..f797beda8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99705.rs b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs new file mode 100644 index 000000000..75b57b621 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs @@ -0,0 +1,33 @@ +// check-pass +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +pub trait MyIterator { + type Output; +} + +pub trait Foo { + const ABC: usize; +} + +pub struct IteratorStruct<const N: usize>{ + +} + +pub struct Bar<const N: usize> { + pub data: [usize; N] +} + +impl<const N: usize> MyIterator for IteratorStruct<N> { + type Output = Bar<N>; +} + +pub fn test1<T: Foo>() -> impl MyIterator<Output = Bar<{T::ABC}>> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} + +pub trait Baz<const N: usize>{} +impl<const N: usize> Baz<N> for Bar<N> {} +pub fn test2<T: Foo>() -> impl MyIterator<Output = impl Baz<{ T::ABC }>> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} diff --git a/tests/ui/const-generics/generic_const_exprs/less_than.rs b/tests/ui/const-generics/generic_const_exprs/less_than.rs new file mode 100644 index 000000000..2e9af1bf4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/less_than.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized { + Foo +} + +fn main() { + let _: Foo<true> = test::<12>(); + let _: Foo<false> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.rs b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs new file mode 100644 index 000000000..cd5d76dd9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// We do not yet want to support let-bindings in abstract consts, +// so this test should keep failing for now. +fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + //~^ ERROR overly complex generic constant + //~| ERROR overly complex generic constant + Default::default() +} + +fn main() { + let x = test::<31>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr new file mode 100644 index 000000000..823a4f8a1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -0,0 +1,20 @@ +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:68 + | +LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:35 + | +LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs new file mode 100644 index 000000000..2bd3c801f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn complex_maths<T>(n : usize) -> usize { + 2 * n + 1 +} + +struct Example<T, const N: usize> { + a: [f32; N], + b: [f32; complex_maths::<T>(N)], + //~^ ERROR unconstrained + c: T, +} diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr new file mode 100644 index 000000000..7b41e39b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/needs_where_clause.rs:11:6 + | +LL | b: [f32; complex_maths::<T>(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs new file mode 100644 index 000000000..7e5022817 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn callee<const M2: usize>() -> usize +where + [u8; M2 + 1]: Sized, +{ + M2 +} + +fn caller<const N1: usize>() -> usize +where + [u8; N1 + 1]: Sized, + [u8; (N1 + 1) + 1]: Sized, +{ + callee::<{ N1 + 1 }>() +} + +fn main() { + assert_eq!(caller::<4>(), 5); +} + +// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs new file mode 100644 index 000000000..769e3ae68 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Generic<const K: u64>; + +struct ConstU64<const K: u64>; + +impl<const K: u64> Generic<K> +where + ConstU64<{ K - 1 }>: , +{ + fn foo(self) -> u64 { + K + } +} + +impl<const K: u64> Generic<K> +where + ConstU64<{ K - 1 }>: , + ConstU64<{ K + 1 }>: , + ConstU64<{ K + 1 - 1 }>: , +{ + fn bar(self) -> u64 { + let x: Generic<{ K + 1 }> = Generic; + x.foo() + } +} + +fn main() { + assert_eq!((Generic::<10>).bar(), 11); +} + +// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the +// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs new file mode 100644 index 000000000..316887e5e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs @@ -0,0 +1,34 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn zero_init<const N: usize>() -> Substs1<N> +where + [u8; N + 1]: , +{ + Substs1([0; N + 1]) +} +struct Substs1<const N: usize>([u8; N + 1]) +where + [(); N + 1]: ; + +fn substs2<const M: usize>() -> Substs1<{ M * 2 }> +where + [(); { M * 2 } + 1]: , +{ + zero_init::<{ M * 2 }>() +} + +fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }> +where + [(); (L - 1) * 2 + 1]: , +{ + substs2::<{ L - 1 }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 3]); +} + +// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the +// ``{ N + 1 }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs new file mode 100644 index 000000000..d45a6465b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs @@ -0,0 +1,29 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_parens, unused_braces)] + +fn zero_init<const N: usize>() -> Substs1<{ (N) }> +where + [u8; { (N) }]: , +{ + Substs1([0; { (N) }]) +} + +struct Substs1<const N: usize>([u8; { (N) }]) +where + [(); { (N) }]: ; + +fn substs2<const M: usize>() -> Substs1<{ (M) }> { + zero_init::<{ (M) }>() +} + +fn substs3<const L: usize>() -> Substs1<{ (L) }> { + substs2::<{ (L) }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 2]); +} + +// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the +// ``{ (N) }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/no_dependence.rs b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs new file mode 100644 index 000000000..db8dc6ed4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs @@ -0,0 +1,13 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn two_args<const N: usize, const M: usize>() -> [u8; M + 2] { + [0; M + 2] +} + +fn yay<const N: usize>() -> [u8; 4] { + two_args::<N, 2>() // no lint +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs new file mode 100644 index 000000000..9c5de0317 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs @@ -0,0 +1,29 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused)] + +const fn complex_maths(n : usize) -> usize { + 2 * n + 1 +} + +pub struct Example<const N: usize> { + a: [f32; N], + b: [f32; complex_maths(N)], + //~^ ERROR unconstrained generic +} + +impl<const N: usize> Example<N> { + pub fn new() -> Self { + Self { + a: [0.; N], + b: [0.; complex_maths(N)], + } + } +} + +impl Example<2> { + pub fn sum(&self) -> f32 { + self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>() + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr new file mode 100644 index 000000000..3e5c2f5ca --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/no_where_clause.rs:10:6 + | +LL | b: [f32; complex_maths(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs new file mode 100644 index 000000000..1254b4435 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs @@ -0,0 +1,16 @@ +// aux-build:anon_const_non_local.rs + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate anon_const_non_local; + +fn bar<const M: usize>() +where + [(); M + 1]:, +{ + let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::<M>(); + //~^ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr new file mode 100644 index 000000000..3926c830a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non_local_anon_const_diagnostics.rs:12:43 + | +LL | let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::<M>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `anon_const_non_local::::foo::{constant#0}` + | + = note: expected constant `2` + found constant `anon_const_non_local::::foo::{constant#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs new file mode 100644 index 000000000..b37b354ae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_braces)] + +#[rustfmt::skip] +fn foo<const N: usize>() { + bar::<{{{{{{ N }}}}}}>(); +} + +fn bar<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs new file mode 100644 index 000000000..24d333aba --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + + +const fn bar<T: ?Sized>() -> usize { 7 } + +trait Foo { + fn test(&self) -> [u8; bar::<Self>()]; +} + +impl Foo for () { + fn test(&self) -> [u8; bar::<Self>()] { + [0; bar::<Self>()] + } +} + +fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr new file mode 100644 index 000000000..4e1d71f15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-ret.rs:17:16 + | +LL | fn use_dyn(v: &dyn Foo) { + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-safety-err-ret.rs:8:23 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) -> [u8; bar::<Self>()]; + | ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type + = help: consider moving `test` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs new file mode 100644 index 000000000..42c1cc507 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(where_clauses_object_safety)] + + +const fn bar<T: ?Sized>() -> usize { 7 } + +trait Foo { + fn test(&self) where [u8; bar::<Self>()]: Sized; + //~^ ERROR the trait `Foo` cannot be made into an object + //~| WARN this was previously accepted by the compiler but is being phased out +} + +impl Foo for () { + fn test(&self) where [u8; bar::<Self>()]: Sized {} +} + +fn use_dyn(v: &dyn Foo) { + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr new file mode 100644 index 000000000..440cf457e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr @@ -0,0 +1,24 @@ +error: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | fn test(&self) where [u8; bar::<Self>()]: Sized; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443> +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) where [u8; bar::<Self>()]: Sized; + | ^^^^ ...because method `test` references the `Self` type in its `where` clause + = help: consider moving `test` to another trait +note: the lint level is defined here + --> $DIR/object-safety-err-where-bounds.rs:3:9 + | +LL | #![deny(where_clauses_object_safety)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs new file mode 100644 index 000000000..79e9834b5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + fn test(&self) -> [u8; N + 1]; +} + +impl<const N: usize> Foo<N> for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn(&()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr new file mode 100644 index 000000000..59e9fee1e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr @@ -0,0 +1,19 @@ +error[E0284]: type annotations needed + --> $DIR/object-safety-ok-infer-err.rs:19:5 + | +LL | use_dyn(&()); + | ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn` + | +note: required by a bound in `use_dyn` + --> $DIR/object-safety-ok-infer-err.rs:14:55 + | +LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + | ^^^^^ required by this bound in `use_dyn` +help: consider specifying the generic argument + | +LL | use_dyn::<N>(&()); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs new file mode 100644 index 000000000..f4c89f623 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo<const N: usize> { + fn test(&self) -> [u8; N + 1]; +} + +impl<const N: usize> Foo<N> for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn::<3>(&()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs new file mode 100644 index 000000000..e7c8e4f66 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs @@ -0,0 +1,24 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait True {} + +struct Is<const V: bool>; + +impl True for Is<true> {} + +fn g<T>() +//~^ NOTE required by a bound in this +where + Is<{ std::mem::size_of::<T>() == 0 }>: True, + //~^ NOTE required by a bound in `g` + //~| NOTE required by this bound in `g` +{ +} + +fn main() { + g::<usize>(); + //~^ ERROR mismatched types + //~| NOTE expected `false`, found `true` + //~| NOTE expected constant `false` +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr new file mode 100644 index 000000000..a253ec676 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/obligation-cause.rs:20:5 + | +LL | g::<usize>(); + | ^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `g` + --> $DIR/obligation-cause.rs:13:44 + | +LL | fn g<T>() + | - required by a bound in this +... +LL | Is<{ std::mem::size_of::<T>() == 0 }>: True, + | ^^^^ required by this bound in `g` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.rs b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs new file mode 100644 index 000000000..cae54df4c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Arr<const N: usize> = [u8; N - 1]; +//~^ ERROR evaluation of `Arr::<0>::{constant#0}` failed + +fn test<const N: usize>() -> Arr<N> +where + [u8; N - 1]: Sized, + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed +{ + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr new file mode 100644 index 000000000..a25fa56b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:9:10 + | +LL | [u8; N - 1]: Sized, + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error[E0080]: evaluation of `Arr::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:4:33 + | +LL | type Arr<const N: usize> = [u8; N - 1]; + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs new file mode 100644 index 000000000..d6574a3aa --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn make_array<const M: usize>() -> [(); M + 1] { + [(); M + 1] +} + +fn foo<const N: usize>() -> [(); (N * 2) + 1] { + make_array::<{ N * 2 }>() +} + +fn main() { + assert_eq!(foo::<10>(), [(); 10 * 2 + 1]) +} + +// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const diff --git a/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs new file mode 100644 index 000000000..d058b3638 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs @@ -0,0 +1,14 @@ +// check-pass +// Test that we correctly substitute generic arguments for type aliases. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Alias<T, const N: usize> = [T; N + 1]; + +fn foo<const M: usize>() -> Alias<u32, M> where [u8; M + 1]: Sized { + [0; M + 1] +} + +fn main() { + foo::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 000000000..c0404d35b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -0,0 +1,35 @@ +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +#![allow(incomplete_features)] + +// test `N + N` unifies with explicit function calls for non-builtin-types +#[derive(PartialEq, Eq)] +struct Foo(u8); + +impl const std::ops::Add for Foo { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + self + } +} + +struct Evaluatable<const N: Foo>; + +fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) { + bar::<{ std::ops::Add::add(N, N) }>(); +} + +fn bar<const N: Foo>() {} + +// test that `N + N` unifies with explicit function calls for builin-types +struct Evaluatable2<const N: usize>; + +fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) { + bar2::<{ std::ops::Add::add(N, N) }>(); + //~^ error: unconstrained generic constant + // FIXME(generic_const_exprs) make this not an error +} + +fn bar2<const N: usize>() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 000000000..d18c7916f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:28:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/unop.rs b/tests/ui/const-generics/generic_const_exprs/unop.rs new file mode 100644 index 000000000..c12fef083 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unop.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const B: bool>; + +fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized { + Foo +} + +fn main() { + let _: Foo<false> = test::<12>(); + let _: Foo<true> = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs new file mode 100644 index 000000000..9580f8a7f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs @@ -0,0 +1,6 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +struct Foo<const N: usize, const M: usize = { N + 1 }>; +struct Bar<const N: usize>(Foo<N, 3>); +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.rs b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs new file mode 100644 index 000000000..c1bf19e0f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs @@ -0,0 +1,25 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn add<const N: usize>() -> [u8; { N + 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn div<const N: usize>() -> [u8; { N / 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +const fn foo(n: usize) {} + +fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn main() { + add::<12>(); + div::<9>(); + fn_call::<14>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr new file mode 100644 index 000000000..265a3b9d2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -0,0 +1,29 @@ +error: overly complex generic constant + --> $DIR/unused_expr.rs:4:34 + | +LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:9:34 + | +LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:16:38 + | +LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] { + | ^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 3 previous errors + |