From 02771849777ce072e5fc3af5a39fa2415124829b Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 14 Sep 2023 15:16:48 +0000
Subject: [PATCH] Paper over an accidental regression

---
 compiler/rustc_hir_analysis/src/check/check.rs     | 10 +++++++++-
 .../ui/impl-trait/lifetime-ambiguity-regression.rs | 13 +++++++++++++
 tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs |  2 +-
 .../type-alias-impl-trait/nested-tait-hrtb.stderr  | 14 +-------------
 4 files changed, 24 insertions(+), 15 deletions(-)
 create mode 100644 tests/ui/impl-trait/lifetime-ambiguity-regression.rs

diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index c0cf1ea34cf..9a57cc6dbab 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -461,7 +461,15 @@ fn check_opaque_meets_bounds<'tcx>(
     }
     match origin {
         // Checked when type checking the function containing them.
-        hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+        hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
+            // HACK: this should also fall through to the hidden type check below, but the original
+            // implementation had a bug where equivalent lifetimes are not identical. This caused us
+            // to reject existing stable code that is otherwise completely fine. The real fix is to
+            // compare the hidden types via our type equivalence/relation infra instead of doing an
+            // identity check.
+            let _ = infcx.take_opaque_types();
+            return Ok(());
+        }
         // Nested opaque types occur only in associated types:
         // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
         // They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
diff --git a/tests/ui/impl-trait/lifetime-ambiguity-regression.rs b/tests/ui/impl-trait/lifetime-ambiguity-regression.rs
new file mode 100644
index 00000000000..ce6ae3786e1
--- /dev/null
+++ b/tests/ui/impl-trait/lifetime-ambiguity-regression.rs
@@ -0,0 +1,13 @@
+//! This test shows a situation where through subtle compiler changes we can
+//! suddenly infer a different lifetime in the hidden type, and thus not meet
+//! the opaque type bounds anymore. In this case `'a` and `'b` are equal, so
+//! picking either is fine, but then we'll fail an identity check of the hidden
+//! type and the expected hidden type.
+
+// check-pass
+
+fn test<'a: 'b, 'b: 'a>() -> impl IntoIterator<Item = (&'a u8, impl Into<(&'b u8, &'a u8)>)> {
+    None::<(_, (_, _))>
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
index 4a9631a7208..ba705d6f85a 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
@@ -8,7 +8,7 @@ fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
 //~^ ERROR captures lifetime that does not appear in bounds
 
 type WithLt<'a> = impl Sized + 'a;
-//~^ ERROR concrete type differs from previous defining opaque type use
+
 fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
 //~^ ERROR expected generic lifetime parameter, found `'a`
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
index 9a783a6d92a..f208730552d 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
@@ -17,19 +17,7 @@ LL |
 LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
    |                                                            ^^
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/nested-tait-hrtb.rs:10:19
-   |
-LL | type WithLt<'a> = impl Sized + 'a;
-   |                   ^^^^^^^^^^^^^^^ expected `&'a str`, got `{type error}`
-   |
-note: previous use here
-  --> $DIR/nested-tait-hrtb.rs:12:17
-   |
-LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0700, E0792.
 For more information about an error, try `rustc --explain E0700`.