Skip to content

Commit 6636916

Browse files
committed
Add UI tests for generic const items
1 parent a011dd9 commit 6636916

34 files changed

+826
-1
lines changed

src/tools/tidy/src/ui_tests.rs

Lines changed: 1 addition & 1 deletion
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 = 1893;
14-
const ROOT_ENTRY_LIMIT: usize = 871;
14+
const ROOT_ENTRY_LIMIT: usize = 872;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
3+
#![feature(generic_const_items, associated_const_equality)]
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-const-items/basic.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// check-pass
2+
3+
// Basic usage patterns of free & associated generic const items.
4+
5+
#![feature(generic_const_items)]
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+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![feature(generic_const_items)]
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() {}
Lines changed: 66 additions & 0 deletions
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`.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// check-pass
2+
3+
// Test that we can call methods from const trait impls inside of generic const items.
4+
5+
#![feature(generic_const_items, const_trait_impl)]
6+
#![allow(incomplete_features)]
7+
#![crate_type = "lib"]
8+
9+
// FIXME(generic_const_items): Interpret `~const` as always-const.
10+
const CREATE<T: ~const Create>: T = T::create();
11+
12+
pub const K0: i32 = CREATE::<i32>;
13+
pub const K1: i32 = CREATE; // arg inferred
14+
15+
#[const_trait]
16+
trait Create {
17+
fn create() -> Self;
18+
}
19+
20+
impl const Create for i32 {
21+
fn create() -> i32 {
22+
4096
23+
}
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(generic_const_items)]
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_const_items): 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() {}
Lines changed: 27 additions & 0 deletions
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+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(generic_const_items)]
2+
#![allow(incomplete_features)]
3+
4+
// Check that we forbid elided lifetimes inside the generics of const items.
5+
6+
const K<T>: () = ()
7+
where
8+
&T: Copy; //~ ERROR `&` without an explicit lifetime name cannot be used here
9+
10+
const I<const S: &str>: &str = "";
11+
//~^ ERROR `&` without an explicit lifetime name cannot be used here
12+
//~| ERROR `&str` is forbidden as the type of a const generic parameter
13+
14+
const B<T: Trait<'_>>: () = (); //~ ERROR `'_` cannot be used here
15+
16+
trait Trait<'a> {}
17+
18+
fn main() {}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0637]: `&` without an explicit lifetime name cannot be used here
2+
--> $DIR/elided-lifetimes.rs:8:5
3+
|
4+
LL | &T: Copy;
5+
| ^ explicit lifetime name needed here
6+
|
7+
help: consider introducing a higher-ranked lifetime here
8+
|
9+
LL | for<'a> &'a T: Copy;
10+
| +++++++ ++
11+
12+
error[E0637]: `&` without an explicit lifetime name cannot be used here
13+
--> $DIR/elided-lifetimes.rs:10:18
14+
|
15+
LL | const I<const S: &str>: &str = "";
16+
| ^ explicit lifetime name needed here
17+
18+
error[E0637]: `'_` cannot be used here
19+
--> $DIR/elided-lifetimes.rs:14:18
20+
|
21+
LL | const B<T: Trait<'_>>: () = ();
22+
| ^^ `'_` is a reserved lifetime name
23+
24+
error: `&str` is forbidden as the type of a const generic parameter
25+
--> $DIR/elided-lifetimes.rs:10:18
26+
|
27+
LL | const I<const S: &str>: &str = "";
28+
| ^^^^
29+
|
30+
= note: the only supported types are integers, `bool` and `char`
31+
= help: more complex types are supported with `#![feature(adt_const_params)]`
32+
33+
error: aborting due to 4 previous errors
34+
35+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 31 additions & 0 deletions
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 const items that appear inside associated consts by
7+
// adding a (makeshift) "evaluatable"-bound to the item.
8+
9+
#![feature(generic_const_items, 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+
}
Lines changed: 10 additions & 0 deletions
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+

0 commit comments

Comments
 (0)