From 9871e160eae4376dea2b9fa3aa1ccca3607fc1c3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 May 2025 21:13:58 +0000 Subject: [PATCH] Normalize possibly unnormalized type in relate_type_and_user_type --- compiler/rustc_borrowck/src/type_check/mod.rs | 3 ++ .../normalizing-user-annotation.rs | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/ui/nll/user-annotations/normalizing-user-annotation.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4d57e7aac584..3c95ebf9ffab 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -482,6 +482,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } trace!(?curr_projected_ty); + // Need to renormalize `a` as typecheck may have failed to normalize + // higher-ranked aliases if normalization was ambiguous due to inference. + let a = self.normalize(a, locations); let ty = self.normalize(curr_projected_ty.ty, locations); self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?; diff --git a/tests/ui/nll/user-annotations/normalizing-user-annotation.rs b/tests/ui/nll/user-annotations/normalizing-user-annotation.rs new file mode 100644 index 000000000000..fa8b3bfd577d --- /dev/null +++ b/tests/ui/nll/user-annotations/normalizing-user-annotation.rs @@ -0,0 +1,31 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . + +// See description in there; this has to do with fundamental limitations +// to the old trait solver surrounding higher-ranked aliases with infer +// vars. This always worked in the new trait solver, but I added a revision +// just for good measure. + +trait Foo<'a> { + type Assoc; +} + +impl Foo<'_> for i32 { + type Assoc = u32; +} + +impl Foo<'_> for u32 { + type Assoc = u32; +} + +fn foo<'b: 'b, T: for<'a> Foo<'a>, F: for<'a> Fn(>::Assoc)>(_: F) -> (T, F) { + todo!() +} + +fn main() { + let (x, c): (i32, _) = foo::<'static, _, _>(|_| {}); +}