about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs1
-rw-r--r--tests/ui/associated-type-bounds/dedup-normalized-1.rs24
-rw-r--r--tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs27
-rw-r--r--tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr20
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.stderr27
-rw-r--r--tests/ui/closures/multiple-fn-bounds.stderr2
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.rs2
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.stderr14
-rw-r--r--tests/ui/generic-associated-types/bugs/issue-88382.stderr29
-rw-r--r--tests/ui/generic-associated-types/issue-93340-1.next.stderr53
-rw-r--r--tests/ui/generic-associated-types/issue-93340-1.old.stderr20
-rw-r--r--tests/ui/generic-associated-types/issue-93340-1.rs22
-rw-r--r--tests/ui/generic-associated-types/issue-93340-2.rs (renamed from tests/ui/generic-associated-types/issue-93340.rs)4
-rw-r--r--tests/ui/higher-ranked/higher-ranked-lifetime-error.rs2
-rw-r--r--tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr9
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.rs8
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.stderr14
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs8
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr75
-rw-r--r--tests/ui/implied-bounds/gluon_salsa.rs13
-rw-r--r--tests/ui/lifetimes/issue-105675.rs12
-rw-r--r--tests/ui/lifetimes/issue-105675.stderr89
-rw-r--r--tests/ui/lifetimes/issue-79187-2.rs2
-rw-r--r--tests/ui/lifetimes/issue-79187-2.stderr22
-rw-r--r--tests/ui/lifetimes/issue-79187.rs4
-rw-r--r--tests/ui/lifetimes/issue-79187.stderr24
-rw-r--r--tests/ui/lifetimes/lifetime-errors/issue_74400.rs2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/issue_74400.stderr16
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr2
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch.rs2
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch.stderr19
-rw-r--r--tests/ui/mismatched_types/closure-mismatch.rs4
-rw-r--r--tests/ui/mismatched_types/closure-mismatch.stderr45
-rw-r--r--tests/ui/mismatched_types/fn-variance-1.stderr4
-rw-r--r--tests/ui/mismatched_types/issue-36053-2.stderr2
-rw-r--r--tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr2
-rw-r--r--tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr4
-rw-r--r--tests/ui/mismatched_types/suggest-option-asderef.stderr8
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.rs4
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.stderr47
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs4
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr18
-rw-r--r--tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr2
-rw-r--r--tests/ui/typeck/mismatched-map-under-self.stderr2
49 files changed, 389 insertions, 395 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index aea58653351..a04bd636622 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -618,6 +618,7 @@ pub enum SelectionError<'tcx> {
     OpaqueTypeAutoTraitLeakageUnknown(DefId),
 }
 
+// FIXME(@lcnr): The `Binder` here should be unnecessary. Just use `TraitRef` instead.
 #[derive(Clone, Debug, TypeVisitable)]
 pub struct SignatureMismatchData<'tcx> {
     pub found_trait_ref: ty::PolyTraitRef<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index d18acb8c864..b85a05c774f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -3409,6 +3409,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err)
     }
 
+    // FIXME(@lcnr): This function could be changed to trait `TraitRef` directly
+    // instead of using a `Binder`.
     fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 89654ed61ae..49091e53be7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -165,7 +165,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
             let placeholder_trait_predicate =
                 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
-            debug!(?placeholder_trait_predicate);
 
             // The bounds returned by `item_bounds` may contain duplicates after
             // normalization, so try to deduplicate when possible to avoid
