From 02771849777ce072e5fc3af5a39fa2415124829b Mon Sep 17 00:00:00 2001 From: Oli Scherer 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 = impl Trait<&'static T, AssocTy = impl Nested>; ` // They can only be referenced as ` 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)> { + 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`.