summaryrefslogtreecommitdiffstats
path: root/src/test/ui/rfc-2632-const-trait-impl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/rfc-2632-const-trait-impl
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs30
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr25
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs23
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs18
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs29
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs42
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs28
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs31
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr16
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr27
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs31
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr25
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-closures.rs30
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs29
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs25
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr78
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs51
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr78
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs112
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr26
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs18
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs16
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs30
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs16
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs26
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs20
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr22
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs23
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs16
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.rs63
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr25
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr42
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs16
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits.rs22
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/syntax.rs8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs29
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr56
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs50
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs40
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs23
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs39
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr77
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr8
88 files changed, 2104 insertions, 0 deletions
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
new file mode 100644
index 000000000..99eacaa83
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
@@ -0,0 +1,30 @@
+#![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)
+ }
+}
+
+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
+}
+
+trait Baz {
+ type Qux: std::ops::Add;
+}
+
+impl const Baz for NonConstAdd {
+ type Qux = NonConstAdd; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
new file mode 100644
index 000000000..64501c523
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -0,0 +1,25 @@
+error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
+ --> $DIR/assoc-type.rs:18: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:18:16
+ |
+LL | type Bar = NonConstAdd;
+ | ^^^^^^^^^^^
+note: required by a bound in `Foo::Bar`
+ --> $DIR/assoc-type.rs:14:15
+ |
+LL | type Bar: ~const std::ops::Add;
+ | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add {
+ | +++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs
new file mode 100644
index 000000000..01ac74fef
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr
new file mode 100644
index 000000000..b18f33218
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
new file mode 100644
index 000000000..e73082c11
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
new file mode 100644
index 000000000..19e900609
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
@@ -0,0 +1,18 @@
+#![feature(const_trait_impl)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+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/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
new file mode 100644
index 000000000..24b9235bb
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+
+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
+ //~| ERROR cannot call non-const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
new file mode 100644
index 000000000..1fc9db277
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
+ --> $DIR/call-const-trait-method-fail.rs:24: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:24:7
+ |
+LL | a.plus(b)
+ | ^^^^^^^
+
+error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
+ --> $DIR/call-const-trait-method-fail.rs:24:7
+ |
+LL | a.plus(b)
+ | ^^^^^^^
+ |
+ = 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/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
new file mode 100644
index 000000000..cf38bc3c9
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
@@ -0,0 +1,42 @@
+// 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)
+ }
+}
+
+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/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
new file mode 100644
index 000000000..89dc47aad
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -0,0 +1,14 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
new file mode 100644
index 000000000..b00ff1f2f
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
new file mode 100644
index 000000000..c8ded0fa7
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
new file mode 100644
index 000000000..2bc5ee512
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
new file mode 100644
index 000000000..83d395dda
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -0,0 +1,16 @@
+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
+ | ^^
+ = help: the trait `PartialEq<&B>` is implemented for `&A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
new file mode 100644
index 000000000..e197c8b73
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
new file mode 100644
index 000000000..d3e14a53a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -0,0 +1,21 @@
+#![feature(const_trait_impl)]
+
+struct S;
+
+impl PartialEq for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+}
+
+const fn equals_self<T: ~const PartialEq>(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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
new file mode 100644
index 000000000..0a2a5f0f2
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -0,0 +1,27 @@
+error[E0277]: can't compare `S` with `S` in const contexts
+ --> $DIR/call-generic-method-nonconst.rs:18:34
+ |
+LL | pub const EQ: bool = equals_self(&S);
+ | ----------- ^^ no implementation for `S == S`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `~const PartialEq` is not implemented for `S`
+note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
+ --> $DIR/call-generic-method-nonconst.rs:18:34
+ |
+LL | pub const EQ: bool = equals_self(&S);
+ | ^^
+note: required by a bound in `equals_self`
+ --> $DIR/call-generic-method-nonconst.rs:11:25
+ |
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
+help: consider annotating `S` with `#[derive(PartialEq)]`
+ |
+LL | #[derive(PartialEq)]
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
new file mode 100644
index 000000000..40565d1b7
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
new file mode 100644
index 000000000..f66d63da6
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
new file mode 100644
index 000000000..f515ec198
--- /dev/null
+++ b/src/test/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 `std::ops::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/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
new file mode 100644
index 000000000..b3e3dd62b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
@@ -0,0 +1,15 @@
+#![feature(const_trait_impl)]
+
+struct S;
+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/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
new file mode 100644
index 000000000..9e49785c5
--- /dev/null
+++ b/src/test/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:11: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/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs
new file mode 100644
index 000000000..755d85398
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
new file mode 100644
index 000000000..140a06a73
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
new file mode 100644
index 000000000..ec724cc96
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -0,0 +1,19 @@
+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:18
+ |
+LL | NonConstImpl.a();
+ | ^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
+ | +++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs
new file mode 100644
index 000000000..948f0efbc
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
new file mode 100644
index 000000000..9dbaffd4c
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -0,0 +1,78 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:43:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+ |
+ = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:34: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:45: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:45: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:34:19
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:47:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+ |
+note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+ --> $DIR/const-drop-fail.rs:28:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: 1 redundant requirement hidden
+ = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:34:19
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `check`
+help: consider borrowing here
+ |
+LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | +
+LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
new file mode 100644
index 000000000..001dd430a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -0,0 +1,51 @@
+// 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) {}
+}
+
+trait A { fn a() { println!("A"); } }
+
+impl A for NonTrivialDrop {}
+
+struct ConstDropImplWithBounds<T: 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
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
new file mode 100644
index 000000000..9dbaffd4c
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -0,0 +1,78 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:43:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+ |
+ = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:34: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:45: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:45: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:34:19
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:47:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+ |
+note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+ --> $DIR/const-drop-fail.rs:28:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: 1 redundant requirement hidden
+ = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:34:19
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `check`
+help: consider borrowing here
+ |
+LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | +
+LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644
index 000000000..04462c0a1
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,112 @@
+// 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);
+
+ pub trait SomeTrait {
+ fn foo();
+ }
+ impl const SomeTrait for () {
+ fn foo() {}
+ }
+ // non-const impl
+ impl SomeTrait for i32 {
+ fn foo() {}
+ }
+
+ pub struct ConstDropWithBound<T: 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/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs
new file mode 100644
index 000000000..bed4e9fd1
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr
new file mode 100644
index 000000000..603f6b7d2
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
new file mode 100644
index 000000000..470c653dd
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
@@ -0,0 +1,15 @@
+#![feature(const_trait_impl)]
+
+trait Foo {}
+
+const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
+
+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/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
new file mode 100644
index 000000000..709084c86
--- /dev/null
+++ b/src/test/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:5: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:9: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/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs
new file mode 100644
index 000000000..bde8bf20f
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
new file mode 100644
index 000000000..174c62912
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -0,0 +1,19 @@
+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:14
+ |
+LL | NonConst.func();
+ | ^^^^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs
new file mode 100644
index 000000000..6df47022c
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr
new file mode 100644
index 000000000..086547542
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
new file mode 100644
index 000000000..4619dd113
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -0,0 +1,19 @@
+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:14
+ |
+LL | NonConst.func();
+ | ^^^^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
new file mode 100644
index 000000000..d27291231
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -0,0 +1,16 @@
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
new file mode 100644
index 000000000..7542b81fe
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied
+ --> $DIR/default-method-body-is-const-body-checking.rs:11: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:11:15
+ |
+LL | foo::<()>();
+ | ^^
+note: required by a bound in `foo`
+ --> $DIR/default-method-body-is-const-body-checking.rs:6:28
+ |
+LL | const fn foo<T>() where T: ~const Tr {}
+ | ^^^^^^^^^ required by this bound in `foo`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub trait Foo where (): ~const Tr {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
new file mode 100644
index 000000000..f70ecbc37
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
new file mode 100644
index 000000000..b229053eb
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -0,0 +1,19 @@
+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:12
+ |
+LL | ().a()
+ | ^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub trait Tr where (): ~const Tr {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
new file mode 100644
index 000000000..1b45cd9aa
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
new file mode 100644
index 000000000..af4d3909e
--- /dev/null
+++ b/src/test/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:13:1
+ |
+LL | fn main() {}
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
new file mode 100644
index 000000000..7bac72e1b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
@@ -0,0 +1,13 @@
+// revisions: stock gated
+// gate-test-const_trait_impl
+
+#![cfg_attr(gated, feature(const_trait_impl))]
+#![feature(rustc_attrs)]
+
+struct S;
+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/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
new file mode 100644
index 000000000..91a8bb578
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -0,0 +1,12 @@
+error[E0658]: const trait impls are experimental
+ --> $DIR/feature-gate.rs:9: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: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs
new file mode 100644
index 000000000..5495b531c
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
new file mode 100644
index 000000000..80a4442de
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
@@ -0,0 +1,16 @@
+// Regression test for #69615.
+
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
new file mode 100644
index 000000000..32df63e44
--- /dev/null
+++ b/src/test/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:11: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/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
new file mode 100644
index 000000000..05b26465c
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
new file mode 100644
index 000000000..0a91719e1
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
new file mode 100644
index 000000000..6df9696f2
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
new file mode 100644
index 000000000..6c6ca9f5d
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
new file mode 100644
index 000000000..ae81421e9
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
new file mode 100644
index 000000000..2cef803a9
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
@@ -0,0 +1,20 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+struct S;
+
+trait A {}
+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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
new file mode 100644
index 000000000..afd0d137b
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
new file mode 100644
index 000000000..8c5562703
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs
new file mode 100644
index 000000000..b132c395a
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr
new file mode 100644
index 000000000..955923505
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
new file mode 100644
index 000000000..96a3e386e
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
new file mode 100644
index 000000000..97c27ce1a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
@@ -0,0 +1,13 @@
+// Regression test for #92230.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+pub trait Super {}
+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/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
new file mode 100644
index 000000000..defef9e04
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs
new file mode 100644
index 000000000..fc0d82727
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr
new file mode 100644
index 000000000..61f9840e0
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
new file mode 100644
index 000000000..1d79f5adf
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr
new file mode 100644
index 000000000..a1aca762e
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr
new file mode 100644
index 000000000..c38d1a81a
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs
new file mode 100644
index 000000000..2f54c09e3
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr
new file mode 100644
index 000000000..0b450a947
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
new file mode 100644
index 000000000..7b38c15af
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -0,0 +1,14 @@
+#![feature(const_trait_impl)]
+
+trait Foo {
+ fn a(&self);
+}
+trait Bar: ~const Foo {}
+
+const fn foo<T: Bar>(x: &T) {
+ x.a();
+ //~^ ERROR the trait bound
+ //~| ERROR cannot call
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
new file mode 100644
index 000000000..1766cdbee
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail-2.rs:9: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:9:7
+ |
+LL | x.a();
+ | ^^^
+
+error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
+ --> $DIR/super-traits-fail-2.rs:9:7
+ |
+LL | x.a();
+ | ^^^
+ |
+ = 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/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
new file mode 100644
index 000000000..af465cad3
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
@@ -0,0 +1,16 @@
+#![feature(const_trait_impl)]
+
+trait Foo {
+ fn a(&self);
+}
+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/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
new file mode 100644
index 000000000..9e8b8f8c6
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail.rs:13: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:13:12
+ |
+LL | impl const Bar for S {}
+ | ^^^
+note: required by a bound in `Bar`
+ --> $DIR/super-traits-fail.rs:6:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^ required by this bound in `Bar`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | impl const Bar for S where S: ~const Foo {}
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs
new file mode 100644
index 000000000..aded4ca9a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+trait Foo {
+ fn a(&self);
+}
+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/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs
new file mode 100644
index 000000000..7ac2458e3
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
new file mode 100644
index 000000000..b4302f3e7
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+#![feature(associated_type_bounds)]
+
+trait T {}
+struct S;
+impl T for S {}
+
+fn rpit() -> impl ~const T { S }
+//~^ ERROR `~const` is not allowed
+
+fn apit(_: impl ~const T) {}
+//~^ ERROR `~const` is not allowed
+
+fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+//~^ ERROR `~const` is not allowed
+
+fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
+//~^ ERROR `~const` is not allowed
+
+fn generic<P: ~const T>() {}
+//~^ ERROR `~const` is not allowed
+
+fn where_clause<P>() where P: ~const T {}
+//~^ ERROR `~const` is not allowed
+
+struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `~const` and `?` are mutually exclusive
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
new file mode 100644
index 000000000..033ec21ba
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -0,0 +1,56 @@
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:8:19
+ |
+LL | fn rpit() -> impl ~const T { S }
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:11:17
+ |
+LL | fn apit(_: impl ~const T) {}
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:14:50
+ |
+LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:17:48
+ |
+LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:20:15
+ |
+LL | fn generic<P: ~const T>() {}
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:23:31
+ |
+LL | fn where_clause<P>() where P: ~const T {}
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` and `?` are mutually exclusive
+ --> $DIR/tilde-const-invalid-places.rs:26:25
+ |
+LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs
new file mode 100644
index 000000000..9b3c2cf2a
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs
new file mode 100644
index 000000000..06e4ede8b
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr
new file mode 100644
index 000000000..928d23e8a
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs
new file mode 100644
index 000000000..334fc4cb8
--- /dev/null
+++ b/src/test/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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
new file mode 100644
index 000000000..b7cf9a13b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
new file mode 100644
index 000000000..acea58eae
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
new file mode 100644
index 000000000..d37ed3bb8
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -0,0 +1,39 @@
+#![feature(const_trait_impl)]
+
+trait Bar {}
+
+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 test3<T: Foo>() {
+ T::a();
+ T::b();
+ //~^ ERROR the trait bound
+ T::c::<T>();
+ //~^ ERROR the trait bound
+}
+
+fn test4<T: Foo + Bar>() {
+ T::a();
+ T::b();
+ T::c::<T>();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
new file mode 100644
index 000000000..d5b2d2697
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -0,0 +1,77 @@
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:13: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.rs:13:5
+ |
+LL | T::b();
+ | ^^^^
+note: required by a bound in `Foo::b`
+ --> $DIR/trait-where-clause.rs:7:24
+ |
+LL | fn b() where Self: ~const Bar;
+ | ^^^^^^^^^^ required by this bound in `Foo::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.rs:15: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.rs:15:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^
+note: required by a bound in `Foo::c`
+ --> $DIR/trait-where-clause.rs:8:13
+ |
+LL | fn c<T: ~const Bar>();
+ | ^^^^^^^^^^ required by this bound in `Foo::c`
+help: consider further restricting this bound
+ |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+ | ++++++++++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:27: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:7:24
+ |
+LL | fn b() where Self: ~const Bar;
+ | ^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider further restricting this bound
+ |
+LL | fn test3<T: Foo + Bar>() {
+ | +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:29:5
+ |
+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:8:13
+ |
+LL | fn c<T: ~const Bar>();
+ | ^^^^^^^^^^ required by this bound in `Foo::c`
+help: consider further restricting this bound
+ |
+LL | fn test3<T: Foo + Bar>() {
+ | +++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
new file mode 100644
index 000000000..e8b261545
--- /dev/null
+++ b/src/test/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 expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
new file mode 100644
index 000000000..b6b77ac4a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const`
+ --> $DIR/without-tilde.rs:5:13
+ |
+LL | struct S<T: const Tr>;
+ | ^^^^^ expected one of 10 possible tokens
+
+error: aborting due to previous error
+