@@ -184,8 +183,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     selcx.infcx.probe(|_| {
                         match selcx.match_normalize_trait_ref(
                             obligation,
-                            bound.to_poly_trait_ref(),
                             placeholder_trait_predicate.trait_ref,
+                            bound.to_poly_trait_ref(),
                         ) {
                             Ok(None) => {
                                 candidates.vec.push(ProjectionCandidate(idx));
@@ -881,8 +880,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         self.infcx.probe(|_| {
                             self.match_normalize_trait_ref(
                                 obligation,
-                                upcast_trait_ref,
                                 placeholder_trait_predicate.trait_ref,
+                                upcast_trait_ref,
                             )
                             .is_ok()
                         })
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 70f6b240ab7..51fc223a5d1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -9,7 +9,7 @@
 use rustc_ast::Mutability;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
+use rustc_infer::infer::HigherRankedType;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
 use rustc_middle::ty::{
@@ -161,8 +161,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let placeholder_trait_predicate =
             self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
-        let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
-
         let candidate_predicate = self
             .for_each_item_bound(
                 placeholder_self_ty,
@@ -182,6 +180,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .expect("projection candidate is not a trait predicate")
             .map_bound(|t| t.trait_ref);
 
+        let candidate = self.infcx.instantiate_binder_with_fresh_vars(
+            obligation.cause.span,
+            HigherRankedType,
+            candidate,
+        );
         let mut obligations = Vec::new();
         let candidate = normalize_with_depth_to(
             self,
@@ -195,7 +198,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligations.extend(
             self.infcx
                 .at(&obligation.cause, obligation.param_env)
-                .sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
+                .eq(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
                 .map(|InferOk { obligations, .. }| obligations)
                 .map_err(|_| Unimplemented)?,
         );
@@ -499,7 +502,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
         let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
-        let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
         let ty::Dynamic(data, ..) = *self_ty.kind() else {
             span_bug!(obligation.cause.span, "object candidate with non-object");
         };
@@ -520,19 +522,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let unnormalized_upcast_trait_ref =
             supertraits.nth(index).expect("supertraits iterator no longer has as many elements");
 
+        let upcast_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
+            obligation.cause.span,
+            HigherRankedType,
+            unnormalized_upcast_trait_ref,
+        );
         let upcast_trait_ref = normalize_with_depth_to(
             self,
             obligation.param_env,
             obligation.cause.clone(),
             obligation.recursion_depth + 1,
-            unnormalized_upcast_trait_ref,
+            upcast_trait_ref,
             &mut nested,
         );
 
         nested.extend(
             self.infcx
                 .at(&obligation.cause, obligation.param_env)
-                .sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
+                .eq(DefineOpaqueTypes::No, trait_predicate.trait_ref, upcast_trait_ref)
                 .map(|InferOk { obligations, .. }| obligations)
                 .map_err(|_| Unimplemented)?,
         );
@@ -1021,7 +1028,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PolyTraitObligation<'tcx>,
         self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
+        let obligation_trait_ref =
+            self.infcx.enter_forall_and_leak_universe(obligation.predicate.to_poly_trait_ref());
+        let self_ty_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
+            obligation.cause.span,
+            HigherRankedType,
+            self_ty_trait_ref,
+        );
         // Normalize the obligation and expected trait refs together, because why not
         let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } =
             ensure_sufficient_stack(|| {
@@ -1037,15 +1050,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
         self.infcx
             .at(&obligation.cause, obligation.param_env)
-            .sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
+            .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
             .map(|InferOk { mut obligations, .. }| {
                 obligations.extend(nested);
                 obligations
             })
             .map_err(|terr| {
                 SignatureMismatch(Box::new(SignatureMismatchData {
-                    expected_trait_ref: obligation_trait_ref,
-                    found_trait_ref: expected_trait_ref,
+                    expected_trait_ref: ty::Binder::dummy(obligation_trait_ref),
+                    found_trait_ref: ty::Binder::dummy(expected_trait_ref),
                     terr,
                 }))
             })
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index a6bd1ba9c3f..be748de1b17 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -33,6 +33,7 @@ use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::BoundRegionConversionTime;
+use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::TraitObligation;
 use rustc_middle::dep_graph::dep_kinds;
@@ -1651,15 +1652,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn match_normalize_trait_ref(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
-        trait_bound: ty::PolyTraitRef<'tcx>,
         placeholder_trait_ref: ty::TraitRef<'tcx>,
-    ) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
+        trait_bound: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Option<ty::TraitRef<'tcx>>, ()> {
         debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
         if placeholder_trait_ref.def_id != trait_bound.def_id() {
             // Avoid unnecessary normalization
             return Err(());
         }
 
+        let trait_bound = self.infcx.instantiate_binder_with_fresh_vars(
+            obligation.cause.span,
+            HigherRankedType,
+            trait_bound,
+        );
         let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {
             normalize_with_depth(
                 self,
@@ -1671,7 +1677,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         });
         self.infcx
             .at(&obligation.cause, obligation.param_env)
-            .sup(DefineOpaqueTypes::No, ty::Binder::dummy(placeholder_trait_ref), trait_bound)
+            .eq(DefineOpaqueTypes::No, placeholder_trait_ref, trait_bound)
             .map(|InferOk { obligations: _, value: () }| {
                 // This method is called within a probe, so we can't have
                 // inference variables and placeholders escape.
@@ -1683,7 +1689,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             })
             .map_err(|_| ())
     }
-
     fn where_clause_may_apply<'o>(
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
@@ -1733,7 +1738,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let is_match = self
             .infcx
             .at(&obligation.cause, obligation.param_env)
-            .sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
+            .eq(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
             .is_ok_and(|InferOk { obligations, value: () }| {
                 self.evaluate_predicates_recursively(
                     TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
@@ -2533,7 +2538,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     nested.extend(
                         self.infcx
                             .at(&obligation.cause, obligation.param_env)
-                            .sup(
+                            .eq(
                                 DefineOpaqueTypes::No,
                                 upcast_principal.map_bound(|trait_ref| {
                                     ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
@@ -2571,7 +2576,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     nested.extend(
                         self.infcx
                             .at(&obligation.cause, obligation.param_env)
-                            .sup(DefineOpaqueTypes::No, source_projection, target_projection)
+                            .eq(DefineOpaqueTypes::No, source_projection, target_projection)
                             .map_err(|_| SelectionError::Unimplemented)?
                             .into_obligations(),
                     );
@@ -2615,9 +2620,15 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         obligation: &PolyTraitObligation<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
+        let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
+            obligation.cause.span,
+            HigherRankedType,
+            poly_trait_ref,
+        );
         self.infcx
             .at(&obligation.cause, obligation.param_env)
-            .sup(DefineOpaqueTypes::No, obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
+            .eq(DefineOpaqueTypes::No, predicate.trait_ref, trait_ref)
             .map(|InferOk { obligations, .. }| obligations)
             .map_err(|_| ())
     }
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 3c0316fce17..46a68508753 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -320,6 +320,7 @@ fn vtable_entries<'tcx>(
 }
 
 /// Find slot base for trait methods within vtable entries of another trait
+// FIXME(@lcnr): This isn't a query, so why does it take a tuple as its argument.
 pub(super) fn vtable_trait_first_method_offset<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: (
diff --git a/tests/ui/associated-type-bounds/dedup-normalized-1.rs b/tests/ui/associated-type-bounds/dedup-normalized-1.rs
new file mode 100644
index 00000000000..5329018e79f
--- /dev/null
+++ b/tests/ui/associated-type-bounds/dedup-normalized-1.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+// We try to prove `T::Rigid: Into<?0>` and have 2 candidates from where-clauses:
+//
+// - `Into<String>`
+// - `Into<<T::Rigid as Elaborate>::Assoc>`
+//
+// This causes ambiguity unless we normalize the alias in the second candidate
+// to detect that they actually result in the same constraints.
+trait Trait {
+    type Rigid: Elaborate<Assoc = String> + Into<String>;
+}
+
+trait Elaborate: Into<Self::Assoc> {
+    type Assoc;
+}
+
+fn impls<T: Into<U>, U>(_: T) {}
+
+fn test<P: Trait>(rigid: P::Rigid) {
+    impls(rigid);
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs
new file mode 100644
index 00000000000..9224d47d30f
--- /dev/null
+++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs
@@ -0,0 +1,27 @@
+// We try to prove `for<'b> T::Rigid: Bound<'b, ?0>` and have 2 candidates from where-clauses:
+//
+// - `for<'a> Bound<'a, String>`
+// - `for<'a> Bound<'a, <T::Rigid as Elaborate>::Assoc>`
+//
+// This causes ambiguity unless we normalize the alias in the second candidate
+// to detect that they actually result in the same constraints. We currently
+// fail to detect that the constraints from these bounds are equal and error
+// with ambiguity.
+trait Bound<'a, U> {}
+
+trait Trait {
+    type Rigid: Elaborate<Assoc = String> + for<'a> Bound<'a, String>;
+}
+
+trait Elaborate: for<'a> Bound<'a, Self::Assoc> {
+    type Assoc;
+}
+
+fn impls<T: for<'b> Bound<'b, U>, U>(_: T) {}
+
+fn test<P: Trait>(rigid: P::Rigid) {
+    impls(rigid);
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr
new file mode 100644
index 00000000000..372d379de5a
--- /dev/null
+++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr
@@ -0,0 +1,20 @@
+error[E0283]: type annotations needed
+  --> $DIR/dedup-normalized-2-higher-ranked.rs:23:5
+   |
+LL |     impls(rigid);
+   |     ^^^^^ cannot infer type of the type parameter `U` declared on the function `impls`
+   |
+   = note: cannot satisfy `for<'b> <P as Trait>::Rigid: Bound<'b, _>`
+note: required by a bound in `impls`
+  --> $DIR/dedup-normalized-2-higher-ranked.rs:20:13
+   |
+LL | fn impls<T: for<'b> Bound<'b, U>, U>(_: T) {}
+   |             ^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls`
+help: consider specifying the generic arguments
+   |
+LL |     impls::<<P as Trait>::Rigid, U>(rigid);
+   |          ++++++++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
index feae2698e8f..23ede089b5a 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
@@ -7,7 +7,7 @@ LL | #![feature(return_type_notation)]
    = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0308]: mismatched types
+error: implementation of `Send` is not general enough
   --> $DIR/issue-110963-early.rs:14:5
    |
 LL | /     spawn(async move {
@@ -16,17 +16,12 @@ LL | |         if !hc.check().await {
 LL | |             log_health_check_failure().await;
 LL | |         }
 LL | |     });
-   | |______^ one type is more general than the other
+   | |______^ implementation of `Send` is not general enough
    |
-   = note: expected trait `Send`
-              found trait `for<'a> Send`
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-110963-early.rs:34:17
-   |
-LL |     F: Future + Send + 'static,
-   |                 ^^^^
+   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>() }`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>() }`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `Send` is not general enough
   --> $DIR/issue-110963-early.rs:14:5
    |
 LL | /     spawn(async move {
@@ -35,17 +30,11 @@ LL | |         if !hc.check().await {
 LL | |             log_health_check_failure().await;
 LL | |         }
 LL | |     });
-   | |______^ one type is more general than the other
-   |
-   = note: expected trait `Send`
-              found trait `for<'a> Send`
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-110963-early.rs:34:17
+   | |______^ implementation of `Send` is not general enough
    |
-LL |     F: Future + Send + 'static,
-   |                 ^^^^
+   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>() }`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>() }`, for some specific lifetime `'2`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr
index 9a49fc99ac3..861b39b4d07 100644
--- a/tests/ui/closures/multiple-fn-bounds.stderr
+++ b/tests/ui/closures/multiple-fn-bounds.stderr
@@ -8,7 +8,7 @@ LL |     foo(move |x| v);
    |     expected due to this
    |
    = note: expected closure signature `fn(_) -> _`
-              found closure signature `for<'a> fn(&'a _) -> _`
+              found closure signature `fn(&_) -> _`
 note: closure inferred to have a different signature due to this bound
   --> $DIR/multiple-fn-bounds.rs:1:11
    |
diff --git a/tests/ui/coroutine/resume-arg-late-bound.rs b/tests/ui/coroutine/resume-arg-late-bound.rs
index dd6d318afbc..3c2ab41047e 100644
--- a/tests/ui/coroutine/resume-arg-late-bound.rs
+++ b/tests/ui/coroutine/resume-arg-late-bound.rs
@@ -13,5 +13,5 @@ fn main() {
         *arg = true;
     };
     test(gen);
-    //~^ ERROR mismatched types
+    //~^ ERROR implementation of `Coroutine` is not general enough
 }
diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr
index a97cc6190fd..4a4ee08c529 100644
--- a/tests/ui/coroutine/resume-arg-late-bound.stderr
+++ b/tests/ui/coroutine/resume-arg-late-bound.stderr
@@ -1,17 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `Coroutine` is not general enough
   --> $DIR/resume-arg-late-bound.rs:15:5
    |
 LL |     test(gen);
-   |     ^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^ implementation of `Coroutine` is not general enough
    |
-   = note: expected trait `for<'a> Coroutine<&'a mut bool>`
-              found trait `Coroutine<&mut bool>`
-note: the lifetime requirement is introduced here
-  --> $DIR/resume-arg-late-bound.rs:8:17
-   |
-LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {}
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:15: 11:31}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr
index 9b061528e3b..0f5e394ab61 100644
--- a/tests/ui/generic-associated-types/bugs/issue-88382.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr
@@ -1,26 +1,21 @@
-error[E0631]: type mismatch in function arguments
+error[E0283]: type annotations needed
   --> $DIR/issue-88382.rs:26:40
    |
 LL |     do_something(SomeImplementation(), test);
-   |     ------------                       ^^^^ expected due to this
-   |     |
-   |     required by a bound introduced by this call
-...
-LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
-   | ------------------------------------------------- found signature defined here
+   |                                        ^^^^ cannot infer type of the type parameter `I` declared on the function `test`
    |
-   = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty<usize>) -> _`
-              found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _`
-note: required by a bound in `do_something`
-  --> $DIR/issue-88382.rs:20:48
+   = note: cannot satisfy `_: Iterable`
+   = help: the trait `Iterable` is implemented for `SomeImplementation`
+note: required by a bound in `test`
+  --> $DIR/issue-88382.rs:29:16
    |
-LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
-   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`
-help: consider wrapping the function in a closure
+LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
+   |                ^^^^^^^^ required by this bound in `test`
+help: consider specifying the generic argument
    |
-LL |     do_something(SomeImplementation(), |arg0: &mut std::iter::Empty<usize>| test(/* &mut <_ as Iterable>::Iterator<'_> */));
-   |                                        ++++++++++++++++++++++++++++++++++++     ++++++++++++++++++++++++++++++++++++++++++
+LL |     do_something(SomeImplementation(), test::<I>);
+   |                                            +++++
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0631`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/generic-associated-types/issue-93340-1.next.stderr b/tests/ui/generic-associated-types/issue-93340-1.next.stderr
new file mode 100644
index 00000000000..0a056c9857a
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-93340-1.next.stderr
@@ -0,0 +1,53 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-93340-1.rs:16:5
+   |
+LL |     cmp_eq
+   |     ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
+   |
+   = note: cannot satisfy `_: Scalar`
+note: required by a bound in `cmp_eq`
+  --> $DIR/issue-93340-1.rs:9:22
+   |
+LL | fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O {
+   |                      ^^^^^^ required by this bound in `cmp_eq`
+help: consider specifying the generic arguments
+   |
+LL |     cmp_eq::<A, B, O>
+   |           +++++++++++
+
+error[E0275]: overflow evaluating the requirement `impl for<'a, 'b> Fn(<A as Scalar>::RefType<'a>, <B as Scalar>::RefType<'b>) -> O == for<'a, 'b> fn(..., ...) -> ... {cmp_eq::<..., ..., ...>}`
+  --> $DIR/issue-93340-1.rs:16:5
+   |
+LL |     cmp_eq
+   |     ^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_93340_1`)
+
+error[E0275]: overflow evaluating the requirement `impl for<'a, 'b> Fn(<A as Scalar>::RefType<'a>, <B as Scalar>::RefType<'b>) -> O == for<'a, 'b> fn(..., ...) -> ... {cmp_eq::<..., ..., ...>}`
+  --> $DIR/issue-93340-1.rs:16:5
+   |
+LL |     cmp_eq
+   |     ^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_93340_1`)
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0275]: overflow evaluating the requirement `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> _ {cmp_eq::<O, ..., ...>} <: ...`
+  --> $DIR/issue-93340-1.rs:14:51
+   |
+LL |   ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
+   |  ___________________________________________________^
+LL | |
+LL | |     cmp_eq
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_93340_1`)
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0275, E0283.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/tests/ui/generic-associated-types/issue-93340-1.old.stderr b/tests/ui/generic-associated-types/issue-93340-1.old.stderr
new file mode 100644
index 00000000000..8b6ab16bb0a
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-93340-1.old.stderr
@@ -0,0 +1,20 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-93340-1.rs:16:5
+   |
+LL |     cmp_eq
+   |     ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
+   |
+   = note: cannot satisfy `_: Scalar`
+note: required by a bound in `cmp_eq`
+  --> $DIR/issue-93340-1.rs:9:22
+   |
+LL | fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O {
+   |                      ^^^^^^ required by this bound in `cmp_eq`
+help: consider specifying the generic arguments
+   |
+LL |     cmp_eq::<A, B, O>
+   |           +++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/generic-associated-types/issue-93340-1.rs b/tests/ui/generic-associated-types/issue-93340-1.rs
new file mode 100644
index 00000000000..4d8ea9d8d48
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-93340-1.rs
@@ -0,0 +1,22 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+pub trait Scalar: 'static {
+    type RefType<'a>: ScalarRef<'a>;
+}
+
+pub trait ScalarRef<'a>: 'a {}
+
+fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O {
+    todo!()
+}
+
+fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
+) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
+    //[next]~^ ERROR overflow evaluating the requirement
+    cmp_eq
+    //~^ ERROR type annotations needed
+    //[next]~| ERROR overflow evaluating the requirement
+    //[next]~| ERROR overflow evaluating the requirement
+}
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/issue-93340.rs b/tests/ui/generic-associated-types/issue-93340-2.rs
index 783f8c06ebf..b55ca845cd3 100644
--- a/tests/ui/generic-associated-types/issue-93340.rs
+++ b/tests/ui/generic-associated-types/issue-93340-2.rs
@@ -1,3 +1,5 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
 //@ check-pass
 
 pub trait Scalar: 'static {
@@ -12,7 +14,7 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT
 
 fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
 ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
-    cmp_eq
+    cmp_eq::<A, B, O>
 }
 
 fn main() {}
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs b/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs
index aee5db83669..f89a37c8512 100644
--- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs
@@ -10,5 +10,5 @@ fn id(x: &String) -> &String {
 
 fn main() {
     assert_all::<_, &String>(id);
-    //~^ mismatched types
+    //~^ ERROR implementation of `FnMut` is not general enough
 }
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
index c25e731d962..d7add865aa0 100644
--- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
@@ -1,12 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnMut` is not general enough
   --> $DIR/higher-ranked-lifetime-error.rs:12:5
    |
 LL |     assert_all::<_, &String>(id);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
    |
-   = note: expected trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>`
-              found trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>`
+   = note: `for<'a> fn(&'a String) -> &'a String {id}` must implement `FnMut<(&String,)>`
+   = note: ...but it actually implements `FnMut<(&'0 String,)>`, for some specific lifetime `'0`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
index 387c78a802a..4e722dc0e80 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
@@ -6,17 +6,17 @@
 // an error, but the regression test is here to ensure
 // that it does not ICE. See discussion on #74889 for details.
 
-pub trait T {
+pub trait Trait {
     fn t<F: Fn()>(&self, _: F) {}
 }
 
 pub fn crash<V>(v: &V)
 where
-    for<'a> &'a V: T + 'static,
+    for<'a> &'a V: Trait + 'static,
 {
     v.t(|| {});
-    //~^ ERROR: higher-ranked lifetime error
-    //~| ERROR: higher-ranked lifetime error
+    //~^ ERROR: implementation of `Trait` is not general enough
+    //~| ERROR: implementation of `Trait` is not general enough
     //~| ERROR: higher-ranked lifetime error
 }
 
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
index 3053a299802..f8bed86ccf5 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
@@ -1,18 +1,20 @@
-error: higher-ranked lifetime error
+error: implementation of `Trait` is not general enough
   --> $DIR/issue-59311.rs:17:5
    |
 LL |     v.t(|| {});
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Trait` is not general enough
    |
-   = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
+   = note: `Trait` would have to be implemented for the type `&'a V`
+   = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0`
 
-error: higher-ranked lifetime error
+error: implementation of `Trait` is not general enough
   --> $DIR/issue-59311.rs:17:5
    |
 LL |     v.t(|| {});
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Trait` is not general enough
    |
-   = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
+   = note: `Trait` would have to be implemented for the type `&'a V`
+   = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: higher-ranked lifetime error
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
index 4bd3b96e475..a44ed9e5ef5 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
@@ -43,9 +43,9 @@ fn main() {
     }
 
     foo(bar, "string", |s| s.len() == 5);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
     foo(baz, "string", |s| s.0.len() == 5);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
index 1cf364aa9f6..b2bb417a8f0 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
@@ -1,79 +1,40 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-71955.rs:45:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a &'b str)`
-              found trait `for<'a> FnOnce(&'a &str)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-71955.rs:45:24
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |                        ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-71955.rs:25:9
-   |
-LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-71955.rs:45:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a &'b str)`
-              found trait `for<'a> FnOnce(&'a &str)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-71955.rs:45:24
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |                        ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-71955.rs:25:44
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
-   |                                            ^^^^
+   = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-71955.rs:48:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a Wrapper<'b>)`
-              found trait `for<'a> FnOnce(&'a Wrapper<'_>)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-71955.rs:48:24
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |                        ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-71955.rs:25:9
-   |
-LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-71955.rs:48:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a Wrapper<'b>)`
-              found trait `for<'a> FnOnce(&'a Wrapper<'_>)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-71955.rs:48:24
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |                        ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-71955.rs:25:44
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
-   |                                            ^^^^
+   = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/implied-bounds/gluon_salsa.rs b/tests/ui/implied-bounds/gluon_salsa.rs
index 368fb197909..cc6352c4a32 100644
--- a/tests/ui/implied-bounds/gluon_salsa.rs
+++ b/tests/ui/implied-bounds/gluon_salsa.rs
@@ -1,5 +1,6 @@
 //@ check-pass
-// Found in a crater run on #118553
+// Related to Bevy regression #115559, found in
+// a crater run on #118553.
 
 pub trait QueryBase {
     type Db;
@@ -17,11 +18,17 @@ pub struct QueryTable<'me, Q, DB> {
     _marker: Option<&'me ()>,
 }
 
-impl<'me, Q> QueryTable<'me, Q, <Q as QueryBase>::Db> // projection is important
-//   ^^^ removing 'me (and in QueryTable) gives a different error
+impl<'me, Q> QueryTable<'me, Q, <Q as QueryBase>::Db>
 where
     Q: for<'f> AsyncQueryFunction<'f>,
 {
+    // When borrowchechking this function we normalize `<Q as QueryBase>::Db` in the
+    // function signature to `<Self as QueryFunction<'?x>>::SendDb`, where `'?x` is an
+    // unconstrained region variable. We then addd `<Self as QueryFunction<'?x>>::SendDb: 'a`
+    // as an implied bound. We currently a structural equality to decide whether this bound
+    // should be used to prove the bound  `<Self as QueryFunction<'?x>>::SendDb: 'a`. For this
+    // to work we may have to structurally resolve regions as the actually used vars may
+    // otherwise be semantically equal but structurally different.
     pub fn get_async<'a>(&'a mut self) {
         panic!();
     }
diff --git a/tests/ui/lifetimes/issue-105675.rs b/tests/ui/lifetimes/issue-105675.rs
index 58d8be8b65f..2e2eaca0d33 100644
--- a/tests/ui/lifetimes/issue-105675.rs
+++ b/tests/ui/lifetimes/issue-105675.rs
@@ -3,12 +3,12 @@ fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
 fn main() {
     let f = | _ , y: &u32 , z | ();
     thing(f);
-    //~^ ERROR mismatched types
-    //~^^ ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~^^ ERROR implementation of `FnOnce` is not general enough
     let f = | x, y: _  , z: u32 | ();
     thing(f);
-    //~^ ERROR mismatched types
-    //~^^ ERROR mismatched types
-    //~^^^ ERROR implementation of `FnOnce` is not general enough
-    //~^^^^ ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
 }
diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr
index f1fa5a59860..4b3d0e8ac5e 100644
--- a/tests/ui/lifetimes/issue-105675.stderr
+++ b/tests/ui/lifetimes/issue-105675.stderr
@@ -1,91 +1,39 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:5:5
    |
 LL |     thing(f);
-   |     ^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)`
-              found trait `for<'a> FnOnce(&u32, &'a u32, u32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-105675.rs:4:13
-   |
-LL |     let f = | _ , y: &u32 , z | ();
-   |             ^^^^^^^^^^^^^^^^^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-105675.rs:1:18
-   |
-LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let f = |_: &_, y: &u32, z| ();
-   |             ~~~~~~~~~~~~~~~~~~~
+   = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:5:5
    |
 LL |     thing(f);
-   |     ^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)`
-              found trait `for<'a> FnOnce(&u32, &'a u32, u32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-105675.rs:4:13
-   |
-LL |     let f = | _ , y: &u32 , z | ();
-   |             ^^^^^^^^^^^^^^^^^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-105675.rs:1:18
+   |     ^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:9:5
    |
 LL |     thing(f);
-   |     ^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)`
-              found trait `FnOnce(&u32, &u32, u32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-105675.rs:8:13
-   |
-LL |     let f = | x, y: _  , z: u32 | ();
-   |             ^^^^^^^^^^^^^^^^^^^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-105675.rs:1:18
-   |
-LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let f = |x: &_, y: &_, z: u32| ();
-   |             ~~~~~~~~~~~~~~~~~~~~~~
+   = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:9:5
    |
 LL |     thing(f);
-   |     ^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)`
-              found trait `FnOnce(&u32, &u32, u32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-105675.rs:8:13
-   |
-LL |     let f = | x, y: _  , z: u32 | ();
-   |             ^^^^^^^^^^^^^^^^^^^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-105675.rs:1:18
-   |
-LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let f = |x: &_, y: &_, z: u32| ();
-   |             ~~~~~~~~~~~~~~~~~~~~~~
+   = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:9:5
@@ -95,6 +43,7 @@ LL |     thing(f);
    |
    = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-105675.rs:9:5
@@ -104,7 +53,7 @@ LL |     thing(f);
    |
    = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lifetimes/issue-79187-2.rs b/tests/ui/lifetimes/issue-79187-2.rs
index fff92c30b37..9d7f17e7f23 100644
--- a/tests/ui/lifetimes/issue-79187-2.rs
+++ b/tests/ui/lifetimes/issue-79187-2.rs
@@ -7,7 +7,7 @@ fn take_foo(_: impl Foo) {}
 fn main() {
     take_foo(|a| a);
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
+    //~| ERROR implementation of `Fn` is not general enough
     take_foo(|a: &i32| a);
     //~^ ERROR lifetime may not live long enough
     //~| ERROR mismatched types
diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr
index e8115bb6b06..78f6ce882df 100644
--- a/tests/ui/lifetimes/issue-79187-2.stderr
+++ b/tests/ui/lifetimes/issue-79187-2.stderr
@@ -25,28 +25,14 @@ LL |     take_foo(|a| a);
    = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/issue-79187-2.rs:8:5
    |
 LL |     take_foo(|a| a);
-   |     ^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> Fn(&'a i32)`
-              found trait `Fn(&i32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-79187-2.rs:8:14
-   |
-LL |     take_foo(|a| a);
-   |              ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-79187-2.rs:5:21
-   |
-LL | fn take_foo(_: impl Foo) {}
-   |                     ^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
    |
-LL |     take_foo(|a: &_| a);
-   |              ~~~~~~~
+   = note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2`
 
 error[E0308]: mismatched types
   --> $DIR/issue-79187-2.rs:11:5
diff --git a/tests/ui/lifetimes/issue-79187.rs b/tests/ui/lifetimes/issue-79187.rs
index 8e13045623b..a8829bd4e49 100644
--- a/tests/ui/lifetimes/issue-79187.rs
+++ b/tests/ui/lifetimes/issue-79187.rs
@@ -3,6 +3,6 @@ fn thing(x: impl FnOnce(&u32)) {}
 fn main() {
     let f = |_| ();
     thing(f);
-    //~^ ERROR mismatched types
-    //~^^ ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
 }
diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr
index 14bdfe75c08..8adde8d6dfb 100644
--- a/tests/ui/lifetimes/issue-79187.stderr
+++ b/tests/ui/lifetimes/issue-79187.stderr
@@ -1,25 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-79187.rs:5:5
    |
 LL |     thing(f);
-   |     ^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> FnOnce(&'a u32)`
-              found trait `FnOnce(&u32)`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-79187.rs:4:13
-   |
-LL |     let f = |_| ();
-   |             ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/issue-79187.rs:1:18
-   |
-LL | fn thing(x: impl FnOnce(&u32)) {}
-   |                  ^^^^^^^^^^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let f = |_: &_| ();
-   |             ~~~~~~~
+   = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-79187.rs:5:5
@@ -29,7 +15,7 @@ LL |     thing(f);
    |
    = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
index f17e0a678c9..b02e38bec3b 100644
--- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
+++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
@@ -13,6 +13,6 @@ fn g<T>(data: &[T]) {
     //~^ ERROR the parameter type
     //~| ERROR the parameter type
     //~| ERROR the parameter type
-    //~| ERROR mismatched types
     //~| ERROR implementation of `FnOnce` is not general
+    //~| ERROR implementation of `Fn` is not general enough
 }
diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
index beb838d2ff8..4dada6ff014 100644
--- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
@@ -42,19 +42,14 @@ help: consider adding an explicit lifetime bound
 LL | fn g<T: 'static>(data: &[T]) {
    |       +++++++++
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/issue_74400.rs:12:5
    |
 LL |     f(data, identity)
-   |     ^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
    |
-   = note: expected trait `for<'a> Fn(&'a T)`
-              found trait `Fn(&T)`
-note: the lifetime requirement is introduced here
-  --> $DIR/issue_74400.rs:8:34
-   |
-LL | fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
-   |                                  ^^^^^^^^^^^
+   = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/issue_74400.rs:12:5
@@ -67,5 +62,4 @@ LL |     f(data, identity)
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0308, E0310.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
index 452cba6b4de..e52e095e9f7 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
@@ -24,7 +24,7 @@ LL |     let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
    |                        expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
-              found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _`
+              found closure signature `fn(&&&i32) -> _`
 note: required by a bound in `find`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 help: consider adjusting the signature so it does not borrow its argument
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs
index e73a33dfded..55a4a0b5707 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs
@@ -8,7 +8,7 @@ fn main() {
 fn baz<F: Fn(*mut &u32)>(_: F) {}
 fn _test<'a>(f: fn(*mut &'a u32)) {
     baz(f);
-    //~^ ERROR: mismatched types
+    //~^ ERROR: implementation of `FnOnce` is not general enough
     //~| ERROR: borrowed data escapes
     //~| ERROR: not general enough
 }
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
index e63d3f6a075..abc5d150a3f 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -24,7 +24,7 @@ LL |     a.iter().map(|_: &(u16, u16)| 45);
    |              expected due to this
    |
    = note: expected closure signature `fn(&(u32, u32)) -> _`
-              found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
+              found closure signature `fn(&(u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
@@ -63,19 +63,14 @@ note: due to current limitations in the borrow checker, this implies a `'static`
 LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
    |           ^^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^^^^ one type is more general than the other
+   |     ^^^^^^ implementation of `Fn` is not general enough
    |
-   = note: expected trait `for<'a> Fn(*mut &'a u32)`
-              found trait `Fn(*mut &u32)`
-note: the lifetime requirement is introduced here
-  --> $DIR/closure-arg-type-mismatch.rs:8:11
-   |
-LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
-   |           ^^^^^^^^^^^^^
+   = note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/closure-arg-type-mismatch.rs:10:5
@@ -88,5 +83,5 @@ LL |     baz(f);
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0308, E0521, E0631.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0521, E0631.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/tests/ui/mismatched_types/closure-mismatch.rs b/tests/ui/mismatched_types/closure-mismatch.rs
index 4eb33497c39..efaed4dc1b9 100644
--- a/tests/ui/mismatched_types/closure-mismatch.rs
+++ b/tests/ui/mismatched_types/closure-mismatch.rs
@@ -7,8 +7,8 @@ fn baz<T: Foo>(_: T) {}
 fn main() {
     baz(|_| ());
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
+    //~| ERROR implementation of `Fn` is not general enough
     baz(|x| ());
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
+    //~| ERROR implementation of `Fn` is not general enough
 }
diff --git a/tests/ui/mismatched_types/closure-mismatch.stderr b/tests/ui/mismatched_types/closure-mismatch.stderr
index 74033c18573..802110c6511 100644
--- a/tests/ui/mismatched_types/closure-mismatch.stderr
+++ b/tests/ui/mismatched_types/closure-mismatch.stderr
@@ -7,28 +7,14 @@ LL |     baz(|_| ());
    = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/closure-mismatch.rs:8:5
    |
 LL |     baz(|_| ());
-   |     ^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^ implementation of `Fn` is not general enough
    |
-   = note: expected trait `for<'a> Fn(&'a ())`
-              found trait `Fn(&())`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/closure-mismatch.rs:8:9
-   |
-LL |     baz(|_| ());
-   |         ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/closure-mismatch.rs:5:11
-   |
-LL | fn baz<T: Foo>(_: T) {}
-   |           ^^^
-help: consider specifying the type of the closure parameters
-   |
-LL |     baz(|_: &_| ());
-   |         ~~~~~~~
+   = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/closure-mismatch.rs:11:5
@@ -39,29 +25,14 @@ LL |     baz(|x| ());
    = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/closure-mismatch.rs:11:5
    |
 LL |     baz(|x| ());
-   |     ^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> Fn(&'a ())`
-              found trait `Fn(&())`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/closure-mismatch.rs:11:9
-   |
-LL |     baz(|x| ());
-   |         ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/closure-mismatch.rs:5:11
-   |
-LL | fn baz<T: Foo>(_: T) {}
-   |           ^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^^^^ implementation of `Fn` is not general enough
    |
-LL |     baz(|x: &_| ());
-   |         ~~~~~~~
+   = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2`
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/mismatched_types/fn-variance-1.stderr b/tests/ui/mismatched_types/fn-variance-1.stderr
index fdb2e6f0097..ed450d8d81c 100644
--- a/tests/ui/mismatched_types/fn-variance-1.stderr
+++ b/tests/ui/mismatched_types/fn-variance-1.stderr
@@ -10,7 +10,7 @@ LL |     apply(&3, takes_mut);
    |     required by a bound introduced by this call
    |
    = note: expected function signature `fn(&{integer}) -> _`
-              found function signature `for<'a> fn(&'a mut isize) -> _`
+              found function signature `fn(&mut isize) -> _`
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
    |
@@ -33,7 +33,7 @@ LL |     apply(&mut 3, takes_imm);
    |     required by a bound introduced by this call
    |
    = note: expected function signature `fn(&mut {integer}) -> _`
-              found function signature `for<'a> fn(&'a isize) -> _`
+              found function signature `fn(&isize) -> _`
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
    |
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index 6d23319ca7e..ffaa276b62e 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -7,7 +7,7 @@ LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a &_) -> _`
-              found closure signature `for<'a> fn(&'a _) -> _`
+              found closure signature `fn(&_) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 help: consider adjusting the signature so it borrows its argument
diff --git a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr
index 0ed57466e9c..0b8943898f5 100644
--- a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr
+++ b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr
@@ -10,7 +10,7 @@ LL |     let _has_inference_vars: Option<i32> = Some(0).map(deref_int);
    |                                                    required by a bound introduced by this call
    |
    = note: expected function signature `fn({integer}) -> _`
-              found function signature `for<'a> fn(&'a i32) -> _`
+              found function signature `fn(&i32) -> _`
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
index 1ac057a5f38..99c9028ae1e 100644
--- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
+++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
@@ -10,7 +10,7 @@ LL |     let _ = produces_string().and_then(takes_str_but_too_many_refs);
    |                               required by a bound introduced by this call
    |
    = note: expected function signature `fn(String) -> _`
-              found function signature `for<'a, 'b> fn(&'a &'b str) -> _`
+              found function signature `fn(&&str) -> _`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
@@ -69,7 +69,7 @@ LL |     let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
    |                                    required by a bound introduced by this call
    |
    = note: expected function signature `fn(TypeWithoutDeref) -> _`
-              found function signature `for<'a, 'b> fn(&'a &'b str) -> _`
+              found function signature `fn(&&str) -> _`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
diff --git a/tests/ui/mismatched_types/suggest-option-asderef.stderr b/tests/ui/mismatched_types/suggest-option-asderef.stderr
index 1702a7f1dec..306c412e9d2 100644
--- a/tests/ui/mismatched_types/suggest-option-asderef.stderr
+++ b/tests/ui/mismatched_types/suggest-option-asderef.stderr
@@ -10,7 +10,7 @@ LL |     let _: Option<()> = produces_string().and_then(takes_str);
    |                                           required by a bound introduced by this call
    |
    = note: expected function signature `fn(String) -> _`
-              found function signature `for<'a> fn(&'a str) -> _`
+              found function signature `fn(&str) -> _`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
@@ -34,7 +34,7 @@ LL |     let _: Option<Option<()>> = produces_string().map(takes_str);
    |                                                   required by a bound introduced by this call
    |
    = note: expected function signature `fn(String) -> _`
-              found function signature `for<'a> fn(&'a str) -> _`
+              found function signature `fn(&str) -> _`
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
@@ -58,7 +58,7 @@ LL |     let _: Option<Option<()>> = produces_string().map(takes_str_mut);
    |                                                   required by a bound introduced by this call
    |
    = note: expected function signature `fn(String) -> _`
-              found function signature `for<'a> fn(&'a mut str) -> _`
+              found function signature `fn(&mut str) -> _`
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
@@ -82,7 +82,7 @@ LL |     let _ = produces_string().and_then(generic_ref);
    |                               required by a bound introduced by this call
    |
    = note: expected function signature `fn(String) -> _`
-              found function signature `for<'a> fn(&'a _) -> _`
+              found function signature `fn(&_) -> _`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.rs b/tests/ui/nll/missing-universe-cause-issue-114907.rs
index 9c69c6bdc36..a3eb5fceea9 100644
--- a/tests/ui/nll/missing-universe-cause-issue-114907.rs
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.rs
@@ -31,8 +31,8 @@ fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
 fn main() {
     let callback = |_| {};
     accept(callback);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR higher-ranked subtype error
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
index a616d29c4fe..26ad1efec05 100644
--- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
@@ -1,25 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/missing-universe-cause-issue-114907.rs:33:5
    |
 LL |     accept(callback);
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> FnOnce(&'a ())`
-              found trait `FnOnce(&())`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/missing-universe-cause-issue-114907.rs:32:20
-   |
-LL |     let callback = |_| {};
-   |                    ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/missing-universe-cause-issue-114907.rs:27:14
-   |
-LL | fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
-   |              ^^^^^^^^^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let callback = |_: &_| {};
-   |                    ~~~~~~~
+   = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/missing-universe-cause-issue-114907.rs:33:5
@@ -29,6 +15,7 @@ LL |     accept(callback);
    |
    = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/missing-universe-cause-issue-114907.rs:33:5
@@ -40,28 +27,15 @@ LL |     accept(callback);
    = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/missing-universe-cause-issue-114907.rs:33:5
    |
 LL |     accept(callback);
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> FnOnce(&'a ())`
-              found trait `FnOnce(&())`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/missing-universe-cause-issue-114907.rs:32:20
-   |
-LL |     let callback = |_| {};
-   |                    ^^^
-note: the lifetime requirement is introduced here
-  --> $DIR/missing-universe-cause-issue-114907.rs:20:21
-   |
-LL | struct Handshake<R: Role> {
-   |                     ^^^^
-help: consider specifying the type of the closure parameters
+   |     ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |     let callback = |_: &_| {};
-   |                    ~~~~~~~
+   = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: higher-ranked subtype error
   --> $DIR/missing-universe-cause-issue-114907.rs:33:21
@@ -79,4 +53,3 @@ LL |     accept(callback);
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
index c0e13a5f5f0..5d11941414f 100644
--- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
@@ -26,8 +26,8 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct {
     foo: &Foo { bools: &[false, true] },
     bar: &Bar { bools: &[true, true] },
     f: &id,
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `Fn` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
 };
diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
index 52c700c326e..5c98a9d4fb4 100644
--- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
@@ -1,21 +1,20 @@
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/rfc1623-2.rs:28:8
    |
 LL |     f: &id,
-   |        ^^^ one type is more general than the other
+   |        ^^^ implementation of `Fn` is not general enough
    |
-   = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)`
-              found trait `Fn(&Foo<'_>)`
+   = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `Fn<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
+error: implementation of `Fn` is not general enough
   --> $DIR/rfc1623-2.rs:28:8
    |
 LL |     f: &id,
-   |        ^^^ one type is more general than the other
+   |        ^^^ implementation of `Fn` is not general enough
    |
-   = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)`
-              found trait `Fn(&Foo<'_>)`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `Fn<(&'a Foo<'1>,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&Foo<'2>,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/rfc1623-2.rs:28:8
@@ -37,4 +36,3 @@ LL |     f: &id,
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr
index ee924522564..f0acf1dbb96 100644
--- a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr
+++ b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr
@@ -10,7 +10,7 @@ LL |     trader.set_closure(closure);
    |            required by a bound introduced by this call
    |
    = note: expected closure signature `for<'a, 'b> fn(&'a mut Trader<'b>) -> _`
-              found closure signature `for<'a> fn(Trader<'a>) -> _`
+              found closure signature `fn(Trader<'_>) -> _`
 note: required by a bound in `Trader::<'a>::set_closure`
   --> $DIR/late-bound-in-borrow-closure-sugg.rs:15:50
    |
diff --git a/tests/ui/typeck/mismatched-map-under-self.stderr b/tests/ui/typeck/mismatched-map-under-self.stderr
index 13678b4b827..322bf349f92 100644
--- a/tests/ui/typeck/mismatched-map-under-self.stderr
+++ b/tests/ui/typeck/mismatched-map-under-self.stderr
@@ -27,7 +27,7 @@ LL |         self.map(Insertable::values).unwrap_or_default()
    |              required by a bound introduced by this call
    |
    = note: expected function signature `fn(T) -> _`
-              found function signature `for<'a> fn(&'a _) -> _`
+              found function signature `fn(&_) -> _`
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: consider wrapping the function in a closure