Skip to content

Commit 05c1549

Browse files
committed
Add UI tests for generic consts
1 parent eee6d3d commit 05c1549

34 files changed

+811
-1
lines changed

src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
1111
const ENTRY_LIMIT: usize = 900;
1212
// FIXME: The following limits should be reduced eventually.
1313
const ISSUES_ENTRY_LIMIT: usize = 1896;
14-
const ROOT_ENTRY_LIMIT: usize = 870;
14+
const ROOT_ENTRY_LIMIT: usize = 871;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
3+
#![feature(generic_consts, associated_const_equality, non_lifetime_binders)]
4+
#![allow(incomplete_features)]
5+
6+
trait Owner {
7+
const C<const N: u32>: u32;
8+
const K<const N: u32>: u32;
9+
}
10+
11+
impl Owner for () {
12+
const C<const N: u32>: u32 = N;
13+
const K<const N: u32>: u32 = N + 1;
14+
}
15+
16+
fn take0<const N: u32>(_: impl Owner<C<N> = {N}>) {}
17+
fn take1(_: impl Owner<K<99> = 100>) {}
18+
19+
fn main() {
20+
take0::<128>(());
21+
take1(());
22+
}

tests/ui/generic-consts/basic.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// check-pass
2+
3+
// Basic usage patterns of free & associated generic consts.
4+
5+
#![feature(generic_consts)]
6+
#![allow(incomplete_features)]
7+
8+
fn main() {
9+
const NULL<T>: Option<T> = None::<T>;
10+
const NOTHING<T>: Option<T> = None; // arg inferred
11+
12+
let _ = NOTHING::<String>;
13+
let _: Option<u8> = NULL; // arg inferred
14+
15+
const IDENTITY<const X: u64>: u64 = X;
16+
17+
const COUNT: u64 = IDENTITY::<48>;
18+
const AMOUNT: u64 = IDENTITY::<COUNT>;
19+
const NUMBER: u64 = IDENTITY::<{ AMOUNT * 2 }>;
20+
let _ = NUMBER;
21+
let _ = IDENTITY::<0>;
22+
23+
let _ = match 0 {
24+
IDENTITY::<1> => 2,
25+
IDENTITY::<{ 1 + 1 }> => 4,
26+
_ => 0,
27+
};
28+
29+
const CREATE<I: Inhabited>: I = I::PROOF;
30+
let _ = CREATE::<u64>;
31+
let _: u64 = CREATE; // arg inferred
32+
33+
let _ = <() as Main<u64>>::MAKE::<u64>;
34+
let _: (u64, u64) = <()>::MAKE; // args inferred
35+
}
36+
37+
pub fn usage<'any>() {
38+
const REGION_POLY<'a>: &'a () = &();
39+
40+
let _: &'any () = REGION_POLY::<'any>;
41+
let _: &'any () = REGION_POLY::<'_>;
42+
let _: &'static () = REGION_POLY;
43+
}
44+
45+
trait Main<O> {
46+
type Output<I>;
47+
const MAKE<I: Inhabited>: Self::Output<I>;
48+
}
49+
50+
impl<O: Inhabited> Main<O> for () {
51+
type Output<I> = (O, I);
52+
const MAKE<I: Inhabited>: Self::Output<I> = (O::PROOF, I::PROOF);
53+
}
54+
55+
trait Inhabited {
56+
const PROOF: Self;
57+
}
58+
59+
impl Inhabited for u64 {
60+
const PROOF: Self = 512;
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![feature(generic_consts)]
2+
#![allow(incomplete_features)]
3+
4+
trait Trait<P> {
5+
const A: ();
6+
const B<const K: u64, const Q: u64>: u64;
7+
const C<T>: T;
8+
const D<const N: usize>: usize;
9+
10+
const E: usize;
11+
const F<T: PartialEq>: ();
12+
}
13+
14+
impl<P> Trait<P> for () {
15+
const A<T>: () = ();
16+
//~^ ERROR const `A` has 1 type parameter but its trait declaration has 0 type parameters
17+
const B<const K: u64>: u64 = 0;
18+
//~^ ERROR const `B` has 1 const parameter but its trait declaration has 2 const parameters
19+
const C<'a>: &'a str = "";
20+
//~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
21+
const D<const N: u16>: u16 = N;
22+
//~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
23+
24+
const E: usize = 1024
25+
where
26+
P: Copy; //~ ERROR impl has stricter requirements than trait
27+
const F<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters
2+
--> $DIR/compare-impl-item.rs:15:13
3+
|
4+
LL | const A: ();
5+
| - expected 0 type parameters
6+
...
7+
LL | const A<T>: () = ();
8+
| ^ found 1 type parameter
9+
10+
error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters
11+
--> $DIR/compare-impl-item.rs:17:13
12+
|
13+
LL | const B<const K: u64, const Q: u64>: u64;
14+
| ------------ ------------
15+
| |
16+
| expected 2 const parameters
17+
...
18+
LL | const B<const K: u64>: u64 = 0;
19+
| ^^^^^^^^^^^^ found 1 const parameter
20+
21+
error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter
22+
--> $DIR/compare-impl-item.rs:19:13
23+
|
24+
LL | const C<T>: T;
25+
| - expected 1 type parameter
26+
...
27+
LL | const C<'a>: &'a str = "";
28+
| ^^ found 0 type parameters
29+
30+
error[E0053]: const `D` has an incompatible generic parameter for trait `Trait`
31+
--> $DIR/compare-impl-item.rs:21:13
32+
|
33+
LL | trait Trait<P> {
34+
| -----
35+
...
36+
LL | const D<const N: usize>: usize;
37+
| -------------- expected const parameter of type `usize`
38+
...
39+
LL | impl<P> Trait<P> for () {
40+
| -----------------------
41+
...
42+
LL | const D<const N: u16>: u16 = N;
43+
| ^^^^^^^^^^^^ found const parameter of type `u16`
44+
45+
error[E0276]: impl has stricter requirements than trait
46+
--> $DIR/compare-impl-item.rs:26:12
47+
|
48+
LL | const E: usize;
49+
| -------------- definition of `E` from trait
50+
...
51+
LL | P: Copy;
52+
| ^^^^ impl has extra requirement `P: Copy`
53+
54+
error[E0276]: impl has stricter requirements than trait
55+
--> $DIR/compare-impl-item.rs:27:16
56+
|
57+
LL | const F<T: PartialEq>: ();
58+
| ------------------------- definition of `F` from trait
59+
...
60+
LL | const F<T: Eq>: () = ();
61+
| ^^ impl has extra requirement `T: Eq`
62+
63+
error: aborting due to 6 previous errors
64+
65+
Some errors have detailed explanations: E0049, E0053, E0276.
66+
For more information about an error, try `rustc --explain E0049`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
3+
// Test that we can call methods from const trait impls from inside of generic consts.
4+
5+
#![feature(generic_consts, const_trait_impl)]
6+
#![allow(incomplete_features)]
7+
#![crate_type = "lib"]
8+
9+
const CREATE<T: ~const Create>: T = T::create();
10+
11+
pub const K0: i32 = CREATE::<i32>;
12+
pub const K1: i32 = CREATE; // arg inferred
13+
14+
#[const_trait]
15+
trait Create {
16+
fn create() -> Self;
17+
}
18+
19+
impl const Create for i32 {
20+
fn create() -> i32 {
21+
4096
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(generic_consts)]
2+
#![allow(incomplete_features)]
3+
4+
trait Tr<P> {
5+
const K: ()
6+
where
7+
P: Copy
8+
where
9+
P: Eq;
10+
//~^ ERROR cannot define duplicate `where` clauses on an item
11+
}
12+
13+
// Test that we error on the first where-clause but also that we don't suggest to swap it with the
14+
// body as it would conflict with the second where-clause.
15+
// FIXME(generic_consts): We should provide a structured sugg to merge the 1st into the 2nd WC.
16+
17+
impl<P> Tr<P> for () {
18+
const K: ()
19+
where
20+
P: Eq
21+
= ()
22+
where
23+
P: Copy;
24+
//~^^^^^ ERROR where clauses are not allowed before const item bodies
25+
}
26+
27+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: cannot define duplicate `where` clauses on an item
2+
--> $DIR/duplicate-where-clause.rs:9:9
3+
|
4+
LL | P: Copy
5+
| - previous `where` clause starts here
6+
LL | where
7+
LL | P: Eq;
8+
| ^
9+
|
10+
help: consider joining the two `where` clauses into one
11+
|
12+
LL | P: Copy,
13+
| ~
14+
15+
error: where clauses are not allowed before const item bodies
16+
--> $DIR/duplicate-where-clause.rs:19:5
17+
|
18+
LL | const K: ()
19+
| - while parsing this const item
20+
LL | / where
21+
LL | | P: Eq
22+
| |_____________^ unexpected where clause
23+
LL | = ()
24+
| -- the item body
25+
26+
error: aborting due to 2 previous errors
27+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// This is a regression test for issue #104400.
2+
3+
// revisions: unconstrained constrained
4+
//[constrained] check-pass
5+
6+
// Test that we can constrain generic consts that appear inside associated consts by
7+
// adding a (makeshift) "evaluatable"-bound to the item.
8+
9+
#![feature(generic_consts, generic_const_exprs)]
10+
#![allow(incomplete_features)]
11+
12+
trait Trait {
13+
const LEN: usize;
14+
15+
#[cfg(unconstrained)]
16+
const ARRAY: [i32; Self::LEN]; //[unconstrained]~ ERROR unconstrained generic constant
17+
18+
#[cfg(constrained)]
19+
const ARRAY: [i32; Self::LEN]
20+
where
21+
[(); Self::LEN]:;
22+
}
23+
24+
impl Trait for () {
25+
const LEN: usize = 2;
26+
const ARRAY: [i32; Self::LEN] = [360, 720];
27+
}
28+
29+
fn main() {
30+
let [_, _] = <() as Trait>::ARRAY;
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unconstrained generic constant
2+
--> $DIR/evaluatable-bounds.rs:16:5
3+
|
4+
LL | const ARRAY: [i32; Self::LEN];
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); Self::LEN]:`
8+
9+
error: aborting due to previous error
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
pub trait Trait<A> {
2+
const ONE<T>: i32;
3+
//~^ ERROR generic consts are experimental
4+
5+
const TWO: ()
6+
where
7+
A: Copy;
8+
//~^^ ERROR generic consts are experimental
9+
}
10+
11+
const CONST<T>: i32 = 0;
12+
//~^ ERROR generic consts are experimental
13+
14+
const EMPTY<>: i32 = 0;
15+
//~^ ERROR generic consts are experimental
16+
17+
const TRUE: () = ()
18+
where
19+
String: Clone;
20+
//~^^ ERROR generic consts are experimental
21+
22+
// Ensure that we flag generic consts inside macro calls as well:
23+
24+
macro_rules! discard {
25+
($item:item) => {}
26+
}
27+
28+
discard! { const FREE<T>: () = (); }
29+
//~^ ERROR generic consts are experimental
30+
31+
discard! { impl () { const ASSOC<const N: ()>: () = (); } }
32+
//~^ ERROR generic consts are experimental
33+
34+
discard! { impl () { const ASSOC: i32 = 0 where String: Copy; } }
35+
//~^ ERROR generic consts are experimental
36+
37+
fn main() {}

0 commit comments

Comments
 (0)