about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2023-07-10 03:10:03 +0200
committerLeón Orell Valerian Liehr <me@fmease.dev>2023-07-28 22:23:20 +0200
commit6636916b666d067277ee31c1eab1970912b6eb8a (patch)
treea92fb7e60577b229e8761669d807a71de46ce3f2
parenta011dd9dacef28a53c868fa537c45fe81415c733 (diff)
downloadrust-6636916b666d067277ee31c1eab1970912b6eb8a.tar.gz
rust-6636916b666d067277ee31c1eab1970912b6eb8a.zip
Add UI tests for generic const items
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/ui/generic-const-items/associated-const-equality.rs22
-rw-r--r--tests/ui/generic-const-items/basic.rs61
-rw-r--r--tests/ui/generic-const-items/compare-impl-item.rs30
-rw-r--r--tests/ui/generic-const-items/compare-impl-item.stderr66
-rw-r--r--tests/ui/generic-const-items/const-trait-impl.rs24
-rw-r--r--tests/ui/generic-const-items/duplicate-where-clause.rs27
-rw-r--r--tests/ui/generic-const-items/duplicate-where-clause.stderr27
-rw-r--r--tests/ui/generic-const-items/elided-lifetimes.rs18
-rw-r--r--tests/ui/generic-const-items/elided-lifetimes.stderr35
-rw-r--r--tests/ui/generic-const-items/evaluatable-bounds.rs31
-rw-r--r--tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr10
-rw-r--r--tests/ui/generic-const-items/feature-gate-generic_const_items.rs37
-rw-r--r--tests/ui/generic-const-items/feature-gate-generic_const_items.stderr77
-rw-r--r--tests/ui/generic-const-items/inference-failure.rs15
-rw-r--r--tests/ui/generic-const-items/inference-failure.stderr20
-rw-r--r--tests/ui/generic-const-items/misplaced-where-clause.fixed18
-rw-r--r--tests/ui/generic-const-items/misplaced-where-clause.rs20
-rw-r--r--tests/ui/generic-const-items/misplaced-where-clause.stderr36
-rw-r--r--tests/ui/generic-const-items/parameter-defaults.rs14
-rw-r--r--tests/ui/generic-const-items/parameter-defaults.stderr8
-rw-r--r--tests/ui/generic-const-items/recursive.rs12
-rw-r--r--tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs12
-rw-r--r--tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr18
-rw-r--r--tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs12
-rw-r--r--tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr11
-rw-r--r--tests/ui/generic-const-items/unsatisfied-bounds.rs34
-rw-r--r--tests/ui/generic-const-items/unsatisfied-bounds.stderr62
-rw-r--r--tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.rs12
-rw-r--r--tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr9
-rw-r--r--tests/ui/generic-const-items/unsatisfied-outlives-bounds.rs17
-rw-r--r--tests/ui/generic-const-items/unsatisfied-outlives-bounds.stderr18
-rw-r--r--tests/ui/parser/generic-statics.rs4
-rw-r--r--tests/ui/parser/generic-statics.stderr8
34 files changed, 826 insertions, 1 deletions
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index ecbd2f79e36..6cc7fbcacaf 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1893;
-const ROOT_ENTRY_LIMIT: usize = 871;
+const ROOT_ENTRY_LIMIT: usize = 872;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/ui/generic-const-items/associated-const-equality.rs b/tests/ui/generic-const-items/associated-const-equality.rs
new file mode 100644
index 00000000000..785d3aa5018
--- /dev/null
+++ b/tests/ui/generic-const-items/associated-const-equality.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(generic_const_items, associated_const_equality)]
+#![allow(incomplete_features)]
+
+trait Owner {
+    const C<const N: u32>: u32;
+    const K<const N: u32>: u32;
+}
+
+impl Owner for () {
+    const C<const N: u32>: u32 = N;
+    const K<const N: u32>: u32 = N + 1;
+}
+
+fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
+fn take1(_: impl Owner<K<99> = 100>) {}
+
+fn main() {
+    take0::<128>(());
+    take1(());
+}
diff --git a/tests/ui/generic-const-items/basic.rs b/tests/ui/generic-const-items/basic.rs
new file mode 100644
index 00000000000..73bfa803acd
--- /dev/null
+++ b/tests/ui/generic-const-items/basic.rs
@@ -0,0 +1,61 @@
+// check-pass
+
+// Basic usage patterns of free & associated generic const items.
+
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+fn main() {
+    const NULL<T>: Option<T> = None::<T>;
+    const NOTHING<T>: Option<T> = None; // arg inferred
+
+    let _ = NOTHING::<String>;
+    let _: Option<u8> = NULL; // arg inferred
+
+    const IDENTITY<const X: u64>: u64 = X;
+
+    const COUNT: u64 = IDENTITY::<48>;
+    const AMOUNT: u64 = IDENTITY::<COUNT>;
+    const NUMBER: u64 = IDENTITY::<{ AMOUNT * 2 }>;
+    let _ = NUMBER;
+    let _ = IDENTITY::<0>;
+
+    let _ = match 0 {
+        IDENTITY::<1> => 2,
+        IDENTITY::<{ 1 + 1 }> => 4,
+        _ => 0,
+    };
+
+    const CREATE<I: Inhabited>: I = I::PROOF;
+    let _ = CREATE::<u64>;
+    let _: u64 = CREATE; // arg inferred
+
+    let _ = <() as Main<u64>>::MAKE::<u64>;
+    let _: (u64, u64) = <()>::MAKE; // args inferred
+}
+
+pub fn usage<'any>() {
+    const REGION_POLY<'a>: &'a () = &();
+
+    let _: &'any () = REGION_POLY::<'any>;
+    let _: &'any () = REGION_POLY::<'_>;
+    let _: &'static () = REGION_POLY;
+}
+
+trait Main<O> {
+    type Output<I>;
+    const MAKE<I: Inhabited>: Self::Output<I>;
+}
+
+impl<O: Inhabited> Main<O> for () {
+    type Output<I> = (O, I);
+    const MAKE<I: Inhabited>: Self::Output<I> = (O::PROOF, I::PROOF);
+}
+
+trait Inhabited {
+    const PROOF: Self;
+}
+
+impl Inhabited for u64 {
+    const PROOF: Self = 512;
+}
diff --git a/tests/ui/generic-const-items/compare-impl-item.rs b/tests/ui/generic-const-items/compare-impl-item.rs
new file mode 100644
index 00000000000..01e4477c698
--- /dev/null
+++ b/tests/ui/generic-const-items/compare-impl-item.rs
@@ -0,0 +1,30 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+trait Trait<P> {
+    const A: ();
+    const B<const K: u64, const Q: u64>: u64;
+    const C<T>: T;
+    const D<const N: usize>: usize;
+
+    const E: usize;
+    const F<T: PartialEq>: ();
+}
+
+impl<P> Trait<P> for () {
+    const A<T>: () = ();
+    //~^ ERROR const `A` has 1 type parameter but its trait declaration has 0 type parameters
+    const B<const K: u64>: u64 = 0;
+    //~^ ERROR const `B` has 1 const parameter but its trait declaration has 2 const parameters
+    const C<'a>: &'a str = "";
+    //~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
+    const D<const N: u16>: u16 = N;
+    //~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
+
+    const E: usize = 1024
+    where
+        P: Copy; //~ ERROR impl has stricter requirements than trait
+    const F<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/compare-impl-item.stderr b/tests/ui/generic-const-items/compare-impl-item.stderr
new file mode 100644
index 00000000000..8610d8cba00
--- /dev/null
+++ b/tests/ui/generic-const-items/compare-impl-item.stderr
@@ -0,0 +1,66 @@
+error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/compare-impl-item.rs:15:13
+   |
+LL |     const A: ();
+   |            - expected 0 type parameters
+...
+LL |     const A<T>: () = ();
+   |             ^ found 1 type parameter
+
+error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters
+  --> $DIR/compare-impl-item.rs:17:13
+   |
+LL |     const B<const K: u64, const Q: u64>: u64;
+   |             ------------  ------------
+   |             |
+   |             expected 2 const parameters
+...
+LL |     const B<const K: u64>: u64 = 0;
+   |             ^^^^^^^^^^^^ found 1 const parameter
+
+error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/compare-impl-item.rs:19:13
+   |
+LL |     const C<T>: T;
+   |             - expected 1 type parameter
+...
+LL |     const C<'a>: &'a str = "";
+   |             ^^ found 0 type parameters
+
+error[E0053]: const `D` has an incompatible generic parameter for trait `Trait`
+  --> $DIR/compare-impl-item.rs:21:13
+   |
+LL | trait Trait<P> {
+   |       -----
+...
+LL |     const D<const N: usize>: usize;
+   |             -------------- expected const parameter of type `usize`
+...
+LL | impl<P> Trait<P> for () {
+   | -----------------------
+...
+LL |     const D<const N: u16>: u16 = N;
+   |             ^^^^^^^^^^^^ found const parameter of type `u16`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/compare-impl-item.rs:26:12
+   |
+LL |     const E: usize;
+   |     -------------- definition of `E` from trait
+...
+LL |         P: Copy;
+   |            ^^^^ impl has extra requirement `P: Copy`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/compare-impl-item.rs:27:16
+   |
+LL |     const F<T: PartialEq>: ();
+   |     ------------------------- definition of `F` from trait
+...
+LL |     const F<T: Eq>: () = ();
+   |                ^^ impl has extra requirement `T: Eq`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0049, E0053, E0276.
+For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs
new file mode 100644
index 00000000000..8da1448df4f
--- /dev/null
+++ b/tests/ui/generic-const-items/const-trait-impl.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+// Test that we can call methods from const trait impls inside of generic const items.
+
+#![feature(generic_const_items, const_trait_impl)]
+#![allow(incomplete_features)]
+#![crate_type = "lib"]
+
+// FIXME(generic_const_items): Interpret `~const` as always-const.
+const CREATE<T: ~const Create>: T = T::create();
+
+pub const K0: i32 = CREATE::<i32>;
+pub const K1: i32 = CREATE; // arg inferred
+
+#[const_trait]
+trait Create {
+    fn create() -> Self;
+}
+
+impl const Create for i32 {
+    fn create() -> i32 {
+        4096
+    }
+}
diff --git a/tests/ui/generic-const-items/duplicate-where-clause.rs b/tests/ui/generic-const-items/duplicate-where-clause.rs
new file mode 100644
index 00000000000..68da4073fc1
--- /dev/null
+++ b/tests/ui/generic-const-items/duplicate-where-clause.rs
@@ -0,0 +1,27 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+trait Tr<P> {
+    const K: ()
+    where
+        P: Copy
+    where
+        P: Eq;
+    //~^ ERROR cannot define duplicate `where` clauses on an item
+}
+
+// Test that we error on the first where-clause but also that we don't suggest to swap it with the
+// body as it would conflict with the second where-clause.
+// FIXME(generic_const_items): We should provide a structured sugg to merge the 1st into the 2nd WC.
+
+impl<P> Tr<P> for () {
+    const K: ()
+    where
+        P: Eq
+    = ()
+    where
+        P: Copy;
+    //~^^^^^ ERROR where clauses are not allowed before const item bodies
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/duplicate-where-clause.stderr b/tests/ui/generic-const-items/duplicate-where-clause.stderr
new file mode 100644
index 00000000000..5fa61b01ee9
--- /dev/null
+++ b/tests/ui/generic-const-items/duplicate-where-clause.stderr
@@ -0,0 +1,27 @@
+error: cannot define duplicate `where` clauses on an item
+  --> $DIR/duplicate-where-clause.rs:9:9
+   |
+LL |         P: Copy
+   |         - previous `where` clause starts here
+LL |     where
+LL |         P: Eq;
+   |         ^
+   |
+help: consider joining the two `where` clauses into one
+   |
+LL |         P: Copy,
+   |                ~
+
+error: where clauses are not allowed before const item bodies
+  --> $DIR/duplicate-where-clause.rs:19:5
+   |
+LL |       const K: ()
+   |             - while parsing this const item
+LL | /     where
+LL | |         P: Eq
+   | |_____________^ unexpected where clause
+LL |       = ()
+   |         -- the item body
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generic-const-items/elided-lifetimes.rs b/tests/ui/generic-const-items/elided-lifetimes.rs
new file mode 100644
index 00000000000..cca73e2e81e
--- /dev/null
+++ b/tests/ui/generic-const-items/elided-lifetimes.rs
@@ -0,0 +1,18 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+// Check that we forbid elided lifetimes inside the generics of const items.
+
+const K<T>: () = ()
+where
+    &T: Copy; //~ ERROR `&` without an explicit lifetime name cannot be used here
+
+const I<const S: &str>: &str = "";
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//~| ERROR `&str` is forbidden as the type of a const generic parameter
+
+const B<T: Trait<'_>>: () = (); //~ ERROR `'_` cannot be used here
+
+trait Trait<'a> {}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/elided-lifetimes.stderr b/tests/ui/generic-const-items/elided-lifetimes.stderr
new file mode 100644
index 00000000000..8cd3f9ee7a9
--- /dev/null
+++ b/tests/ui/generic-const-items/elided-lifetimes.stderr
@@ -0,0 +1,35 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/elided-lifetimes.rs:8:5
+   |
+LL |     &T: Copy;
+   |     ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here
+   |
+LL |     for<'a> &'a T: Copy;
+   |     +++++++  ++
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/elided-lifetimes.rs:10:18
+   |
+LL | const I<const S: &str>: &str = "";
+   |                  ^ explicit lifetime name needed here
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/elided-lifetimes.rs:14:18
+   |
+LL | const B<T: Trait<'_>>: () = ();
+   |                  ^^ `'_` is a reserved lifetime name
+
+error: `&str` is forbidden as the type of a const generic parameter
+  --> $DIR/elided-lifetimes.rs:10:18
+   |
+LL | const I<const S: &str>: &str = "";
+   |                  ^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/tests/ui/generic-const-items/evaluatable-bounds.rs b/tests/ui/generic-const-items/evaluatable-bounds.rs
new file mode 100644
index 00000000000..cdcfcf9188a
--- /dev/null
+++ b/tests/ui/generic-const-items/evaluatable-bounds.rs
@@ -0,0 +1,31 @@
+// This is a regression test for issue #104400.
+
+// revisions: unconstrained constrained
+//[constrained] check-pass
+
+// Test that we can constrain generic const items that appear inside associated consts by
+// adding a (makeshift) "evaluatable"-bound to the item.
+
+#![feature(generic_const_items, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    const LEN: usize;
+
+    #[cfg(unconstrained)]
+    const ARRAY: [i32; Self::LEN]; //[unconstrained]~ ERROR unconstrained generic constant
+
+    #[cfg(constrained)]
+    const ARRAY: [i32; Self::LEN]
+    where
+        [(); Self::LEN]:;
+}
+
+impl Trait for () {
+    const LEN: usize = 2;
+    const ARRAY: [i32; Self::LEN] = [360, 720];
+}
+
+fn main() {
+    let [_, _] = <() as Trait>::ARRAY;
+}
diff --git a/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr b/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr
new file mode 100644
index 00000000000..930080f7c37
--- /dev/null
+++ b/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/evaluatable-bounds.rs:16:5
+   |
+LL |     const ARRAY: [i32; Self::LEN];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); Self::LEN]:`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/generic-const-items/feature-gate-generic_const_items.rs b/tests/ui/generic-const-items/feature-gate-generic_const_items.rs
new file mode 100644
index 00000000000..5c241f256eb
--- /dev/null
+++ b/tests/ui/generic-const-items/feature-gate-generic_const_items.rs
@@ -0,0 +1,37 @@
+pub trait Trait<A> {
+    const ONE<T>: i32;
+    //~^ ERROR generic const items are experimental
+
+    const TWO: ()
+    where
+        A: Copy;
+    //~^^ ERROR generic const items are experimental
+}
+
+const CONST<T>: i32 = 0;
+//~^ ERROR generic const items are experimental
+
+const EMPTY<>: i32 = 0;
+//~^ ERROR generic const items are experimental
+
+const TRUE: () = ()
+where
+    String: Clone;
+//~^^ ERROR generic const items are experimental
+
+// Ensure that we flag generic const items inside macro calls as well:
+
+macro_rules! discard {
+    ($item:item) => {}
+}
+
+discard! { const FREE<T>: () = (); }
+//~^ ERROR generic const items are experimental
+
+discard! { impl () { const ASSOC<const N: ()>: () = (); } }
+//~^ ERROR generic const items are experimental
+
+discard! { impl () { const ASSOC: i32 = 0 where String: Copy; } }
+//~^ ERROR generic const items are experimental
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/feature-gate-generic_const_items.stderr b/tests/ui/generic-const-items/feature-gate-generic_const_items.stderr
new file mode 100644
index 00000000000..a1fdf5f6ef3
--- /dev/null
+++ b/tests/ui/generic-const-items/feature-gate-generic_const_items.stderr
@@ -0,0 +1,77 @@
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:2:14
+   |
+LL |     const ONE<T>: i32;
+   |              ^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:6:5
+   |
+LL | /     where
+LL | |         A: Copy;
+   | |_______________^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:11:12
+   |
+LL | const CONST<T>: i32 = 0;
+   |            ^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:14:12
+   |
+LL | const EMPTY<>: i32 = 0;
+   |            ^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:18:1
+   |
+LL | / where
+LL | |     String: Clone;
+   | |_________________^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:28:22
+   |
+LL | discard! { const FREE<T>: () = (); }
+   |                      ^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:31:33
+   |
+LL | discard! { impl () { const ASSOC<const N: ()>: () = (); } }
+   |                                 ^^^^^^^^^^^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+  --> $DIR/feature-gate-generic_const_items.rs:34:43
+   |
+LL | discard! { impl () { const ASSOC: i32 = 0 where String: Copy; } }
+   |                                           ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/generic-const-items/inference-failure.rs b/tests/ui/generic-const-items/inference-failure.rs
new file mode 100644
index 00000000000..fd4f424dd97
--- /dev/null
+++ b/tests/ui/generic-const-items/inference-failure.rs
@@ -0,0 +1,15 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+const NONE<T>: Option<T> = None::<T>;
+const IGNORE<T>: () = ();
+
+fn none() {
+    let _ = NONE; //~ ERROR type annotations needed
+}
+
+fn ignore() {
+    let _ = IGNORE; //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr
new file mode 100644
index 00000000000..22ff1b9ba7f
--- /dev/null
+++ b/tests/ui/generic-const-items/inference-failure.stderr
@@ -0,0 +1,20 @@
+error[E0282]: type annotations needed for `Option<T>`
+  --> $DIR/inference-failure.rs:8:9
+   |
+LL |     let _ = NONE;
+   |         ^
+   |
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
+   |
+LL |     let _: Option<T> = NONE;
+   |          +++++++++++
+
+error[E0282]: type annotations needed
+  --> $DIR/inference-failure.rs:12:13
+   |
+LL |     let _ = IGNORE;
+   |             ^^^^^^ cannot infer type for type parameter `T` declared on the constant `IGNORE`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/generic-const-items/misplaced-where-clause.fixed b/tests/ui/generic-const-items/misplaced-where-clause.fixed
new file mode 100644
index 00000000000..bff470c2883
--- /dev/null
+++ b/tests/ui/generic-const-items/misplaced-where-clause.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![feature(generic_const_items)]
+#![allow(incomplete_features, dead_code)]
+
+const K<T>: u64
+= T::K where
+    T: Tr<()>;
+//~^^^ ERROR where clauses are not allowed before const item bodies
+
+trait Tr<P> {
+    const K: u64
+    = 0 where
+        P: Copy;
+    //~^^^ ERROR where clauses are not allowed before const item bodies
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/misplaced-where-clause.rs b/tests/ui/generic-const-items/misplaced-where-clause.rs
new file mode 100644
index 00000000000..b14c6d594a5
--- /dev/null
+++ b/tests/ui/generic-const-items/misplaced-where-clause.rs
@@ -0,0 +1,20 @@
+// run-rustfix
+
+#![feature(generic_const_items)]
+#![allow(incomplete_features, dead_code)]
+
+const K<T>: u64
+where
+    T: Tr<()>
+= T::K;
+//~^^^ ERROR where clauses are not allowed before const item bodies
+
+trait Tr<P> {
+    const K: u64
+    where
+        P: Copy
+    = 0;
+    //~^^^ ERROR where clauses are not allowed before const item bodies
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/misplaced-where-clause.stderr b/tests/ui/generic-const-items/misplaced-where-clause.stderr
new file mode 100644
index 00000000000..431741d8724
--- /dev/null
+++ b/tests/ui/generic-const-items/misplaced-where-clause.stderr
@@ -0,0 +1,36 @@
+error: where clauses are not allowed before const item bodies
+  --> $DIR/misplaced-where-clause.rs:7:1
+   |
+LL |   const K<T>: u64
+   |         - while parsing this const item
+LL | / where
+LL | |     T: Tr<()>
+   | |_____________^ unexpected where clause
+LL |   = T::K;
+   |     ---- the item body
+   |
+help: move the body before the where clause
+   |
+LL ~ = T::K where
+LL ~     T: Tr<()>;
+   |
+
+error: where clauses are not allowed before const item bodies
+  --> $DIR/misplaced-where-clause.rs:14:5
+   |
+LL |       const K: u64
+   |             - while parsing this const item
+LL | /     where
+LL | |         P: Copy
+   | |_______________^ unexpected where clause
+LL |       = 0;
+   |         - the item body
+   |
+help: move the body before the where clause
+   |
+LL ~     = 0 where
+LL ~         P: Copy;
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generic-const-items/parameter-defaults.rs b/tests/ui/generic-const-items/parameter-defaults.rs
new file mode 100644
index 00000000000..a6f82c249fe
--- /dev/null
+++ b/tests/ui/generic-const-items/parameter-defaults.rs
@@ -0,0 +1,14 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+// Check that we emit a *hard* error (not just a lint warning or error for example) for generic
+// parameter defaults on free const items since we are not limited by backward compatibility.
+#![allow(invalid_type_param_default)] // Should have no effect here.
+
+// FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly.
+
+const NONE<T = ()>: Option<T> = None::<T>; //~ ERROR defaults for type parameters are only allowed
+
+fn main() {
+    let _ = NONE;
+}
diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr
new file mode 100644
index 00000000000..62da45e55d6
--- /dev/null
+++ b/tests/ui/generic-const-items/parameter-defaults.stderr
@@ -0,0 +1,8 @@
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/parameter-defaults.rs:10:12
+   |
+LL | const NONE<T = ()>: Option<T> = None::<T>;
+   |            ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/generic-const-items/recursive.rs b/tests/ui/generic-const-items/recursive.rs
new file mode 100644
index 00000000000..3266b37d380
--- /dev/null
+++ b/tests/ui/generic-const-items/recursive.rs
@@ -0,0 +1,12 @@
+// FIXME(generic_const_items): This leads to a stack overflow in the compiler!
+// known-bug: unknown
+// ignore-test
+
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+const RECUR<T>: () = RECUR::<(T,)>;
+
+fn main() {
+    let _ = RECUR::<()>;
+}
diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs
new file mode 100644
index 00000000000..dd00b327d2d
--- /dev/null
+++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs
@@ -0,0 +1,12 @@
+#![feature(generic_const_items, trivial_bounds)]
+#![allow(incomplete_features)]
+
+// Ensure that we check if trivial bounds on const items hold or not.
+
+const UNUSABLE: () = ()
+where
+    String: Copy;
+
+fn main() {
+    let _ = UNUSABLE; //~ ERROR the trait bound `String: Copy` is not satisfied
+}
diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr
new file mode 100644
index 00000000000..c3ef94529a4
--- /dev/null
+++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/trivially-unsatisfied-bounds-0.rs:11:13
+   |
+LL |     let _ = UNUSABLE;
+   |             ^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `UNUSABLE`
+  --> $DIR/trivially-unsatisfied-bounds-0.rs:8:13
+   |
+LL | const UNUSABLE: () = ()
+   |       -------- required by a bound in this constant
+LL | where
+LL |     String: Copy;
+   |             ^^^^ required by this bound in `UNUSABLE`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs
new file mode 100644
index 00000000000..9243deac870
--- /dev/null
+++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs
@@ -0,0 +1,12 @@
+#![feature(generic_const_items, trivial_bounds)]
+#![allow(incomplete_features, dead_code, trivial_bounds)]
+
+// FIXME(generic_const_items): This looks like a bug to me. I expected that we wouldn't emit any
+// errors. I thought we'd skip the evaluation of consts whose bounds don't hold.
+
+const UNUSED: () = ()
+where
+    String: Copy;
+//~^^^ ERROR evaluation of constant value failed
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr
new file mode 100644
index 00000000000..a68400798d8
--- /dev/null
+++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr
@@ -0,0 +1,11 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/trivially-unsatisfied-bounds-1.rs:7:1
+   |
+LL | / const UNUSED: () = ()
+LL | | where
+LL | |     String: Copy;
+   | |_________________^ entering unreachable code
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.rs b/tests/ui/generic-const-items/unsatisfied-bounds.rs
new file mode 100644
index 00000000000..05879900172
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-bounds.rs
@@ -0,0 +1,34 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+// Ensure that we check if bounds on const items hold or not.
+
+use std::convert::Infallible;
+
+const C<T: Copy>: () = ();
+
+const K<T>: () = ()
+where
+    Infallible: From<T>;
+
+trait Trait<P> {
+    const A: u32
+    where
+        P: Copy;
+
+    const B<T>: u32
+    where
+        Infallible: From<T>;
+}
+
+impl<P> Trait<P> for () {
+    const A: u32 = 0;
+    const B<T>: u32 = 1;
+}
+
+fn main() {
+    let () = C::<String>; //~ ERROR the trait bound `String: Copy` is not satisfied
+    let () = K::<()>; //~ ERROR the trait bound `Infallible: From<()>` is not satisfied
+    let _ = <() as Trait<Vec<u8>>>::A; //~ ERROR the trait bound `Vec<u8>: Copy` is not satisfied
+    let _ = <() as Trait<&'static str>>::B::<()>; //~ ERROR the trait bound `Infallible: From<()>` is not satisfied
+}
diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
new file mode 100644
index 00000000000..1fda460372a
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
@@ -0,0 +1,62 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/unsatisfied-bounds.rs:30:18
+   |
+LL |     let () = C::<String>;
+   |                  ^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `C`
+  --> $DIR/unsatisfied-bounds.rs:8:12
+   |
+LL | const C<T: Copy>: () = ();
+   |            ^^^^ required by this bound in `C`
+
+error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
+  --> $DIR/unsatisfied-bounds.rs:31:18
+   |
+LL |     let () = K::<()>;
+   |                  ^^ the trait `From<()>` is not implemented for `Infallible`
+   |
+   = help: the trait `From<!>` is implemented for `Infallible`
+note: required by a bound in `K`
+  --> $DIR/unsatisfied-bounds.rs:12:17
+   |
+LL | const K<T>: () = ()
+   |       - required by a bound in this constant
+LL | where
+LL |     Infallible: From<T>;
+   |                 ^^^^^^^ required by this bound in `K`
+
+error[E0277]: the trait bound `Vec<u8>: Copy` is not satisfied
+  --> $DIR/unsatisfied-bounds.rs:32:13
+   |
+LL |     let _ = <() as Trait<Vec<u8>>>::A;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>`
+   |
+note: required by a bound in `Trait::A`
+  --> $DIR/unsatisfied-bounds.rs:17:12
+   |
+LL |     const A: u32
+   |           - required by a bound in this associated constant
+LL |     where
+LL |         P: Copy;
+   |            ^^^^ required by this bound in `Trait::A`
+
+error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
+  --> $DIR/unsatisfied-bounds.rs:33:46
+   |
+LL |     let _ = <() as Trait<&'static str>>::B::<()>;
+   |                                              ^^ the trait `From<()>` is not implemented for `Infallible`
+   |
+   = help: the trait `From<!>` is implemented for `Infallible`
+note: required by a bound in `Trait::B`
+  --> $DIR/unsatisfied-bounds.rs:21:21
+   |
+LL |     const B<T>: u32
+   |           - required by a bound in this associated constant
+LL |     where
+LL |         Infallible: From<T>;
+   |                     ^^^^^^^ required by this bound in `Trait::B`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.rs b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.rs
new file mode 100644
index 00000000000..961e5b4aeeb
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.rs
@@ -0,0 +1,12 @@
+#![feature(generic_const_items, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// Ensure that we check if (makeshift) "evaluatable"-bounds on const items hold or not.
+
+const POSITIVE<const N: usize>: usize = N
+where
+    [(); N - 1]:; //~ ERROR evaluation of `POSITIVE::<0>::{constant#0}` failed
+
+fn main() {
+    let _ = POSITIVE::<0>;
+}
diff --git a/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr
new file mode 100644
index 00000000000..bed213b0caa
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of `POSITIVE::<0>::{constant#0}` failed
+  --> $DIR/unsatisfied-evaluatable-bounds.rs:8:10
+   |
+LL |     [(); 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/generic-const-items/unsatisfied-outlives-bounds.rs b/tests/ui/generic-const-items/unsatisfied-outlives-bounds.rs
new file mode 100644
index 00000000000..204cf9def36
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-outlives-bounds.rs
@@ -0,0 +1,17 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+
+// Ensure that we check if outlives-bounds on const items hold or not.
+
+const C<'a, T: 'a>: () = ();
+const K<'a, 'b: 'a>: () = ();
+
+fn parametrized0<'any>() {
+    let () = C::<'static, &'any ()>; //~ ERROR lifetime may not live long enough
+}
+
+fn parametrized1<'any>() {
+    let () = K::<'static, 'any>; //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/unsatisfied-outlives-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-outlives-bounds.stderr
new file mode 100644
index 00000000000..72e4265b3d7
--- /dev/null
+++ b/tests/ui/generic-const-items/unsatisfied-outlives-bounds.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+  --> $DIR/unsatisfied-outlives-bounds.rs:10:14
+   |
+LL | fn parametrized0<'any>() {
+   |                  ---- lifetime `'any` defined here
+LL |     let () = C::<'static, &'any ()>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/unsatisfied-outlives-bounds.rs:14:14
+   |
+LL | fn parametrized1<'any>() {
+   |                  ---- lifetime `'any` defined here
+LL |     let () = K::<'static, 'any>;
+   |              ^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/generic-statics.rs b/tests/ui/parser/generic-statics.rs
new file mode 100644
index 00000000000..2fb8781fdff
--- /dev/null
+++ b/tests/ui/parser/generic-statics.rs
@@ -0,0 +1,4 @@
+static S<T>: i32 = 0;
+//~^ ERROR static items may not have generic parameters
+
+fn main() {}
diff --git a/tests/ui/parser/generic-statics.stderr b/tests/ui/parser/generic-statics.stderr
new file mode 100644
index 00000000000..c757232b061
--- /dev/null
+++ b/tests/ui/parser/generic-statics.stderr
@@ -0,0 +1,8 @@
+error: static items may not have generic parameters
+  --> $DIR/generic-statics.rs:1:9
+   |
+LL | static S<T>: i32 = 0;
+   |         ^^^
+
+error: aborting due to previous error
+