From b8bd9815455ac3c1bff865dee30aa694ad19beb6 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 21 Feb 2024 11:30:57 +0000
Subject: [PATCH] Specialization already rejects defining opaque types

---
 .../min_specialization/impl-on-opaque.rs      | 31 +++++++++++++++++++
 .../min_specialization/impl-on-opaque2.rs     | 28 +++++++++++++++++
 .../min_specialization/impl-on-opaque2.stderr | 12 +++++++
 3 files changed, 71 insertions(+)
 create mode 100644 tests/ui/specialization/min_specialization/impl-on-opaque.rs
 create mode 100644 tests/ui/specialization/min_specialization/impl-on-opaque2.rs
 create mode 100644 tests/ui/specialization/min_specialization/impl-on-opaque2.stderr

diff --git a/tests/ui/specialization/min_specialization/impl-on-opaque.rs b/tests/ui/specialization/min_specialization/impl-on-opaque.rs
new file mode 100644
index 00000000000..7531dcaccf2
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl-on-opaque.rs
@@ -0,0 +1,31 @@
+// Test that specializing on opaque types is allowed
+
+//@ check-pass
+
+#![feature(min_specialization, type_alias_impl_trait)]
+
+trait SpecTrait<U> {
+    fn f();
+}
+
+impl<U> SpecTrait<U> for () {
+    default fn f() {}
+}
+
+type Opaque = impl Tuple;
+
+trait Tuple {}
+
+impl Tuple for () {}
+
+impl SpecTrait<Opaque> for () {
+    fn f() {}
+}
+
+impl SpecTrait<u32> for () {
+    fn f() {}
+}
+
+fn foo() -> Opaque {}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl-on-opaque2.rs b/tests/ui/specialization/min_specialization/impl-on-opaque2.rs
new file mode 100644
index 00000000000..0cd8be84ed3
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl-on-opaque2.rs
@@ -0,0 +1,28 @@
+// Test that specializing on opaque types is allowed
+
+#![feature(min_specialization, type_alias_impl_trait)]
+
+trait SpecTrait<U, V> {
+    fn f();
+}
+
+impl<U> SpecTrait<U, ()> for () {
+    default fn f() {}
+}
+
+type Opaque = impl Tuple;
+
+trait Tuple {}
+
+impl Tuple for () {}
+
+// FIXME: this passes if we use `<(), ()>` here instead of `<(), Opaque>`,
+// even though there can't be more overlap from the opaque version
+impl SpecTrait<(), Opaque> for () {
+    //~^ ERROR: conflicting implementations
+    fn f() {}
+}
+
+fn foo() -> Opaque {}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl-on-opaque2.stderr b/tests/ui/specialization/min_specialization/impl-on-opaque2.stderr
new file mode 100644
index 00000000000..3c0bc8f8f83
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl-on-opaque2.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `SpecTrait<(), ()>` for type `()`
+  --> $DIR/impl-on-opaque2.rs:21:1
+   |
+LL | impl<U> SpecTrait<U, ()> for () {
+   | ------------------------------- first implementation here
+...
+LL | impl SpecTrait<(), Opaque> for () {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.