From d43683f2e905d34ab289882c16124deb5ed09edd Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 18 Jun 2023 22:10:07 +0000
Subject: [PATCH] Treat TAIT equation as always ambiguous in coherence

---
 compiler/rustc_infer/src/infer/combine.rs     | 11 +++----
 .../tests/ui/from_over_into_unfixable.rs      |  6 ----
 .../tests/ui/from_over_into_unfixable.stderr  | 33 ++++++++++++++-----
 ...coherence-treats-tait-ambig.current.stderr | 13 ++++++++
 .../coherence-treats-tait-ambig.next.stderr   | 13 ++++++++
 .../impl-trait/coherence-treats-tait-ambig.rs | 19 +++++++++++
 6 files changed, 74 insertions(+), 21 deletions(-)
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.rs

diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 152c56572b6..12cb86d7d72 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -124,13 +124,10 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             // During coherence, opaque types should be treated as *possibly*
-            // equal to each other, even if their generic params differ, as
-            // they could resolve to the same hidden type, even for different
-            // generic params.
-            (
-                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
-                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
-            ) if self.intercrate && a_def_id == b_def_id => {
+            // equal to any other type (except for possibly itself). This is an
+            // extremely heavy hammer, but can be relaxed in a fowards-compatible
+            // way later.
+            (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => {
                 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
                 Ok(a)
             }
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
index bd62c655216..3b280b7488a 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
@@ -32,10 +32,4 @@ impl Into<u8> for ContainsVal {
     }
 }
 
-type Opaque = impl Sized;
-struct IntoOpaque;
-impl Into<Opaque> for IntoOpaque {
-    fn into(self) -> Opaque {}
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
index bb966af4b0f..251f1d84e74 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -1,12 +1,29 @@
-error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/from_over_into_unfixable.rs:35:15
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:11:1
    |
-LL | type Opaque = impl Sized;
-   |               ^^^^^^^^^^
+LL | impl Into<InMacro> for String {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = help: replace the `Into` implementation with `From<std::string::String>`
+   = note: `-D clippy::from-over-into` implied by `-D warnings`
 
-error: aborting due to previous error
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:19:1
+   |
+LL | impl Into<WeirdUpperSelf> for &'static [u8] {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: replace the `Into` implementation with `From<&'static [u8]>`
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:28:1
+   |
+LL | impl Into<u8> for ContainsVal {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+   = help: replace the `Into` implementation with `From<ContainsVal>`
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
new file mode 100644
index 00000000000..61fed16294b
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+  --> $DIR/coherence-treats-tait-ambig.rs:10:1
+   |
+LL | impl Into<T> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> Into<U> for T
+             where U: From<T>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
new file mode 100644
index 00000000000..61fed16294b
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+  --> $DIR/coherence-treats-tait-ambig.rs:10:1
+   |
+LL | impl Into<T> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> Into<U> for T
+             where U: From<T>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
new file mode 100644
index 00000000000..156a7eb0e23
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
@@ -0,0 +1,19 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+#![feature(type_alias_impl_trait)]
+
+type T = impl Sized;
+
+struct Foo;
+
+impl Into<T> for Foo {
+//~^ ERROR conflicting implementations of trait `Into<T>` for type `Foo`
+    fn into(self) -> T {
+        Foo
+    }
+}
+
+fn main() {
+    let _: T = Foo.into();
+}