about summary refs log tree commit diff
path: root/tests/ui/rfc-2632-const-trait-impl
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfc-2632-const-trait-impl')
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/assoc-type.rs32
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr21
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs10
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs23
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs29
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs43
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs28
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs31
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs26
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr22
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs24
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs31
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr25
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs16
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr11
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr23
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closures.rs30
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs29
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs25
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr99
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs62
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr99
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop.rs113
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr26
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs9
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs55
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs4
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr11
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs13
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/cross-crate.rs24
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr11
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr20
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/feature-gate.rs14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr21
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/generic-bound.rs30
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs9
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs26
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs22
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs13
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr22
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-100222.rs39
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-102156.rs15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-102985.rs12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr41
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-103677.rs5
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-79450.rs20
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-88155.rs13
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr24
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-90052.rs9
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-92111.rs23
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/nested-closure.rs12
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs46
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs39
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs26
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs15
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs37
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs45
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs39
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs31
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs28
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs16
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr11
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/staged-api.rs63
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr25
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr42
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs21
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr11
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs20
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr20
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits.rs25
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/syntax.rs8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs34
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr14
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs7
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs9
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs6
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr8
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs17
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs50
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs31
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr35
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs41
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs24
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs26
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr35
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/without-tilde.rs6
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr10
137 files changed, 3040 insertions, 0 deletions
diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
new file mode 100644
index 00000000000..780a510c500
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
@@ -0,0 +1,14 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    type Assoc: ~const Foo;
+    fn foo() {}
+}
+
+const fn foo<T: ~const Foo>() {
+    <T as Foo>::Assoc::foo();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs
new file mode 100644
index 00000000000..7d9dae52cf1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs
@@ -0,0 +1,32 @@
+#![feature(const_trait_impl)]
+
+struct NonConstAdd(i32);
+
+impl std::ops::Add for NonConstAdd {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        NonConstAdd(self.0 + rhs.0)
+    }
+}
+
+#[const_trait]
+trait Foo {
+    type Bar: ~const std::ops::Add;
+}
+
+impl const Foo for NonConstAdd {
+    type Bar = NonConstAdd;
+    //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
+}
+
+#[const_trait]
+trait Baz {
+    type Qux: std::ops::Add;
+}
+
+impl const Baz for NonConstAdd {
+    type Qux = NonConstAdd; // OK
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr
new file mode 100644
index 00000000000..89177b0f1ac
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -0,0 +1,21 @@
+error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
+  --> $DIR/assoc-type.rs:19:16
+   |
+LL |     type Bar = NonConstAdd;
+   |                ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
+   |
+   = help: the trait `~const Add` is not implemented for `NonConstAdd`
+note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const`
+  --> $DIR/assoc-type.rs:19:16
+   |
+LL |     type Bar = NonConstAdd;
+   |                ^^^^^^^^^^^
+note: required by a bound in `Foo::Bar`
+  --> $DIR/assoc-type.rs:15:15
+   |
+LL |     type Bar: ~const std::ops::Add;
+   |               ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs
new file mode 100644
index 00000000000..01ac74feff7
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs
@@ -0,0 +1,10 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait A {
+    #[const_trait] //~ ERROR attribute should be applied
+    fn foo(self);
+}
+
+#[const_trait] //~ ERROR attribute should be applied
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr
new file mode 100644
index 00000000000..b18f33218c2
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr
@@ -0,0 +1,14 @@
+error: attribute should be applied to a trait
+  --> $DIR/attr-misuse.rs:9:1
+   |
+LL | #[const_trait]
+   | ^^^^^^^^^^^^^^
+
+error: attribute should be applied to a trait
+  --> $DIR/attr-misuse.rs:5:5
+   |
+LL |     #[const_trait]
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
new file mode 100644
index 00000000000..e73082c1127
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
@@ -0,0 +1,23 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait MyTrait {
+    fn defaulted_func(&self) {}
+    fn func(self);
+}
+
+pub struct NonConst;
+
+impl MyTrait for NonConst {
+    fn func(self) {
+
+    }
+}
+
+pub struct Const;
+
+impl const MyTrait for Const {
+    fn func(self) {
+
+    }
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
new file mode 100644
index 00000000000..589e3f02420
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_impl)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
+pub trait MyTrait {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn func();
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Unstable;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "unstable", issue = "none")]
+impl const MyTrait for Unstable {
+    fn func() {}
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
new file mode 100644
index 00000000000..dd993397420
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait Plus {
+    fn plus(self, rhs: Self) -> Self;
+}
+
+impl const Plus for i32 {
+    fn plus(self, rhs: Self) -> Self {
+        self + rhs
+    }
+}
+
+impl Plus for u32 {
+    fn plus(self, rhs: Self) -> Self {
+        self + rhs
+    }
+}
+
+pub const fn add_i32(a: i32, b: i32) -> i32 {
+    a.plus(b) // ok
+}
+
+pub const fn add_u32(a: u32, b: u32) -> u32 {
+    a.plus(b)
+    //~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
new file mode 100644
index 00000000000..7350909ba8e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
+  --> $DIR/call-const-trait-method-fail.rs:25:7
+   |
+LL |     a.plus(b)
+   |       ^^^^ the trait `~const Plus` is not implemented for `u32`
+   |
+note: the trait `Plus` is implemented for `u32`, but that implementation is not `const`
+  --> $DIR/call-const-trait-method-fail.rs:25:7
+   |
+LL |     a.plus(b)
+   |       ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
new file mode 100644
index 00000000000..b64161b6aa0
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
@@ -0,0 +1,43 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+
+struct Int(i32);
+
+impl const std::ops::Add for Int {
+    type Output = Int;
+
+    fn add(self, rhs: Self) -> Self {
+        Int(self.0.plus(rhs.0))
+    }
+}
+
+impl const PartialEq for Int {
+    fn eq(&self, rhs: &Self) -> bool {
+        self.0 == rhs.0
+    }
+    fn ne(&self, other: &Self) -> bool {
+        !self.eq(other)
+    }
+}
+
+#[const_trait]
+pub trait Plus {
+    fn plus(self, rhs: Self) -> Self;
+}
+
+impl const Plus for i32 {
+    fn plus(self, rhs: Self) -> Self {
+        self + rhs
+    }
+}
+
+pub const fn add_i32(a: i32, b: i32) -> i32 {
+    a.plus(b)
+}
+
+const ADD_INT: Int = Int(1i32) + Int(2i32);
+
+fn main() {
+    assert!(ADD_INT == Int(3i32));
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
new file mode 100644
index 00000000000..50c46579086
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait MyPartialEq {
+    fn eq(&self, other: &Self) -> bool;
+}
+
+impl<T: ~const PartialEq> const MyPartialEq for T {
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(self, other)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
new file mode 100644
index 00000000000..b00ff1f2fac
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
@@ -0,0 +1,28 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
+}
+
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
+    equals_self(t)
+}
+
+pub const EQ: bool = equals_self_wrapper(&S);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
new file mode 100644
index 00000000000..c8ded0fa7ea
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
+}
+
+// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
+// bound.
+const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+trait A: PartialEq {}
+impl<T: PartialEq> A for T {}
+
+const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S) && equals_self2(&S);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
new file mode 100644
index 00000000000..2bc5ee512c5
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
@@ -0,0 +1,8 @@
+#![feature(const_trait_impl)]
+
+pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    *t == *t
+    //~^ ERROR can't compare
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
new file mode 100644
index 00000000000..31e6dbdab22
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -0,0 +1,15 @@
+error[E0277]: can't compare `T` with `_` in const contexts
+  --> $DIR/call-generic-method-fail.rs:4:8
+   |
+LL |     *t == *t
+   |        ^^ no implementation for `T == _`
+   |
+note: the trait `PartialEq<_>` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/call-generic-method-fail.rs:4:8
+   |
+LL |     *t == *t
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
new file mode 100644
index 00000000000..e197c8b73c5
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+struct S;
+
+impl PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    true
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
new file mode 100644
index 00000000000..414a8c87d2c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl)]
+
+struct S;
+
+#[const_trait]
+trait Foo {
+    fn eq(&self, _: &Self) -> bool;
+}
+
+impl Foo for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+    true
+}
+
+// Calling `equals_self` with something that has a non-const impl should throw an error, despite
+// it not using the impl.
+
+pub const EQ: bool = equals_self(&S);
+//~^ ERROR
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
new file mode 100644
index 00000000000..706f5234365
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+  --> $DIR/call-generic-method-nonconst.rs:23:34
+   |
+LL | pub const EQ: bool = equals_self(&S);
+   |                      ----------- ^^ the trait `~const Foo` is not implemented for `S`
+   |                      |
+   |                      required by a bound introduced by this call
+   |
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+  --> $DIR/call-generic-method-nonconst.rs:23:34
+   |
+LL | pub const EQ: bool = equals_self(&S);
+   |                                  ^^
+note: required by a bound in `equals_self`
+  --> $DIR/call-generic-method-nonconst.rs:16:25
+   |
+LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+   |                         ^^^^^^^^^^ required by this bound in `equals_self`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
new file mode 100644
index 00000000000..40565d1b76a
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
@@ -0,0 +1,24 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S;
+
+impl const PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+    fn ne(&self, other: &S) -> bool {
+        !self.eq(other)
+    }
+}
+
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
new file mode 100644
index 00000000000..f66d63da693
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl)]
+
+pub struct Int(i32);
+
+impl const std::ops::Add for i32 {
+    //~^ ERROR only traits defined in the current crate can be implemented for primitive types
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        self + rhs
+    }
+}
+
+impl std::ops::Add for Int {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Int(self.0 + rhs.0)
+    }
+}
+
+impl const std::ops::Add for Int {
+    //~^ ERROR conflicting implementations of trait
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        Int(self.0 + rhs.0)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
new file mode 100644
index 00000000000..36a09add4d3
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
@@ -0,0 +1,25 @@
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
+  --> $DIR/const-and-non-const-impl.rs:5:1
+   |
+LL | impl const std::ops::Add for i32 {
+   | ^^^^^^^^^^^-------------^^^^^---
+   | |          |                 |
+   | |          |                 `i32` is not defined in the current crate
+   | |          `i32` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0119]: conflicting implementations of trait `Add` for type `Int`
+  --> $DIR/const-and-non-const-impl.rs:22:1
+   |
+LL | impl std::ops::Add for Int {
+   | -------------------------- first implementation here
+...
+LL | impl const std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0117, E0119.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
new file mode 100644
index 00000000000..52984fb6be4
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
@@ -0,0 +1,16 @@
+#![feature(const_trait_impl)]
+
+struct S;
+#[const_trait]
+trait T {
+    fn foo();
+}
+
+fn non_const() {}
+
+impl const T for S {
+    fn foo() { non_const() }
+    //~^ ERROR cannot call non-const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
new file mode 100644
index 00000000000..c8783de4c3e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `non_const` in constant functions
+  --> $DIR/const-check-fns-in-const-impl.rs:12:16
+   |
+LL |     fn foo() { non_const() }
+   |                ^^^^^^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs
new file mode 100644
index 00000000000..b5f19e40c03
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+    fn a(self) -> i32;
+}
+
+impl Tr for () {
+    fn a(self) -> i32 { 42 }
+}
+
+const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+    x(())
+}
+
+const _: () = assert!(need_const_closure(Tr::a) == 42);
+//~^ ERROR: the trait bound
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
new file mode 100644
index 00000000000..4470e287cc3
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}`
+  --> $DIR/const-closure-trait-method-fail.rs:16:42
+   |
+LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
+   |                       ------------------ ^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()`
+   |                       |
+   |                       required by a bound introduced by this call
+   |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+  --> $DIR/const-closure-trait-method-fail.rs:16:42
+   |
+LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
+   |                                          ^^^^^
+   = note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}`
+note: required by a bound in `need_const_closure`
+  --> $DIR/const-closure-trait-method-fail.rs:12:32
+   |
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `need_const_closure`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs
new file mode 100644
index 00000000000..3e6d1908848
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+    fn a(self) -> i32;
+}
+
+impl const Tr for () {
+    fn a(self) -> i32 { 42 }
+}
+
+const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+    x(())
+}
+
+const _: () = assert!(need_const_closure(Tr::a) == 42);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closures.rs b/tests/ui/rfc-2632-const-trait-impl/const-closures.rs
new file mode 100644
index 00000000000..755d8539839
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closures.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+
+const fn answer_p1<F>(f: &F) -> u8
+    where
+        F: ~const FnOnce() -> u8,
+        F: ~const FnMut() -> u8,
+        F: ~const Fn() -> u8,
+{
+    f() * 7
+}
+
+const fn three() -> u8 {
+    3
+}
+
+const fn answer_p2() -> u8 {
+    answer_p1(&three)
+}
+
+const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
+    f() + f()
+}
+
+const ANSWER: u8 = answer(&answer_p2);
+
+fn main() {
+    assert_eq!(ANSWER, 42)
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
new file mode 100644
index 00000000000..140a06a73ac
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait ConstDefaultFn: Sized {
+    fn b(self);
+
+    fn a(self) {
+        self.b();
+    }
+}
+
+struct NonConstImpl;
+struct ConstImpl;
+
+impl ConstDefaultFn for NonConstImpl {
+    fn b(self) {}
+}
+
+impl const ConstDefaultFn for ConstImpl {
+    fn b(self) {}
+}
+
+const fn test() {
+    NonConstImpl.a();
+    //~^ ERROR the trait bound
+    ConstImpl.a();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
new file mode 100644
index 00000000000..f9d0d1f7875
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
+  --> $DIR/const-default-method-bodies.rs:24:18
+   |
+LL |     NonConstImpl.a();
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |
+note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
+  --> $DIR/const-default-method-bodies.rs:24:5
+   |
+LL |     NonConstImpl.a();
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs
new file mode 100644
index 00000000000..948f0efbcfc
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_precise_live_drops)]
+
+use std::marker::Destruct;
+
+const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
+    match res {
+        Ok(t) => Some(t),
+        Err(_e) => None,
+    }
+}
+
+pub struct Foo<T>(T);
+
+const fn baz<T, E>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>>
+where
+    T: ~const Destruct,
+    E: ~const Destruct,
+{
+    foo(res)
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
new file mode 100644
index 00000000000..796c0d388ea
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -0,0 +1,99 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+  --> $DIR/const-drop-fail.rs:44:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+   |
+   = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:35:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
+help: consider borrowing here
+   |
+LL |     &NonTrivialDrop,
+   |     +
+LL |     &mut NonTrivialDrop,
+   |     ++++
+
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+  --> $DIR/const-drop-fail.rs:46:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:46:5
+   |
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `ConstImplWithDropGlue`
+  --> $DIR/const-drop-fail.rs:16:8
+   |
+LL | struct ConstImplWithDropGlue(NonTrivialDrop);
+   |        ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:35:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |                                               ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+  --> $DIR/const-drop-fail.rs:55:9
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+   |         ^^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/const-drop-fail.rs:53:1
+   |
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
new file mode 100644
index 00000000000..d36c7f81ced
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -0,0 +1,62 @@
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::{Destruct, PhantomData};
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+    fn drop(&mut self) {
+        println!("Non trivial drop");
+    }
+}
+
+struct ConstImplWithDropGlue(NonTrivialDrop);
+
+impl const Drop for ConstImplWithDropGlue {
+    fn drop(&mut self) {}
+}
+
+#[const_trait]
+trait A { fn a() { } }
+
+impl A for NonTrivialDrop {}
+
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+    fn drop(&mut self) {
+        T::a();
+    }
+}
+
+const fn check<T: ~const Destruct>(_: T) {}
+
+macro_rules! check_all {
+    ($($exp:expr),*$(,)?) => {$(
+        const _: () = check($exp);
+    )*};
+}
+
+check_all! {
+    NonTrivialDrop,
+    //~^ ERROR can't drop
+    ConstImplWithDropGlue(NonTrivialDrop),
+    //~^ ERROR can't drop
+    ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+    //~^ ERROR the trait bound
+    //~| ERROR the trait bound
+}
+
+struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+    fn drop(&mut self) {
+        T::a();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
new file mode 100644
index 00000000000..796c0d388ea
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -0,0 +1,99 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+  --> $DIR/const-drop-fail.rs:44:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+   |
+   = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:35:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
+help: consider borrowing here
+   |
+LL |     &NonTrivialDrop,
+   |     +
+LL |     &mut NonTrivialDrop,
+   |     ++++
+
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+  --> $DIR/const-drop-fail.rs:46:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:46:5
+   |
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `ConstImplWithDropGlue`
+  --> $DIR/const-drop-fail.rs:16:8
+   |
+LL | struct ConstImplWithDropGlue(NonTrivialDrop);
+   |        ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:35:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:47
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |                                               ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+   |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+  --> $DIR/const-drop-fail.rs:48:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+  --> $DIR/const-drop-fail.rs:55:9
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+   |         ^^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/const-drop-fail.rs:53:1
+   |
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644
index 00000000000..b0fc3adf984
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,113 @@
+// run-pass
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(never_type)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::Destruct;
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+const fn a<T: ~const Destruct>(_: T) {}
+
+const fn b() -> u8 {
+    let mut c = 0;
+    let _ = S(&mut c);
+    a(S(&mut c));
+    c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+    ($($exp:expr),*$(,)?) => {
+        $(
+            const _: () = a($exp);
+        )*
+    }
+}
+
+#[allow(dead_code)]
+mod t {
+    pub struct Foo;
+    pub enum Bar { A }
+    pub fn foo() {}
+    pub struct ConstDrop;
+
+    impl const Drop for ConstDrop {
+        fn drop(&mut self) {}
+    }
+
+    pub struct HasConstDrop(pub ConstDrop);
+    pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+
+    #[const_trait]
+    pub trait SomeTrait {
+        fn foo();
+    }
+    impl const SomeTrait for () {
+        fn foo() {}
+    }
+    // non-const impl
+    impl SomeTrait for i32 {
+        fn foo() {}
+    }
+
+    pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
+
+    impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
+        fn drop(&mut self) {
+            T::foo();
+        }
+    }
+
+    pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+
+    impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> {
+        fn drop(&mut self) {
+            // Note: we DON'T use the `T: SomeTrait` bound
+        }
+    }
+}
+
+use t::*;
+
+implements_const_drop! {
+    1u8,
+    2,
+    3.0,
+    Foo,
+    Bar::A,
+    foo,
+    ConstDrop,
+    HasConstDrop(ConstDrop),
+    TrivialFields(1, 2, 3, 4),
+    &1,
+    &1 as *const i32,
+    ConstDropWithBound::<()>,
+    ConstDropWithNonconstBound::<i32>,
+    Result::<i32, !>::Ok(1),
+}
+
+fn main() {
+    struct HasDropGlue(#[allow(unused_tuple_struct_fields)] Box<u8>);
+    struct HasDropImpl;
+    impl Drop for HasDropImpl {
+        fn drop(&mut self) {
+            println!("not trivial drop");
+        }
+    }
+
+    // These types should pass because ~const in a non-const context should have no effect.
+    a(HasDropGlue(Box::new(0)));
+    a(HasDropImpl);
+
+    assert_eq!(C, 2);
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs
new file mode 100644
index 00000000000..bed4e9fd1e6
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl)]
+
+struct Foo;
+
+const impl Foo { //~ ERROR: expected identifier, found keyword
+    fn bar() {}
+}
+
+fn main() {
+     // shouldn't error here because we shouldn't have been able to recover above
+     Foo::bar();
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr
new file mode 100644
index 00000000000..603f6b7d283
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found keyword `impl`
+  --> $DIR/const-impl-norecover.rs:5:7
+   |
+LL | const impl Foo {
+   |       ^^^^ expected identifier, found keyword
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
new file mode 100644
index 00000000000..837124db04e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {}
+
+const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
+
+#[const_trait]
+trait Bar {}
+
+const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword
+
+const fn still_implements<T: Bar>() {}
+
+const _: () = still_implements::<i32>();
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
new file mode 100644
index 00000000000..7217fc85543
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `impl`
+  --> $DIR/const-impl-recovery.rs:6:7
+   |
+LL | const impl Foo for i32 {}
+   |       ^^^^ expected identifier, found keyword
+   |
+help: you might have meant to write a const trait impl
+   |
+LL - const impl Foo for i32 {}
+LL + impl const Foo for i32 {}
+   |
+
+error: expected identifier, found keyword `impl`
+  --> $DIR/const-impl-recovery.rs:11:7
+   |
+LL | const impl<T: Foo> Bar for T {}
+   |       ^^^^ expected identifier, found keyword
+   |
+help: you might have meant to write a const trait impl
+   |
+LL - const impl<T: Foo> Bar for T {}
+LL + impl<T: Foo> const Bar for T {}
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
new file mode 100644
index 00000000000..2b4963991db
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+pub trait A {}
+//~^ HELP: mark `A` as const
+
+impl const A for () {}
+//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
new file mode 100644
index 00000000000..478adcf3e9e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -0,0 +1,14 @@
+error: const `impl` for trait `A` which is not marked with `#[const_trait]`
+  --> $DIR/const-impl-requires-const-trait.rs:6:12
+   |
+LL | pub trait A {}
+   | - help: mark `A` as const: `#[const_trait]`
+...
+LL | impl const A for () {}
+   |            ^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs
new file mode 100644
index 00000000000..0622f96e70d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs
@@ -0,0 +1,55 @@
+// check-pass
+#![allow(incomplete_features)]
+#![feature(
+    associated_type_bounds,
+    const_trait_impl,
+    const_cmp,
+    return_position_impl_trait_in_trait,
+)]
+
+use std::marker::Destruct;
+
+const fn cmp(a: &impl ~const PartialEq) -> bool {
+    a == a
+}
+
+const fn wrap(x: impl ~const PartialEq + ~const Destruct)
+    -> impl ~const PartialEq + ~const Destruct
+{
+    x
+}
+
+#[const_trait]
+trait Foo {
+    fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+}
+
+impl const Foo for () {
+    fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+        123
+    }
+}
+
+const _: () = {
+    assert!(cmp(&0xDEADBEEFu32));
+    assert!(cmp(&()));
+    assert!(wrap(123) == wrap(123));
+    assert!(wrap(123) != wrap(456));
+    let x = <() as Foo>::huh();
+    assert!(x == x);
+};
+
+#[const_trait]
+trait T {}
+struct S;
+impl const T for S {}
+
+const fn rpit() -> impl ~const T { S }
+
+const fn apit(_: impl ~const T + ~const Destruct) {}
+
+const fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+
+const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
new file mode 100644
index 00000000000..348ca0ab190
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
@@ -0,0 +1,4 @@
+#[derive_const(Default)] //~ ERROR use of unstable library feature
+pub struct S;
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
new file mode 100644
index 00000000000..cc9bdd2715f
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'derive_const'
+  --> $DIR/derive-const-gate.rs:1:3
+   |
+LL | #[derive_const(Default)]
+   |   ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(derive_const)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
new file mode 100644
index 00000000000..92843a8a2da
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
@@ -0,0 +1,13 @@
+#![feature(derive_const)]
+
+pub struct A;
+
+impl Default for A {
+    fn default() -> A { A }
+}
+
+#[derive_const(Default)]
+pub struct S(A);
+//~^ cannot call non-const fn
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
new file mode 100644
index 00000000000..d463c774e28
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
@@ -0,0 +1,14 @@
+error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions
+  --> $DIR/derive-const-non-const-type.rs:10:14
+   |
+LL | #[derive_const(Default)]
+   |                ------- in this derive macro expansion
+LL | pub struct S(A);
+   |              ^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
new file mode 100644
index 00000000000..d1fbeac8598
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+
+pub struct A;
+
+impl const Default for A {
+    fn default() -> A { A }
+}
+
+impl const PartialEq for A {
+    fn eq(&self, _: &A) -> bool { true }
+}
+
+#[derive_const(Default, PartialEq)]
+pub struct S((), A);
+
+const _: () = assert!(S((), A) == S::default());
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs
new file mode 100644
index 00000000000..bde8bf20f46
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs
@@ -0,0 +1,18 @@
+// This tests that `const_trait` default methods can
+// be called from a const context when used across crates.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::*;
+
+const _: () = {
+    Const.func();
+    Const.defaulted_func();
+};
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
new file mode 100644
index 00000000000..633b7cc255a
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+  --> $DIR/cross-crate.rs:17:5
+   |
+LL |     NonConst.func();
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs b/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs
new file mode 100644
index 00000000000..6df47022cc9
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs
@@ -0,0 +1,24 @@
+// revisions: stock gated stocknc gatednc
+// [gated] check-pass
+#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))]
+
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::*;
+
+fn non_const_context() {
+    NonConst.func();
+    Const.func();
+}
+
+const fn const_context() {
+    #[cfg(any(stocknc, gatednc))]
+    NonConst.func();
+    //[stocknc]~^ ERROR: the trait bound
+    //[gatednc]~^^ ERROR: the trait bound
+    Const.func();
+    //[stock]~^ ERROR: cannot call
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr
new file mode 100644
index 00000000000..086547542bb
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
+  --> $DIR/cross-crate.rs:20:11
+   |
+LL |     Const.func();
+   |           ^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
new file mode 100644
index 00000000000..9e97d3f1137
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+  --> $DIR/cross-crate.rs:17:5
+   |
+LL |     NonConst.func();
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
new file mode 100644
index 00000000000..96acdc300e0
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {}
+impl Tr for () {}
+
+const fn foo<T>() where T: ~const Tr {}
+
+#[const_trait]
+pub trait Foo {
+    fn foo() {
+        foo::<()>();
+        //~^ ERROR the trait bound `(): ~const Tr` is not satisfied
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
new file mode 100644
index 00000000000..a244ab10cab
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied
+  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
+   |
+LL |         foo::<()>();
+   |               ^^ the trait `~const Tr` is not implemented for `()`
+   |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
+   |
+LL |         foo::<()>();
+   |               ^^
+note: required by a bound in `foo`
+  --> $DIR/default-method-body-is-const-body-checking.rs:7:28
+   |
+LL | const fn foo<T>() where T: ~const Tr {}
+   |                            ^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
new file mode 100644
index 00000000000..f70ecbc3746
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
@@ -0,0 +1,15 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait Tr {
+    fn a(&self) {}
+
+    fn b(&self) {
+        ().a()
+        //~^ ERROR the trait bound
+    }
+}
+
+impl Tr for () {}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
new file mode 100644
index 00000000000..21ecddaffbb
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+   |
+LL |         ().a()
+   |            ^ the trait `~const Tr` is not implemented for `()`
+   |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+   |
+LL |         ().a()
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
new file mode 100644
index 00000000000..1b45cd9aab9
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+// This was an ICE, because the compiler ensures the
+// function to be const when performing const checking,
+// but functions marked with the attribute are not const
+// *and* subject to const checking.
+
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![stable(since = "1", feature = "foo")]
+
+#[const_trait]
+trait Tr {
+    fn a() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
new file mode 100644
index 00000000000..4c630d33c55
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/feature-gate.rs:14:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs
new file mode 100644
index 00000000000..0b409fbaac9
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs
@@ -0,0 +1,14 @@
+// revisions: stock gated
+// gate-test-const_trait_impl
+
+#![cfg_attr(gated, feature(const_trait_impl))]
+#![feature(rustc_attrs)]
+
+struct S;
+#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
+trait T {}
+impl const T for S {}
+//[stock]~^ ERROR const trait impls are experimental
+
+#[rustc_error]
+fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
new file mode 100644
index 00000000000..0e938c1c55d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -0,0 +1,21 @@
+error[E0658]: const trait impls are experimental
+  --> $DIR/feature-gate.rs:10:6
+   |
+LL | impl const T for S {}
+   |      ^^^^^
+   |
+   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
+  --> $DIR/feature-gate.rs:8:1
+   |
+LL | #[const_trait]
+   | ^^^^^^^^^^^^^^
+   |
+   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs b/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs
new file mode 100644
index 00000000000..5495b531cff
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+
+use std::marker::PhantomData;
+
+struct S<T>(PhantomData<T>);
+
+impl<T> Copy for S<T> {}
+impl<T> Clone for S<T> {
+    fn clone(&self) -> Self {
+        S(PhantomData)
+    }
+}
+
+impl<T> const std::ops::Add for S<T> {
+    type Output = Self;
+
+    fn add(self, _: Self) -> Self {
+        S(std::marker::PhantomData)
+    }
+}
+
+const fn twice<T: std::ops::Add>(arg: S<T>) -> S<T> {
+    arg + arg
+}
+
+fn main() {
+    let _ = twice(S(PhantomData::<i32>));
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs
new file mode 100644
index 00000000000..337c733403b
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs
@@ -0,0 +1,17 @@
+// Regression test for #69615.
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait MyTrait {
+    fn method(&self) -> Option<()>;
+}
+
+impl const MyTrait for () {
+    fn method(&self) -> Option<()> {
+        Some(())?; //~ ERROR `?` is not allowed in a `const fn`
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
new file mode 100644
index 00000000000..6d2be1daa37
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `?` is not allowed in a `const fn`
+  --> $DIR/hir-const-check.rs:12:9
+   |
+LL |         Some(())?;
+   |         ^^^^^^^^^
+   |
+   = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+   = help: add `#![feature(const_try)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
new file mode 100644
index 00000000000..05b26465c5b
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+struct S;
+trait T {}
+
+impl ~const T for S {}
+//~^ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
new file mode 100644
index 00000000000..0a91719e1f1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/impl-tilde-const-trait.rs:6:6
+   |
+LL | impl ~const T for S {}
+   |      ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
new file mode 100644
index 00000000000..6df9696f2cb
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+    fn req(&self);
+
+    fn default() {}
+}
+
+struct S;
+
+impl const Tr for u16 {
+    fn default() {}
+} //~^^ ERROR not all trait items implemented
+
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
new file mode 100644
index 00000000000..6c6ca9f5db8
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `req`
+  --> $DIR/impl-with-default-fn-fail.rs:12:1
+   |
+LL |     fn req(&self);
+   |     -------------- `req` from trait
+...
+LL | impl const Tr for u16 {
+   | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
new file mode 100644
index 00000000000..ae81421e9e1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+    fn req(&self);
+
+    fn default() {}
+}
+
+impl const Tr for u8 {
+    fn req(&self) {}
+}
+
+macro_rules! impl_tr {
+    ($ty: ty) => {
+        impl const Tr for $ty {
+            fn req(&self) {}
+        }
+    }
+}
+
+impl_tr!(u64);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
new file mode 100644
index 00000000000..f8ac793e4c1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+struct S;
+
+#[const_trait]
+trait A {}
+#[const_trait]
+trait B {}
+
+impl const A for S {}
+impl const B for S {}
+
+impl S {
+    const fn a<T: ~const A>() where T: ~const B {
+
+    }
+}
+
+const _: () = S::a::<S>();
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs
new file mode 100644
index 00000000000..afd0d137bb4
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs
@@ -0,0 +1,13 @@
+#![feature(const_trait_impl)]
+#![allow(bare_trait_objects)]
+
+struct S;
+trait T {}
+
+impl const S {}
+//~^ ERROR inherent impls cannot be `const`
+
+impl const T {}
+//~^ ERROR inherent impls cannot be `const`
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
new file mode 100644
index 00000000000..8c55627031d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
@@ -0,0 +1,22 @@
+error: inherent impls cannot be `const`
+  --> $DIR/inherent-impl.rs:7:12
+   |
+LL | impl const S {}
+   |      ----- ^ inherent impl for this type
+   |      |
+   |      `const` because of this
+   |
+   = note: only trait implementations may be annotated with `const`
+
+error: inherent impls cannot be `const`
+  --> $DIR/inherent-impl.rs:10:12
+   |
+LL | impl const T {}
+   |      ----- ^ inherent impl for this type
+   |      |
+   |      `const` because of this
+   |
+   = note: only trait implementations may be annotated with `const`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs
new file mode 100644
index 00000000000..9f3f38ad4bc
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs
@@ -0,0 +1,39 @@
+// revisions: nn ny yn yy
+// check-pass
+#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)]
+
+#[cfg_attr(any(yn, yy), const_trait)]
+pub trait Index {
+    type Output;
+}
+
+#[cfg_attr(any(ny, yy), const_trait)]
+pub trait IndexMut where Self: Index {
+    const C: <Self as Index>::Output;
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
+}
+
+impl Index for () { type Output = (); }
+
+#[cfg(not(any(nn, yn)))]
+impl const IndexMut for <() as Index>::Output {
+    const C: <Self as Index>::Output = ();
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+        where <Self as Index>::Output:,
+    {}
+}
+
+#[cfg(any(nn, yn))]
+impl IndexMut for <() as Index>::Output {
+    const C: <Self as Index>::Output = ();
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+        where <Self as Index>::Output:,
+    {}
+}
+
+const C: <() as Index>::Output = ();
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs b/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs
new file mode 100644
index 00000000000..fe4e9108130
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs
@@ -0,0 +1,15 @@
+#![feature(allocator_api)]
+#![feature(const_trait_impl)]
+
+use core::convert::{From, TryFrom};
+//~^ ERROR
+//~| ERROR
+
+use std::pin::Pin;
+use std::alloc::Allocator;
+impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
+where
+    A: 'static,
+{}
+
+pub fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr
new file mode 100644
index 00000000000..8bf00eaff1f
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,19 @@
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs b/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs
new file mode 100644
index 00000000000..07d3f51edce
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl)]
+
+struct Bug {
+    inner: [(); match || 1 {
+        n => n(),
+        //~^ ERROR the trait bound
+        //~| ERROR the trait bound
+        //~| ERROR cannot call non-const closure in constants
+    }],
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr
new file mode 100644
index 00000000000..b98ccbe5d03
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr
@@ -0,0 +1,41 @@
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+  --> $DIR/issue-102985.rs:5:14
+   |
+LL |         n => n(),
+   |              ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+   |
+   = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+  --> $DIR/issue-102985.rs:5:14
+   |
+LL |         n => n(),
+   |              ^^^
+   = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+  --> $DIR/issue-102985.rs:5:14
+   |
+LL |         n => n(),
+   |              ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+   |
+   = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+  --> $DIR/issue-102985.rs:5:14
+   |
+LL |         n => n(),
+   |              ^^^
+   = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0015]: cannot call non-const closure in constants
+  --> $DIR/issue-102985.rs:5:14
+   |
+LL |         n => n(),
+   |              ^^^
+   |
+   = note: closures need an RFC before allowed to be called in constants
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs b/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs
new file mode 100644
index 00000000000..d81724a3685
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs
@@ -0,0 +1,5 @@
+// check-pass
+
+const _: fn(&String) = |s| { &*s as &str; };
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs
new file mode 100644
index 00000000000..b604c65d751
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs
@@ -0,0 +1,20 @@
+#![feature(const_fmt_arguments_new)]
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+    fn req(&self);
+
+    fn prov(&self) {
+        println!("lul"); //~ ERROR: cannot call non-const fn `_print` in constant functions
+        self.req();
+    }
+}
+
+struct S;
+
+impl const Tr for S {
+    fn req(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr
new file mode 100644
index 00000000000..082c0333fbf
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot call non-const fn `_print` in constant functions
+  --> $DIR/issue-79450.rs:9:9
+   |
+LL |         println!("lul");
+   |         ^^^^^^^^^^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs b/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs
new file mode 100644
index 00000000000..b132c395ac7
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs
@@ -0,0 +1,13 @@
+#![feature(const_trait_impl)]
+
+pub trait A {
+    fn assoc() -> bool;
+}
+
+pub const fn foo<T: A>() -> bool {
+    T::assoc()
+    //~^ ERROR the trait bound
+    //~| ERROR cannot call non-const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr
new file mode 100644
index 00000000000..95592350520
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: ~const A` is not satisfied
+  --> $DIR/issue-88155.rs:8:5
+   |
+LL |     T::assoc()
+   |     ^^^^^^^^^^ the trait `~const A` is not implemented for `T`
+   |
+note: the trait `A` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/issue-88155.rs:8:5
+   |
+LL |     T::assoc()
+   |     ^^^^^^^^^^
+
+error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
+  --> $DIR/issue-88155.rs:8:5
+   |
+LL |     T::assoc()
+   |     ^^^^^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs
new file mode 100644
index 00000000000..21ddf4ab4e5
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+fn foo<T>() where T: ~const Bar {}
+//~^ ERROR `~const` is not allowed
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr
new file mode 100644
index 00000000000..b2a9365378b
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+  --> $DIR/issue-90052.rs:6:22
+   |
+LL | fn foo<T>() where T: ~const Bar {}
+   |                      ^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/issue-90052.rs:6:4
+   |
+LL | fn foo<T>() where T: ~const Bar {}
+   |    ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs b/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs
new file mode 100644
index 00000000000..96a3e386e6e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs
@@ -0,0 +1,23 @@
+// Regression test for #92111.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+use std::marker::Destruct;
+
+pub trait Tr {}
+
+#[allow(drop_bounds)]
+impl<T: Drop> Tr for T {}
+
+#[derive(Debug)]
+pub struct S(i32);
+
+impl Tr for S {}
+
+const fn a<T: ~const Destruct>(t: T) {}
+
+fn main() {
+    a(S(0));
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
new file mode 100644
index 00000000000..4d346965394
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
@@ -0,0 +1,15 @@
+// Regression test for #92230.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait Super {}
+#[const_trait]
+pub trait Sub: Super {}
+
+impl<A> const Super for &A where A: ~const Super {}
+impl<A> const Sub for &A where A: ~const Sub {}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs
new file mode 100644
index 00000000000..a851136009c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(const_trait_impl, once_cell)]
+
+use std::sync::LazyLock;
+
+static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
+    let x = || String::new();
+    x()
+});
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
new file mode 100644
index 00000000000..1a4509b1869
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Convert<T> {
+    fn to(self) -> T;
+}
+
+impl<A, B> const Convert<B> for A where B: ~const From<A> {
+    fn to(self) -> B {
+        B::from(self)
+    }
+}
+
+const FOO: fn() -> String = || "foo".to();
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs
new file mode 100644
index 00000000000..3ac90992486
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs
@@ -0,0 +1,46 @@
+// Tests that trait bounds on specializing trait impls must be `~const` if the
+// same bound is present on the default impl and is `~const` there.
+
+#![feature(const_trait_impl)]
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {}
+
+#[const_trait]
+trait Bar {}
+
+// bgr360: I was only able to exercise the code path that raises the
+// "missing ~const qualifier" error by making this base impl non-const, even
+// though that doesn't really make sense to do. As seen below, if the base impl
+// is made const, rustc fails earlier with an overlapping impl failure.
+impl<T> Bar for T
+where
+    T: ~const Foo,
+{}
+
+impl<T> Bar for T
+where
+    T: Foo, //~ ERROR missing `~const` qualifier
+    T: Specialize,
+{}
+
+#[const_trait]
+trait Baz {}
+
+impl<T> const Baz for T
+where
+    T: ~const Foo,
+{}
+
+impl<T> const Baz for T //~ ERROR conflicting implementations of trait `Baz`
+where
+    T: Foo,
+    T: Specialize,
+{}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
new file mode 100644
index 00000000000..4aea1979421
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
@@ -0,0 +1,18 @@
+error: missing `~const` qualifier for specialization
+  --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:8
+   |
+LL |     T: Foo,
+   |        ^^^
+
+error[E0119]: conflicting implementations of trait `Baz`
+  --> $DIR/const-default-bound-non-const-specialized-bound.rs:40:1
+   |
+LL | impl<T> const Baz for T
+   | ----------------------- first implementation here
+...
+LL | impl<T> const Baz for T
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs
new file mode 100644
index 00000000000..9ddea427cfd
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs
@@ -0,0 +1,39 @@
+// Tests that a const default trait impl can be specialized by another const
+// trait impl and that the specializing impl will be used during const-eval.
+
+// run-pass
+
+#![feature(const_trait_impl)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+    fn value() -> u32;
+}
+
+const fn get_value<T: ~const Value>() -> u32 {
+    T::value()
+}
+
+impl<T> const Value for T {
+    default fn value() -> u32 {
+        0
+    }
+}
+
+struct FortyTwo;
+
+impl const Value for FortyTwo {
+    fn value() -> u32 {
+        42
+    }
+}
+
+const ZERO: u32 = get_value::<()>();
+
+const FORTY_TWO: u32 = get_value::<FortyTwo>();
+
+fn main() {
+    assert_eq!(ZERO, 0);
+    assert_eq!(FORTY_TWO, 42);
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs
new file mode 100644
index 00000000000..a3bb9b3f93e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs
@@ -0,0 +1,26 @@
+// Tests that specializing trait impls must be at least as const as the default impl.
+
+#![feature(const_trait_impl)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+    fn value() -> u32;
+}
+
+impl<T> const Value for T {
+    default fn value() -> u32 {
+        0
+    }
+}
+
+struct FortyTwo;
+
+impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl
+    fn value() -> u32 {
+        println!("You can't do that (constly)");
+        42
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr
new file mode 100644
index 00000000000..24766804708
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on const impl with non-const impl
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1
+   |
+LL | impl Value for FortyTwo {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs
new file mode 100644
index 00000000000..2aac0a2b4d1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Foo {
+    fn foo();
+}
+
+impl const Foo for u32 {
+    default fn foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs
new file mode 100644
index 00000000000..9c2c2cf1610
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs
@@ -0,0 +1,37 @@
+// Tests that `~const` trait bounds can be used to specialize const trait impls.
+
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+
+#[const_trait]
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {}
+
+impl<T> const Foo for T {}
+
+impl<T> const Foo for T
+where
+    T: ~const Specialize,
+{}
+
+#[const_trait]
+trait Bar {}
+
+impl<T> const Bar for T
+where
+    T: ~const Foo,
+{}
+
+impl<T> const Bar for T
+where
+    T: ~const Foo,
+    T: ~const Specialize,
+{}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs
new file mode 100644
index 00000000000..1e6b1c6513b
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs
@@ -0,0 +1,45 @@
+// Tests that `T: ~const Foo` in a specializing impl is treated as equivalent to
+// `T: Foo` in the default impl for the purposes of specialization (i.e., it
+// does not think that the user is attempting to specialize on trait `Foo`).
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+#![feature(const_trait_impl)]
+
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {}
+
+#[const_trait]
+trait Bar {}
+
+impl<T> Bar for T
+where
+    T: Foo,
+{}
+
+impl<T> const Bar for T
+where
+    T: ~const Foo,
+    T: Specialize,
+{}
+
+#[const_trait]
+trait Baz {}
+
+impl<T> const Baz for T
+where
+    T: Foo,
+{}
+
+impl<T> const Baz for T
+where
+    T: ~const Foo,
+    T: Specialize,
+{}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs
new file mode 100644
index 00000000000..35aa52fbd4e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs
@@ -0,0 +1,39 @@
+// Tests that a non-const default impl can be specialized by a const trait impl,
+// but that the default impl cannot be used in a const context.
+
+// run-pass
+
+#![feature(const_trait_impl)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+    fn value() -> u32;
+}
+
+const fn get_value<T: ~const Value>() -> u32 {
+    T::value()
+}
+
+impl<T> Value for T {
+    default fn value() -> u32 {
+        println!("You can't do that (constly)");
+        0
+    }
+}
+
+struct FortyTwo;
+
+impl const Value for FortyTwo {
+    fn value() -> u32 {
+        42
+    }
+}
+
+fn main() {
+    let zero = get_value::<()>();
+    assert_eq!(zero, 0);
+
+    const FORTY_TWO: u32 = get_value::<FortyTwo>();
+    assert_eq!(FORTY_TWO, 42);
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs
new file mode 100644
index 00000000000..633543700d2
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+    fn a() -> u32;
+}
+
+impl<T: Default> A for T {
+    default fn a() -> u32 {
+        2
+    }
+}
+
+impl<T: Default + ~const Sup> const A for T {
+    fn a() -> u32 {
+        3
+    }
+}
+
+const fn generic<T: Default>() {
+    <T as A>::a();
+    //~^ ERROR: the trait bound `T: ~const Sup` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr
new file mode 100644
index 00000000000..c554671e18d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Sup` is not satisfied
+  --> $DIR/specializing-constness-2.rs:27:5
+   |
+LL |     <T as A>::a();
+   |     ^^^^^^^^^^^^^ the trait `~const Sup` is not implemented for `T`
+   |
+note: required for `T` to implement `~const A`
+  --> $DIR/specializing-constness-2.rs:20:37
+   |
+LL | impl<T: Default + ~const Sup> const A for T {
+   |                                     ^     ^
+help: consider further restricting this bound
+   |
+LL | const fn generic<T: Default + ~const Sup>() {
+   |                             ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs
new file mode 100644
index 00000000000..9ab170f0920
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs
@@ -0,0 +1,28 @@
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+    fn a() -> u32;
+}
+
+impl<T: ~const Default> const A for T {
+    default fn a() -> u32 {
+        2
+    }
+}
+
+impl<T: Default + Sup> A for T {
+//~^ ERROR: cannot specialize
+//~| ERROR: missing `~const` qualifier
+    fn a() -> u32 {
+        3
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr
new file mode 100644
index 00000000000..843fc6ce84d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr
@@ -0,0 +1,14 @@
+error: cannot specialize on const impl with non-const impl
+  --> $DIR/specializing-constness.rs:20:1
+   |
+LL | impl<T: Default + Sup> A for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing `~const` qualifier for specialization
+  --> $DIR/specializing-constness.rs:20:9
+   |
+LL | impl<T: Default + Sup> A for T {
+   |         ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs
new file mode 100644
index 00000000000..fc0d82727b5
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs
@@ -0,0 +1,16 @@
+// aux-build: staged-api.rs
+extern crate staged_api;
+
+use staged_api::*;
+
+// Const stability has no impact on usage in non-const contexts.
+fn non_const_context() {
+    Unstable::func();
+}
+
+const fn stable_const_context() {
+    Unstable::func();
+    //~^ ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr
new file mode 100644
index 00000000000..61f9840e0d0
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
+  --> $DIR/staged-api-user-crate.rs:12:5
+   |
+LL |     Unstable::func();
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/staged-api.rs
new file mode 100644
index 00000000000..1d79f5adf93
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.rs
@@ -0,0 +1,63 @@
+// revisions: stable unstable
+
+#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
+#![feature(const_trait_impl)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// aux-build: staged-api.rs
+extern crate staged_api;
+
+use staged_api::*;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Foo;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))]
+impl const MyTrait for Foo {
+    //[stable]~^ ERROR trait implementations cannot be const stable yet
+    fn func() {}
+}
+
+// Const stability has no impact on usage in non-const contexts.
+fn non_const_context() {
+    Unstable::func();
+    Foo::func();
+}
+
+#[unstable(feature = "none", issue = "none")]
+const fn const_context() {
+    Unstable::func();
+    // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+    // not const-stable.
+    Foo::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
+    // ^ fails, because the `foo` feature is not active
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+pub const fn const_context_not_const_stable() {
+    //[stable]~^ ERROR function has missing const stability attribute
+    Unstable::func();
+    // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+    // not const-stable.
+    Foo::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
+    // ^ fails, because the `foo` feature is not active
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "cheese", since = "1.0.0")]
+const fn stable_const_context() {
+    Unstable::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
+    Foo::func();
+    //[unstable]~^ ERROR not yet stable as a const fn
+    const_context_not_const_stable()
+    //[unstable]~^ ERROR not yet stable as a const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
new file mode 100644
index 00000000000..a1aca762ef4
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
@@ -0,0 +1,25 @@
+error: trait implementations cannot be const stable yet
+  --> $DIR/staged-api.rs:19:1
+   |
+LL | / impl const MyTrait for Foo {
+LL | |
+LL | |     fn func() {}
+LL | | }
+   | |_^
+   |
+   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+
+error: function has missing const stability attribute
+  --> $DIR/staged-api.rs:42:1
+   |
+LL | / pub const fn const_context_not_const_stable() {
+LL | |
+LL | |     Unstable::func();
+LL | |     // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+...  |
+LL | |     // ^ fails, because the `foo` feature is not active
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
new file mode 100644
index 00000000000..c38d1a81ae7
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
@@ -0,0 +1,42 @@
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:35:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:47:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:55:5
+   |
+LL |     Unstable::func();
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: const-stable functions can only call other const-stable functions
+
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:57:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: const-stable functions can only call other const-stable functions
+
+error: `const_context_not_const_stable` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:59:5
+   |
+LL |     const_context_not_const_stable()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: const-stable functions can only call other const-stable functions
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs b/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs
new file mode 100644
index 00000000000..4520a36960c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs
@@ -0,0 +1,18 @@
+// check-pass
+pub struct S<T, F: FnOnce() -> T = fn() -> T> {
+    f: F,
+    x: Option<T>,
+}
+
+impl<T, F: FnOnce() -> T> S<T, F> {
+    pub const fn new(f: F) -> Self {
+        Self { f, x: None }
+    }
+}
+
+#[derive(Default)]
+pub struct Foo;
+
+static LOCKED_CALLSITES: S<Foo> = S::new(Default::default);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs
new file mode 100644
index 00000000000..2f54c09e31c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs
@@ -0,0 +1,21 @@
+// This tests feature gates for const impls in the standard library.
+
+// revisions: stock gated
+//[gated] run-pass
+
+#![cfg_attr(gated, feature(const_trait_impl, const_default_impls))]
+
+fn non_const_context() -> Vec<usize> {
+    Default::default()
+}
+
+const fn const_context() -> Vec<usize> {
+    Default::default()
+    //[stock]~^ ERROR cannot call non-const fn
+}
+
+fn main() {
+    const VAL: Vec<usize> = const_context();
+
+    assert_eq!(VAL, non_const_context());
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr
new file mode 100644
index 00000000000..0b450a94742
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions
+  --> $DIR/std-impl-gate.rs:13:5
+   |
+LL |     Default::default()
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
new file mode 100644
index 00000000000..d4f42b787e4
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:11:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
new file mode 100644
index 00000000000..d4f42b787e4
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:11:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
new file mode 100644
index 00000000000..d183efde2df
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+    fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: Bar>(x: &T) {
+    x.a();
+    //[yn,yy]~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
new file mode 100644
index 00000000000..13fc719f28c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail-2.rs:15:7
+   |
+LL |     x.a();
+   |       ^ the trait `~const Foo` is not implemented for `T`
+   |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^
+help: consider further restricting this bound
+   |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+   |                     ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
new file mode 100644
index 00000000000..13fc719f28c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail-2.rs:15:7
+   |
+LL |     x.a();
+   |       ^ the trait `~const Foo` is not implemented for `T`
+   |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^
+help: consider further restricting this bound
+   |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+   |                     ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
new file mode 100644
index 00000000000..d433e1cfa69
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -0,0 +1,14 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:12:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:15:24
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                        ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
new file mode 100644
index 00000000000..2a7e8e00bc7
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:12:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
new file mode 100644
index 00000000000..70d2936d3b2
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
@@ -0,0 +1,20 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+//[yy] check-pass
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+    fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: ~const Bar>(x: &T) {
+    //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+    x.a();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
new file mode 100644
index 00000000000..e5978c12a09
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:15:24
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                        ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
new file mode 100644
index 00000000000..3e2b81368a5
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
@@ -0,0 +1,18 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    fn a(&self);
+}
+#[const_trait]
+trait Bar: ~const Foo {}
+
+struct S;
+impl Foo for S {
+    fn a(&self) {}
+}
+
+impl const Bar for S {}
+//~^ ERROR the trait bound
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
new file mode 100644
index 00000000000..1f8f312df01
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail.rs:15:12
+   |
+LL | impl const Bar for S {}
+   |            ^^^ the trait `~const Foo` is not implemented for `S`
+   |
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+  --> $DIR/super-traits-fail.rs:15:12
+   |
+LL | impl const Bar for S {}
+   |            ^^^
+note: required by a bound in `Bar`
+  --> $DIR/super-traits-fail.rs:8:12
+   |
+LL | trait Bar: ~const Foo {}
+   |            ^^^^^^^^^^ required by this bound in `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits.rs
new file mode 100644
index 00000000000..df96f6fb4ab
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits.rs
@@ -0,0 +1,25 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    fn a(&self);
+}
+
+#[const_trait]
+trait Bar: ~const Foo {}
+
+struct S;
+impl const Foo for S {
+    fn a(&self) {}
+}
+
+impl const Bar for S {}
+
+const fn foo<T: ~const Bar>(t: &T) {
+    t.a();
+}
+
+const _: () = foo(&S);
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/syntax.rs b/tests/ui/rfc-2632-const-trait-impl/syntax.rs
new file mode 100644
index 00000000000..7ac2458e399
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/syntax.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+
+// For now, this parses since an error does not occur until AST lowering.
+impl ~const T {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
new file mode 100644
index 00000000000..78a64b9018a
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -0,0 +1,34 @@
+#![feature(const_trait_impl)]
+#![feature(generic_arg_infer)]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+   fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+      Foo
+   }
+}
+
+#[const_trait]
+trait Add42 {
+    fn add(a: usize) -> usize;
+}
+
+impl const Add42 for () {
+    fn add(a: usize) -> usize {
+        a + 42
+    }
+}
+
+fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+    //~^ ERROR `~const` is not allowed here
+    Foo
+}
+
+fn main() {
+   let foo = Foo::<0>;
+   let foo = bar::<(), _>(foo);
+   let _foo = bar::<(), _>(foo);
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
new file mode 100644
index 00000000000..aae72f36e57
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-and-const-params.rs:25:11
+   |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+   |           ^^^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/tilde-const-and-const-params.rs:25:4
+   |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+   |    ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
new file mode 100644
index 00000000000..95f7aaba0fc
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -0,0 +1,7 @@
+#![feature(const_trait_impl)]
+#![feature(associated_type_bounds)]
+
+struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `~const` and `?` are mutually exclusive
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
new file mode 100644
index 00000000000..d20f146df3f
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -0,0 +1,8 @@
+error: `~const` and `?` are mutually exclusive
+  --> $DIR/tilde-const-invalid-places.rs:4:25
+   |
+LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+   |                         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs
new file mode 100644
index 00000000000..9b3c2cf2a3b
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S<
+    T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add,
+    T: ~const ?for<'a: 'b> m::Trait<'a>,
+>;
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs
new file mode 100644
index 00000000000..06e4ede8b5e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: ~const ~const Tr>;
+//~^ ERROR expected identifier, found `~`
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr
new file mode 100644
index 00000000000..928d23e8a42
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `~`
+  --> $DIR/tilde-twice.rs:5:20
+   |
+LL | struct S<T: ~const ~const Tr>;
+   |                    ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
new file mode 100644
index 00000000000..285cef571f3
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    fn foo(&self) {}
+}
+
+struct Bar<T>(T);
+
+impl<T: ~const Foo> Bar<T> {
+    const fn foo(&self) {
+        self.0.foo()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs
new file mode 100644
index 00000000000..334fc4cb847
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs
@@ -0,0 +1,50 @@
+// check-pass
+
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![feature(const_t_try)]
+#![feature(const_try)]
+#![feature(try_trait_v2)]
+
+#![stable(feature = "foo", since = "1.0")]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+#[stable(feature = "foo", since = "1.0")]
+pub struct T;
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const Try for T {
+    type Output = T;
+    type Residual = T;
+
+    fn from_output(t: T) -> T {
+        t
+    }
+
+    fn branch(self) -> ControlFlow<T, T> {
+        ControlFlow::Continue(self)
+    }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const FromResidual for T {
+    fn from_residual(t: T) -> T {
+        t
+    }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+#[const_trait]
+pub trait Tr {
+    #[stable(feature = "foo", since = "1.0")]
+    fn bar() -> T {
+        T?
+        // Should be allowed.
+        // Must enable unstable features to call this trait fn in const contexts.
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
new file mode 100644
index 00000000000..bfe98b98c74
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -0,0 +1,31 @@
+// Like trait-where-clause.rs, but we are calling from a const context.
+// Checking the validity of traits' where clauses happen at a later stage.
+// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a
+// test is not enough.
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+#[const_trait]
+trait Foo {
+    fn a();
+    fn b() where Self: ~const Bar;
+    fn c<T: ~const Bar>();
+}
+
+const fn test1<T: ~const Foo + Bar>() {
+    T::a();
+    T::b();
+    //~^ ERROR the trait bound
+    T::c::<T>();
+    //~^ ERROR the trait bound
+}
+
+const fn test2<T: ~const Foo + ~const Bar>() {
+    T::a();
+    T::b();
+    T::c::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
new file mode 100644
index 00000000000..f2846b6a662
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+  --> $DIR/trait-where-clause-const.rs:19:5
+   |
+LL |     T::b();
+   |     ^^^^^^ the trait `~const Bar` is not implemented for `T`
+   |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/trait-where-clause-const.rs:19:5
+   |
+LL |     T::b();
+   |     ^^^^^^
+help: consider further restricting this bound
+   |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+   |                                    ++++++++++++
+
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+  --> $DIR/trait-where-clause-const.rs:21:5
+   |
+LL |     T::c::<T>();
+   |     ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
+   |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/trait-where-clause-const.rs:21:5
+   |
+LL |     T::c::<T>();
+   |     ^^^^^^^^^^^
+help: consider further restricting this bound
+   |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+   |                                    ++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
new file mode 100644
index 00000000000..4b8b004069d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
@@ -0,0 +1,41 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {
+    fn bar() -> u8;
+}
+
+#[const_trait]
+trait Foo {
+    fn foo() -> u8 where Self: ~const Bar {
+        <Self as Bar>::bar() * 6
+    }
+}
+
+struct NonConst;
+struct Const;
+
+impl Bar for NonConst {
+    fn bar() -> u8 {
+        3
+    }
+}
+
+impl Foo for NonConst {}
+
+impl const Bar for Const {
+    fn bar() -> u8 {
+        4
+    }
+}
+
+impl const Foo for Const {}
+
+fn main() {
+    const ANS1: u8 = Const::foo();
+    let ans2 = NonConst::foo();
+
+    assert_eq!(ANS1 + ans2, 42);
+}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
new file mode 100644
index 00000000000..3b028ac48db
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+    fn bar() where Self: ~const Foo;
+}
+
+struct S;
+
+impl Foo for S {
+    fn bar() {}
+}
+
+fn baz<T: Foo>() {
+    T::bar();
+}
+
+const fn qux<T: ~const Foo>() {
+    T::bar();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
new file mode 100644
index 00000000000..85ca5fc9048
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+trait Foo {
+    fn a();
+    fn b() where Self: ~const Bar;
+    fn c<T: ~const Bar>();
+}
+
+fn test1<T: Foo>() {
+    T::a();
+    T::b();
+    //~^ ERROR the trait bound
+    T::c::<T>();
+    //~^ ERROR the trait bound
+}
+
+fn test2<T: Foo + Bar>() {
+    T::a();
+    T::b();
+    T::c::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
new file mode 100644
index 00000000000..11f0c40160d
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:14:5
+   |
+LL |     T::b();
+   |     ^^^^ the trait `Bar` is not implemented for `T`
+   |
+note: required by a bound in `Foo::b`
+  --> $DIR/trait-where-clause.rs:8:24
+   |
+LL |     fn b() where Self: ~const Bar;
+   |                        ^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider further restricting this bound
+   |
+LL | fn test1<T: Foo + Bar>() {
+   |                 +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:16:12
+   |
+LL |     T::c::<T>();
+   |            ^ the trait `Bar` is not implemented for `T`
+   |
+note: required by a bound in `Foo::c`
+  --> $DIR/trait-where-clause.rs:9:13
+   |
+LL |     fn c<T: ~const Bar>();
+   |             ^^^^^^^^^^ required by this bound in `Foo::c`
+help: consider further restricting this bound
+   |
+LL | fn test1<T: Foo + Bar>() {
+   |                 +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs b/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs
new file mode 100644
index 00000000000..d63381b5f2c
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: const Tr>;
+//~^ ERROR const bounds must start with `~`
diff --git a/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr
new file mode 100644
index 00000000000..31300354a57
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr
@@ -0,0 +1,10 @@
+error: const bounds must start with `~`
+  --> $DIR/without-tilde.rs:5:13
+   |
+LL | struct S<T: const Tr>;
+   |             -^^^^
+   |             |
+   |             help: add `~`: `~`
+
+error: aborting due to previous error
+