diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3fbe8e39d1e3f..926044bd6a803 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -60,6 +60,20 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 mod candidate_assembly;
 mod confirmation;
 
+/// Whether to consider the binder of higher ranked goals for the `leak_check` when
+/// evaluating higher-ranked goals. See #119820 for more info.
+///
+/// While this is a bit hacky, it is necessary to match the behavior of the new solver:
+/// We eagerly instantiate binders in the new solver, outside of candidate selection, so
+/// the leak check inside of candidates does not consider any bound vars from the higher
+/// ranked goal. However, we do exit the binder once we're completely finished with a goal,
+/// so the leak-check can be used in evaluate by causing nested higher-ranked goals to fail.
+#[derive(Debug, Copy, Clone)]
+enum LeakCheckHigherRankedGoal {
+    No,
+    Yes,
+}
+
 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
 pub enum IntercrateAmbiguityCause<'tcx> {
     DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },
@@ -384,7 +398,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let mut no_candidates_apply = true;
 
                     for c in candidate_set.vec.iter() {
-                        if self.evaluate_candidate(stack, c)?.may_apply() {
+                        if self
+                            .evaluate_candidate(stack, c, LeakCheckHigherRankedGoal::No)?
+                            .may_apply()
+                        {
                             no_candidates_apply = false;
                             break;
                         }
@@ -455,7 +472,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // is needed for specialization. Propagate overflow if it occurs.
         let mut candidates = candidates
             .into_iter()
-            .map(|c| match self.evaluate_candidate(stack, &c) {
+            .map(|c| match self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::No) {
                 Ok(eval) if eval.may_apply() => {
                     Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
                 }
@@ -545,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         debug_assert!(!self.infcx.next_trait_solver());
-        self.evaluation_probe(|this| {
+        self.evaluation_probe(|this, _outer_universe| {
             let goal =
                 this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
             let mut result = this.evaluate_predicate_recursively(
@@ -561,13 +578,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
+    /// Computes the evaluation result of `op`, discarding any constraints.
+    ///
+    /// This also runs for leak check to allow higher ranked region errors to impact
+    /// selection. By default it checks for leaks from all universes created inside of
+    /// `op`, but this can be overwritten if necessary.
     fn evaluation_probe(
         &mut self,
-        op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
+        op: impl FnOnce(&mut Self, &mut ty::UniverseIndex) -> Result<EvaluationResult, OverflowError>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
-            let outer_universe = self.infcx.universe();
-            let result = op(self)?;
+            let mut outer_universe = self.infcx.universe();
+            let result = op(self, &mut outer_universe)?;
 
             match self.infcx.leak_check(outer_universe, Some(snapshot)) {
                 Ok(()) => {}
@@ -586,9 +608,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
-    /// Evaluates the predicates in `predicates` recursively. Note that
-    /// this applies projections in the predicates, and therefore
+    /// Evaluates the predicates in `predicates` recursively. This may
+    /// guide inference. If this is not desired, run it inside of a
     /// is run within an inference probe.
+    /// `probe`.
     #[instrument(skip(self, stack), level = "debug")]
     fn evaluate_predicates_recursively<'o, I>(
         &mut self,
@@ -1194,7 +1217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         match self.candidate_from_obligation(stack) {
-            Ok(Some(c)) => self.evaluate_candidate(stack, &c),
+            Ok(Some(c)) => self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::Yes),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
             Err(..) => Ok(EvaluatedToErr),
@@ -1219,6 +1242,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
     /// obligations are met. Returns whether `candidate` remains viable after this further
     /// scrutiny.
+    ///
+    /// Depending on the value of [LeakCheckHigherRankedGoal], we may ignore the binder of the goal
+    /// when eagerly detecting higher ranked region errors via the `leak_check`. See that enum for
+    /// more info.
     #[instrument(
         level = "debug",
         skip(self, stack),
@@ -1229,10 +1256,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
         candidate: &SelectionCandidate<'tcx>,
+        leak_check_higher_ranked_goal: LeakCheckHigherRankedGoal,
     ) -> Result<EvaluationResult, OverflowError> {
-        let mut result = self.evaluation_probe(|this| {
-            let candidate = (*candidate).clone();
-            match this.confirm_candidate(stack.obligation, candidate) {
+        let mut result = self.evaluation_probe(|this, outer_universe| {
+            // We eagerly instantiate higher ranked goals to prevent universe errors
+            // from impacting candidate selection. This matches the behavior of the new
+            // solver. This slightly weakens type inference.
+            //
+            // In case there are no unresolved type or const variables this
+            // should still not be necessary to select a unique impl as any overlap
+            // relying on a universe error from higher ranked goals should have resulted
+            // in an overlap error in coherence.
+            let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate);
+            let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p));
+            match leak_check_higher_ranked_goal {
+                LeakCheckHigherRankedGoal::No => *outer_universe = self.infcx.universe(),
+                LeakCheckHigherRankedGoal::Yes => {}
+            }
+
+            match this.confirm_candidate(&obligation, candidate.clone()) {
                 Ok(selection) => {
                     debug!(?selection);
                     this.evaluate_predicates_recursively(
@@ -1657,8 +1699,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         stack: &TraitObligationStack<'o, 'tcx>,
         where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
-        self.evaluation_probe(|this| {
-            match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
+        self.evaluation_probe(|this, outer_universe| {
+            // Eagerly instantiate higher ranked goals.
+            //
+            // See the comment in `evaluate_candidate` to see why.
+            let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate);
+            let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p));
+            *outer_universe = self.infcx.universe();
+            match this.match_where_clause_trait_ref(&obligation, where_clause_trait_ref) {
                 Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
                 Err(()) => Ok(EvaluatedToErr),
             }
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index f6b1d45ee94ef..6b0573f5a3ff2 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -1129,7 +1129,6 @@
 "ui/generics/issue-98432.rs",
 "ui/higher-ranked/trait-bounds/issue-100689.rs",
 "ui/higher-ranked/trait-bounds/issue-102899.rs",
-"ui/higher-ranked/trait-bounds/issue-30786.rs",
 "ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs",
 "ui/higher-ranked/trait-bounds/issue-39292.rs",
 "ui/higher-ranked/trait-bounds/issue-42114.rs",
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs
new file mode 100644
index 0000000000000..b448f0bdc7778
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs
@@ -0,0 +1,28 @@
+// cc #119820
+
+trait Trait {}
+
+impl<T: Trait> Trait for &T {}
+impl Trait for u32 {}
+
+fn hr_bound<T>()
+where
+    for<'a> &'a T: Trait,
+{
+}
+
+fn foo<T>()
+where
+    T: Trait,
+    for<'a> &'a &'a T: Trait,
+{
+    // We get a universe error when using the `param_env` candidate
+    // but are able to successfully use the impl candidate. Without
+    // the leak check both candidates may apply and we prefer the
+    // `param_env` candidate in winnowing.
+    hr_bound::<&T>();
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| ERROR implementation of `Trait` is not general enough
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr
new file mode 100644
index 0000000000000..febe252d7d1d5
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr
@@ -0,0 +1,26 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/candidate-from-env-universe-err-1.rs:23:5
+   |
+LL |     hr_bound::<&T>();
+   |     ^^^^^^^^^^^^^^
+   |     |
+   |     the parameter type `T` must be valid for the static lifetime...
+   |     ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     T: Trait + 'static,
+   |              +++++++++
+
+error: implementation of `Trait` is not general enough
+  --> $DIR/candidate-from-env-universe-err-1.rs:23:5
+   |
+LL |     hr_bound::<&T>();
+   |     ^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+   |
+   = note: `Trait` would have to be implemented for the type `&'0 &T`, for any lifetime `'0`...
+   = note: ...but `Trait` is actually implemented for the type `&'1 &'1 T`, for some specific lifetime `'1`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr
new file mode 100644
index 0000000000000..22ce87c024861
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr
@@ -0,0 +1,25 @@
+error: lifetime may not live long enough
+  --> $DIR/candidate-from-env-universe-err-2.rs:14:5
+   |
+LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() {
+   |           -- lifetime `'a` defined here
+LL |     impl_hr::<T>();
+   |     ^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/candidate-from-env-universe-err-2.rs:11:19
+   |
+LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of `Trait` is not general enough
+  --> $DIR/candidate-from-env-universe-err-2.rs:14:5
+   |
+LL |     impl_hr::<T>();
+   |     ^^^^^^^^^^^^ implementation of `Trait` is not general enough
+   |
+   = note: `T` must implement `Trait<'0, '_>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Trait<'1, '_>`, for some specific lifetime `'1`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr
new file mode 100644
index 0000000000000..a61bc748bea2d
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
+  --> $DIR/candidate-from-env-universe-err-2.rs:14:5
+   |
+LL |     impl_hr::<T>();
+   |     ^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T`
+   |
+note: required by a bound in `impl_hr`
+  --> $DIR/candidate-from-env-universe-err-2.rs:11:19
+   |
+LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr`
+help: consider further restricting this bound
+   |
+LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static> + for<'a> Trait<'a, '_>>() {
+   |                                                              +++++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr
new file mode 100644
index 0000000000000..29a72b1c1b641
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr
@@ -0,0 +1,26 @@
+error: lifetime may not live long enough
+  --> $DIR/candidate-from-env-universe-err-2.rs:14:5
+   |
+LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() {
+   |           -- lifetime `'a` defined here
+LL |     impl_hr::<T>();
+   |     ^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/candidate-from-env-universe-err-2.rs:11:19
+   |
+LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/candidate-from-env-universe-err-2.rs:14:5
+   |
+LL |     impl_hr::<T>();
+   |     ^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected trait `for<'a> Trait<'a, '_>`
+              found trait `for<'b> Trait<'_, 'b>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs
new file mode 100644
index 0000000000000..56fa70469ccf8
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs
@@ -0,0 +1,20 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+// cc #119820
+
+trait Trait<'a, 'b> {}
+
+trait OtherTrait<'b> {}
+impl<'a, 'b, T: OtherTrait<'b>> Trait<'a, 'b> for T {}
+
+fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
+
+fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() {
+    impl_hr::<T>();
+    //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
+    //[current]~^^ERROR lifetime may not live long enough
+    //[current]~| ERROR implementation of `Trait` is not general enough
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr
new file mode 100644
index 0000000000000..bb0b2de788e83
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr
@@ -0,0 +1,54 @@
+error: implementation of `Trait` is not general enough
+  --> $DIR/candidate-from-env-universe-err-project.rs:28:5
+   |
+LL |     trait_bound::<T>();
+   |     ^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+   |
+   = note: `T` must implement `Trait<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Trait<'static>`
+
+error: implementation of `Trait` is not general enough
+  --> $DIR/candidate-from-env-universe-err-project.rs:39:5
+   |
+LL |     projection_bound::<T>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+   |
+   = note: `T` must implement `Trait<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Trait<'static>`
+
+error[E0308]: mismatched types
+  --> $DIR/candidate-from-env-universe-err-project.rs:39:5
+   |
+LL |     projection_bound::<T>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected associated type `<T as Trait<'static>>::Assoc`
+              found associated type `<T as Trait<'a>>::Assoc`
+note: the lifetime requirement is introduced here
+  --> $DIR/candidate-from-env-universe-err-project.rs:18:42
+   |
+LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
+   |                                          ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/candidate-from-env-universe-err-project.rs:55:30
+   |
+LL |     let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected associated type `<T as Trait<'static>>::Assoc`
+              found associated type `<T as Trait<'a>>::Assoc`
+
+error[E0308]: mismatched types
+  --> $DIR/candidate-from-env-universe-err-project.rs:55:30
+   |
+LL |     let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected associated type `<T as Trait<'static>>::Assoc`
+              found associated type `<T as Trait<'a>>::Assoc`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr
new file mode 100644
index 0000000000000..2804d5bbe9408
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr
@@ -0,0 +1,67 @@
+error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
+  --> $DIR/candidate-from-env-universe-err-project.rs:28:19
+   |
+LL |     trait_bound::<T>();
+   |                   ^ the trait `for<'a> Trait<'a>` is not implemented for `T`
+   |
+note: required by a bound in `trait_bound`
+  --> $DIR/candidate-from-env-universe-err-project.rs:17:19
+   |
+LL | fn trait_bound<T: for<'a> Trait<'a>>() {}
+   |                   ^^^^^^^^^^^^^^^^^ required by this bound in `trait_bound`
+help: consider further restricting this bound
+   |
+LL | fn function1<T: Trait<'static> + for<'a> Trait<'a>>() {
+   |                                +++++++++++++++++++
+
+error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
+  --> $DIR/candidate-from-env-universe-err-project.rs:39:24
+   |
+LL |     projection_bound::<T>();
+   |                        ^ the trait `for<'a> Trait<'a>` is not implemented for `T`
+   |
+note: required by a bound in `projection_bound`
+  --> $DIR/candidate-from-env-universe-err-project.rs:18:24
+   |
+LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound`
+help: consider further restricting this bound
+   |
+LL | fn function2<T: Trait<'static, Assoc = usize> + for<'a> Trait<'a>>() {
+   |                                               +++++++++++++++++++
+
+error[E0271]: type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
+  --> $DIR/candidate-from-env-universe-err-project.rs:39:24
+   |
+LL |     projection_bound::<T>();
+   |                        ^ type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
+   |
+note: types differ
+  --> $DIR/candidate-from-env-universe-err-project.rs:14:18
+   |
+LL |     type Assoc = usize;
+   |                  ^^^^^
+note: required by a bound in `projection_bound`
+  --> $DIR/candidate-from-env-universe-err-project.rs:18:42
+   |
+LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
+   |                                          ^^^^^^^^^^^^^ required by this bound in `projection_bound`
+
+error: higher-ranked subtype error
+  --> $DIR/candidate-from-env-universe-err-project.rs:55:30
+   |
+LL |     let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/candidate-from-env-universe-err-project.rs:55:30
+   |
+LL |     let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs
new file mode 100644
index 0000000000000..2f53bd019b78c
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs
@@ -0,0 +1,62 @@
+//@ revisions: next current
+//@[next] compile-flags: -Znext-solver
+
+// cc #119820 the previous behavior here was inconsistent as we discarded
+// the where-bound candidate for trait goals due to the leak check, but did
+// not do so for projection candidates and during normalization.
+//
+// This results in an inconsistency between `Trait` and `Projection` goals as
+// normalizing always constraints the normalized-to term.
+trait Trait<'a> {
+    type Assoc;
+}
+impl<'a, T> Trait<'a> for T {
+    type Assoc = usize;
+}
+
+fn trait_bound<T: for<'a> Trait<'a>>() {}
+fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
+
+// We use a function with a trivial where-bound which is more
+// restrictive than the impl.
+fn function1<T: Trait<'static>>() {
+    // err
+    //
+    // Proving `for<'a> T: Trait<'a>` using the where-bound does not
+    // result in a leak check failure even though it does not apply.
+    // We prefer env candidates over impl candidatescausing this to succeed.
+    trait_bound::<T>();
+    //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied
+    //[current]~^^ ERROR implementation of `Trait` is not general enough
+}
+
+fn function2<T: Trait<'static, Assoc = usize>>() {
+    // err
+    //
+    // Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>`
+    // does not use the leak check when trying the where-bound, causing us
+    // to prefer it over the impl, resulting in a placeholder error.
+    projection_bound::<T>();
+    //[next]~^ ERROR type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
+    //[next]~| ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied
+    //[current]~^^^ ERROR implementation of `Trait` is not general enough
+    //[current]~| ERROR mismatched types
+}
+
+fn function3<T: Trait<'static, Assoc = usize>>() {
+    // err
+    //
+    // Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
+    // only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
+    // instantiated, causing us to prefer the where-bound over the impl
+    // resulting in a placeholder error. Even if were were to also use the
+    // leak check during candidate selection for normalization, this
+    // case would still not compile.
+    let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
+    //[next]~^ ERROR higher-ranked subtype error
+    //[next]~| ERROR higher-ranked subtype error
+    //[current]~^^^ ERROR mismatched types
+    //[current]~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/leak-check-in-selection.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs
similarity index 100%
rename from tests/ui/higher-ranked/leak-check-in-selection.rs
rename to tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr
new file mode 100644
index 0000000000000..a840304e49c1f
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr
@@ -0,0 +1,23 @@
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-2.rs:16:5
+   |
+LL |     impls_trait::<(), _>();
+   |     ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait`
+   |
+note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found
+  --> $DIR/leak-check-in-selection-2.rs:9:1
+   |
+LL | impl<'a> Trait<&'a str, &'a str> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | impl<'a> Trait<&'a str, String> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `impls_trait`
+  --> $DIR/leak-check-in-selection-2.rs:13:19
+   |
+LL | fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr
new file mode 100644
index 0000000000000..a840304e49c1f
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr
@@ -0,0 +1,23 @@
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-2.rs:16:5
+   |
+LL |     impls_trait::<(), _>();
+   |     ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait`
+   |
+note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found
+  --> $DIR/leak-check-in-selection-2.rs:9:1
+   |
+LL | impl<'a> Trait<&'a str, &'a str> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | impl<'a> Trait<&'a str, String> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `impls_trait`
+  --> $DIR/leak-check-in-selection-2.rs:13:19
+   |
+LL | fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs
new file mode 100644
index 0000000000000..48dd569f201b9
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs
@@ -0,0 +1,18 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+
+// cc #119820
+
+trait Trait<T, U> {}
+
+// using this impl results in a higher-ranked region error.
+impl<'a> Trait<&'a str, &'a str> for () {}
+
+impl<'a> Trait<&'a str, String> for () {}
+
+fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
+
+fn main() {
+    impls_trait::<(), _>();
+    //~^ ERROR type annotations needed
+}
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr
new file mode 100644
index 0000000000000..8a8118dea859b
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr
@@ -0,0 +1,35 @@
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-3.rs:18:5
+   |
+LL |     impls_leak::<Box<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak`
+   |
+note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
+  --> $DIR/leak-check-in-selection-3.rs:9:1
+   |
+LL | impl Leak<'_> for Box<u32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Leak<'static> for Box<u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `impls_leak`
+  --> $DIR/leak-check-in-selection-3.rs:12:18
+   |
+LL | fn impls_leak<T: for<'a> Leak<'a>>() {}
+   |                  ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak`
+
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-3.rs:35:5
+   |
+LL |     impls_indirect_leak::<Box<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
+   |
+   = note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>`
+note: required by a bound in `impls_indirect_leak`
+  --> $DIR/leak-check-in-selection-3.rs:25:27
+   |
+LL | fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr
new file mode 100644
index 0000000000000..662a06537401a
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr
@@ -0,0 +1,48 @@
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-3.rs:18:5
+   |
+LL |     impls_leak::<Box<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak`
+   |
+note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
+  --> $DIR/leak-check-in-selection-3.rs:9:1
+   |
+LL | impl Leak<'_> for Box<u32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Leak<'static> for Box<u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `impls_leak`
+  --> $DIR/leak-check-in-selection-3.rs:12:18
+   |
+LL | fn impls_leak<T: for<'a> Leak<'a>>() {}
+   |                  ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak`
+
+error[E0283]: type annotations needed
+  --> $DIR/leak-check-in-selection-3.rs:35:5
+   |
+LL |     impls_indirect_leak::<Box<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
+   |
+note: multiple `impl`s satisfying `Box<_>: Leak<'_>` found
+  --> $DIR/leak-check-in-selection-3.rs:9:1
+   |
+LL | impl Leak<'_> for Box<u32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Leak<'static> for Box<u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>`
+  --> $DIR/leak-check-in-selection-3.rs:23:23
+   |
+LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
+   |             --------  ^^^^^^^^^^^^^^^^     ^
+   |             |
+   |             unsatisfied trait bound introduced here
+note: required by a bound in `impls_indirect_leak`
+  --> $DIR/leak-check-in-selection-3.rs:25:27
+   |
+LL | fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs
new file mode 100644
index 0000000000000..9e99b6c527d9d
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs
@@ -0,0 +1,39 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+
+// cc #119820, the previous behavior here was inconsistent,
+// using the leak check to guide inference for `for<'a> Box<_>: Leak<'a>`
+// but not for `for<'a> Box<_>: IndirectLeak<'a>`
+
+trait Leak<'a> {}
+impl Leak<'_> for Box<u32> {}
+impl Leak<'static> for Box<u16> {}
+
+fn impls_leak<T: for<'a> Leak<'a>>() {}
+fn direct() {
+    // ok
+    //
+    // The `Box<u16>` impls fails the leak check,
+    // meaning that we apply the `Box<u32>` impl.
+    impls_leak::<Box<_>>();
+    //~^ ERROR type annotations needed
+}
+
+trait IndirectLeak<'a> {}
+impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
+
+fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
+fn indirect() {
+    // error: type annotations needed
+    //
+    // While the `Box<u16>` impl would fail the leak check
+    // we have already instantiated the binder while applying
+    // the generic `IndirectLeak` impl, so during candidate
+    // selection of `Leak` we do not detect the placeholder error.
+    // Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous,
+    // resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous.
+    impls_indirect_leak::<Box<_>>();
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs
new file mode 100644
index 0000000000000..8d87bdd064a06
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs
@@ -0,0 +1,29 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// cc #119820. While the leak check does not consider the binder
+// of the current goal, leaks from higher-ranked nested goals are
+// considered.
+//
+// We enter and exit the binder of the nested goal while evaluating
+// the candidate.
+
+trait LeakCheckFailure<'a> {}
+impl LeakCheckFailure<'static> for () {}
+
+trait Trait<T> {}
+impl Trait<u32> for () where for<'a> (): LeakCheckFailure<'a> {}
+impl Trait<u16> for () {}
+fn impls_trait<T: Trait<U>, U>() {}
+fn main() {
+    // ok
+    //
+    // It does not matter whether candidate assembly
+    // considers the placeholders from higher-ranked goal.
+    //
+    // Either `for<'a> (): LeakCheckFailure<'a>` has no applicable
+    // candidate or it has a single applicable candidate which then later
+    // results in an error. This allows us to infer `U` to `u16`.
+    impls_trait::<(), _>()
+}
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
similarity index 86%
rename from tests/ui/higher-ranked/trait-bounds/issue-30786.rs
rename to tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
index ffb2b306ae76a..799df8cae9fd7 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-30786.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs
@@ -1,6 +1,6 @@
 //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 
-// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
+// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T>`
 // should act as assertion that item does not borrow from its stream;
 // but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
 // have such an item.
@@ -97,10 +97,6 @@ where
 
 impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
 
-fn identity<T>(x: &T) -> &T {
-    x
-}
-
 fn variant1() {
     let source = Repeat(10);
 
@@ -118,19 +114,7 @@ fn variant1() {
     // guess.
     let map = source.mapx(|x: &_| x);
     let filter = map.filterx(|x: &_| true);
-    //~^ ERROR the method
-}
-
-fn variant2() {
-    let source = Repeat(10);
-
-    // Here, we use a function, which is not subject to the vagaries
-    // of closure signature inference. In this case, we get the error
-    // on `countx` as, I think, the test originally expected.
-    let map = source.mapx(identity);
-    let filter = map.filterx(|x: &_| true);
-    let count = filter.countx();
-    //~^ ERROR the method
+    //~^ ERROR the method `filterx` exists for struct
 }
 
 fn main() {}
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr
new file mode 100644
index 0000000000000..ae364de8cc061
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr
@@ -0,0 +1,27 @@
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, {closure@hrtb-doesnt-borrow-self-1.rs:115:27}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:116:22
+   |
+LL | pub struct Map<S, F> {
+   | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt`
+...
+LL |     let filter = map.filterx(|x: &_| true);
+   |                      ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `&'a mut &Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
+      `&'a mut &mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
+      `&'a mut Map<Repeat, {closure@$DIR/hrtb-doesnt-borrow-self-1.rs:115:27: 115:34}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:98:50
+   |
+LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `StreamExt` defines an item `filterx`, perhaps you need to implement it
+  --> $DIR/hrtb-doesnt-borrow-self-1.rs:66:1
+   |
+LL | pub trait StreamExt
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
new file mode 100644
index 0000000000000..92e2e7f796eaa
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
@@ -0,0 +1,116 @@
+//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
+// should act as assertion that item does not borrow from its stream;
+// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
+// have such an item.
+//
+// This tests double-checks that we do not allow such behavior to leak
+// through again.
+
+pub trait Stream {
+    type Item;
+    fn next(self) -> Option<Self::Item>;
+}
+
+// Example stream
+pub struct Repeat(u64);
+
+impl<'a> Stream for &'a mut Repeat {
+    type Item = &'a u64;
+    fn next(self) -> Option<Self::Item> {
+        Some(&self.0)
+    }
+}
+
+pub struct Map<S, F> {
+    stream: S,
+    func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Map<A, F>
+where
+    &'a mut A: Stream,
+    F: FnMut(<&'a mut A as Stream>::Item) -> T,
+{
+    type Item = T;
+    fn next(self) -> Option<T> {
+        match self.stream.next() {
+            Some(item) => Some((self.func)(item)),
+            None => None,
+        }
+    }
+}
+
+pub struct Filter<S, F> {
+    stream: S,
+    func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
+where
+    for<'b> &'b mut A: Stream<Item = T>, // <---- BAD
+    F: FnMut(&T) -> bool,
+{
+    type Item = <&'a mut A as Stream>::Item;
+    fn next(self) -> Option<Self::Item> {
+        while let Some(item) = self.stream.next() {
+            if (self.func)(&item) {
+                return Some(item);
+            }
+        }
+        None
+    }
+}
+
+pub trait StreamExt
+where
+    for<'b> &'b mut Self: Stream,
+{
+    fn mapx<F>(self, func: F) -> Map<Self, F>
+    where
+        Self: Sized,
+        for<'a> &'a mut Map<Self, F>: Stream,
+    {
+        Map { func: func, stream: self }
+    }
+
+    fn filterx<F>(self, func: F) -> Filter<Self, F>
+    where
+        Self: Sized,
+        for<'a> &'a mut Filter<Self, F>: Stream,
+    {
+        Filter { func: func, stream: self }
+    }
+
+    fn countx(mut self) -> usize
+    where
+        Self: Sized,
+    {
+        let mut count = 0;
+        while let Some(_) = self.next() {
+            count += 1;
+        }
+        count
+    }
+}
+
+impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+
+fn identity<T>(x: &T) -> &T {
+    x
+}
+
+fn variant2() {
+    let source = Repeat(10);
+
+    // Here, we use a function, which is not subject to the vagaries
+    // of closure signature inference. In this case, we get the error
+    // on `countx` as, I think, the test originally expected.
+    let map = source.mapx(identity);
+    let filter = map.filterx(|x: &_| true);
+    let count = filter.countx();
+    //~^ ERROR the method
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
new file mode 100644
index 0000000000000..eeb4e12fa8b31
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
@@ -0,0 +1,27 @@
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@hrtb-doesnt-borrow-self-2.rs:111:30}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:112:24
+   |
+LL | pub struct Filter<S, F> {
+   | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
+...
+LL |     let count = filter.countx();
+   |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:98:50
+   |
+LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `StreamExt` defines an item `countx`, perhaps you need to implement it
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:66:1
+   |
+LL | pub trait StreamExt
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
index e10da26665ebb..be19bf85bd2f3 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -1,23 +1,11 @@
-error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
-  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
+error: implementation of `Bar` is not general enough
+  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5
    |
 LL |     want_bar_for_any_ccx(b);
-   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough
    |
-note: required by a bound in `want_bar_for_any_ccx`
-  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
-   |
-LL | fn want_bar_for_any_ccx<B>(b: &B)
-   |    -------------------- required by a bound in this function
-LL |     where B : for<'ccx> Bar<'ccx>
-   |               ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
-help: consider further restricting this bound
-   |
-LL |     where B : Qux + for<'ccx> Bar<'ccx>
-   |                   +++++++++++++++++++++
+   = note: `B` must implement `Bar<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Bar<'static>`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs
index 33e0ec4635b66..70ce580258d43 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs
@@ -1,43 +1,37 @@
 // Test a trait (`Bar`) with a higher-ranked supertrait.
+#![allow(unconditional_recursion)]
 
-trait Foo<'tcx>
-{
+trait Foo<'tcx> {
     fn foo(&'tcx self) -> &'tcx isize;
 }
 
-trait Bar<'ccx>
-    : for<'tcx> Foo<'tcx>
-{
+trait Bar<'ccx>: for<'tcx> Foo<'tcx> {
     fn bar(&'ccx self) -> &'ccx isize;
 }
 
-fn want_foo_for_some_tcx<'x,F>(f: &'x F)
-    where F : Foo<'x>
-{
+fn want_foo_for_some_tcx<'x, F: Foo<'x>>(f: &'x F) {
     want_foo_for_some_tcx(f);
-    want_foo_for_any_tcx(f); //~ ERROR not satisfied
+    want_foo_for_any_tcx(f);
+    //~^ ERROR lifetime may not live long enough
+    //~| ERROR implementation of `Foo` is not general enough
 }
 
-fn want_foo_for_any_tcx<F>(f: &F) //~ WARN cannot return without recursing
-    where F : for<'tcx> Foo<'tcx>
-{
+fn want_foo_for_any_tcx<F: for<'tcx> Foo<'tcx>>(f: &F) {
     want_foo_for_some_tcx(f);
     want_foo_for_any_tcx(f);
 }
 
-fn want_bar_for_some_ccx<'x,B>(b: &B)
-    where B : Bar<'x>
-{
+fn want_bar_for_some_ccx<'x, B: Bar<'x>>(b: &B) {
     want_foo_for_some_tcx(b);
     want_foo_for_any_tcx(b);
 
     want_bar_for_some_ccx(b);
-    want_bar_for_any_ccx(b); //~ ERROR not satisfied
+    want_bar_for_any_ccx(b);
+    //~^ ERROR lifetime may not live long enough
+    //~| ERROR implementation of `Bar` is not general enough
 }
 
-fn want_bar_for_any_ccx<B>(b: &B) //~ WARN cannot return without recursing
-    where B : for<'ccx> Bar<'ccx>
-{
+fn want_bar_for_any_ccx<B: for<'ccx> Bar<'ccx>>(b: &B) {
     want_foo_for_some_tcx(b);
     want_foo_for_any_tcx(b);
 
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
index f220ba6f33893..dd760926ea117 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
@@ -1,68 +1,50 @@
-error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
+error: lifetime may not live long enough
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:14:5
    |
+LL | fn want_foo_for_some_tcx<'x, F: Foo<'x>>(f: &'x F) {
+   |                          -- lifetime `'x` defined here
+LL |     want_foo_for_some_tcx(f);
 LL |     want_foo_for_any_tcx(f);
-   |     -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static`
    |
-note: required by a bound in `want_foo_for_any_tcx`
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:19:28
    |
-LL | fn want_foo_for_any_tcx<F>(f: &F)
-   |    -------------------- required by a bound in this function
-LL |     where F : for<'tcx> Foo<'tcx>
-   |               ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx`
-help: consider further restricting this bound
-   |
-LL |     where F : Foo<'x> + for<'tcx> Foo<'tcx>
-   |                       +++++++++++++++++++++
+LL | fn want_foo_for_any_tcx<F: for<'tcx> Foo<'tcx>>(f: &F) {
+   |                            ^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
-   |
-LL |     want_bar_for_any_ccx(b);
-   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
-   |     |
-   |     required by a bound introduced by this call
+error: implementation of `Foo` is not general enough
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:14:5
    |
-note: required by a bound in `want_bar_for_any_ccx`
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
-   |
-LL | fn want_bar_for_any_ccx<B>(b: &B)
-   |    -------------------- required by a bound in this function
-LL |     where B : for<'ccx> Bar<'ccx>
-   |               ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
-help: consider further restricting this bound
+LL |     want_foo_for_any_tcx(f);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-LL |     where B : Bar<'x> + for<'ccx> Bar<'ccx>
-   |                       +++++++++++++++++++++
+   = note: `F` must implement `Foo<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1`
 
-warning: function cannot return without recursing
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1
+error: lifetime may not live long enough
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:29:5
    |
-LL | / fn want_foo_for_any_tcx<F>(f: &F)
-LL | |     where F : for<'tcx> Foo<'tcx>
-   | |_________________________________^ cannot return without recursing
+LL | fn want_bar_for_some_ccx<'x, B: Bar<'x>>(b: &B) {
+   |                          -- lifetime `'x` defined here
 ...
-LL |       want_foo_for_any_tcx(f);
-   |       ----------------------- recursive call site
+LL |     want_bar_for_any_ccx(b);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static`
+   |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:34:28
    |
-   = help: a `loop` may express intention better if this is on purpose
-   = note: `#[warn(unconditional_recursion)]` on by default
+LL | fn want_bar_for_any_ccx<B: for<'ccx> Bar<'ccx>>(b: &B) {
+   |                            ^^^^^^^^^^^^^^^^^^^
 
-warning: function cannot return without recursing
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1
+error: implementation of `Bar` is not general enough
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:29:5
    |
-LL | / fn want_bar_for_any_ccx<B>(b: &B)
-LL | |     where B : for<'ccx> Bar<'ccx>
-   | |_________________________________^ cannot return without recursing
-...
-LL |       want_bar_for_any_ccx(b);
-   |       ----------------------- recursive call site
+LL |     want_bar_for_any_ccx(b);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough
    |
-   = help: a `loop` may express intention better if this is on purpose
+   = note: `B` must implement `Bar<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Bar<'1>`, for some specific lifetime `'1`
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
deleted file mode 100644
index 699a4ecc42bb9..0000000000000
--- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
+++ /dev/null
@@ -1,51 +0,0 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, {closure@issue-30786.rs:119:27}>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:120:22
-   |
-LL | pub struct Map<S, F> {
-   | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt`
-...
-LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, {closure@issue-30786.rs:119:27}>` due to unsatisfied trait bounds
-   |
-note: the following trait bounds were not satisfied:
-      `&'a mut &Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
-      `&'a mut &mut Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
-      `&'a mut Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
-  --> $DIR/issue-30786.rs:98:50
-   |
-LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
-   = help: items from traits can only be used if the trait is implemented and in scope
-note: `StreamExt` defines an item `filterx`, perhaps you need to implement it
-  --> $DIR/issue-30786.rs:66:1
-   |
-LL | pub trait StreamExt
-   | ^^^^^^^^^^^^^^^^^^^
-
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:132:24
-   |
-LL | pub struct Filter<S, F> {
-   | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
-...
-LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
-   |
-note: the following trait bounds were not satisfied:
-      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
-      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
-  --> $DIR/issue-30786.rs:98:50
-   |
-LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
-   = help: items from traits can only be used if the trait is implemented and in scope
-note: `StreamExt` defines an item `countx`, perhaps you need to implement it
-  --> $DIR/issue-30786.rs:66:1
-   |
-LL | pub trait StreamExt
-   | ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/implied-bounds/issue-100690.rs b/tests/ui/implied-bounds/issue-100690.rs
index ea33c9f423b77..041c687ec9430 100644
--- a/tests/ui/implied-bounds/issue-100690.rs
+++ b/tests/ui/implied-bounds/issue-100690.rs
@@ -4,11 +4,8 @@
 use std::io;
 
 fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
-//~^ NOTE required by a bound in this
 where
     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
-    //~^ NOTE required by this bound in `real_dispatch`
-    //~| NOTE required by a bound in `real_dispatch`
 {
     todo!()
 }
@@ -35,10 +32,10 @@ impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandl
         F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static,
     {
         real_dispatch(f)
-        //~^ ERROR expected a `FnOnce(&mut UIView<'_, T>)` closure, found `F`
-        //~| NOTE expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F`
-        //~| NOTE expected a closure with arguments
-        //~| NOTE required by a bound introduced by this call
+        //~^ ERROR lifetime may not live long enough
+        //~| ERROR implementation of `FnOnce` is not general enough
+        //~| ERROR mismatched types
+        //
     }
 }
 
diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr
index df069d875cebc..2cfd028f2559b 100644
--- a/tests/ui/implied-bounds/issue-100690.stderr
+++ b/tests/ui/implied-bounds/issue-100690.stderr
@@ -1,22 +1,41 @@
-error[E0277]: expected a `FnOnce(&mut UIView<'_, T>)` closure, found `F`
-  --> $DIR/issue-100690.rs:37:23
+error: lifetime may not live long enough
+  --> $DIR/issue-100690.rs:34:9
    |
+LL | impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle<T> {
+   |      -- lifetime `'a` defined here
+...
 LL |         real_dispatch(f)
-   |         ------------- ^ expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F`
-   |         |
-   |         required by a bound introduced by this call
+   |         ^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
    |
-   = note: expected a closure with arguments `(&mut UIView<'a, _>,)`
-              found a closure with arguments `(&mut UIView<'_, _>,)`
-note: required by a bound in `real_dispatch`
-  --> $DIR/issue-100690.rs:9:8
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+  --> $DIR/issue-100690.rs:8:8
+   |
+LL |     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-100690.rs:34:9
+   |
+LL |         real_dispatch(f)
+   |         ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: `F` must implement `FnOnce<(&mut UIView<'0, T>,)>`, for any lifetime `'0`...
+   = note: ...but it actually implements `FnOnce<(&mut UIView<'1, T>,)>`, for some specific lifetime `'1`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-100690.rs:34:9
+   |
+LL |         real_dispatch(f)
+   |         ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected associated type `<F as FnOnce<(&mut UIView<'_, T>,)>>::Output`
+              found associated type `<F as FnOnce<(&mut UIView<'_, T>,)>>::Output`
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-100690.rs:8:34
    |
-LL | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
-   |    ------------- required by a bound in this function
-...
 LL |     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`
+   |                                  ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0308`.