diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index 7f1f3c3c802a4..e4c62bf027bd3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -120,15 +120,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
     fn visit_goal(&mut self, inspect_goal: &InspectGoal<'_, 'tcx>) {
         // No need to walk into goal subtrees that certainly hold, since they
         // wouldn't then be stalled on an infer var.
-        // FIXME: We also walk into normalizes-to goals since their certainty
-        // is forced to `Certainty::Yes` since they pass down ambiguous subgoals
-        // to their parent.
-        if inspect_goal.result() == Ok(Certainty::Yes)
-            && !matches!(
-                inspect_goal.goal().predicate.kind().skip_binder(),
-                ty::PredicateKind::NormalizesTo(_)
-            )
-        {
+        if inspect_goal.result() == Ok(Certainty::Yes) {
             return;
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index d5d318ee49095..b0c8fa1f217d2 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -11,7 +11,8 @@
 
 use std::assert_matches::assert_matches;
 
-use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::Obligation;
 use rustc_macros::extension;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
@@ -20,7 +21,7 @@ use rustc_middle::{bug, ty};
 use rustc_next_trait_solver::resolve::eager_resolve_vars;
 use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state};
 use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _};
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::Span;
 use tracing::instrument;
 
 use crate::solve::delegate::SolverDelegate;
@@ -60,28 +61,29 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
     /// Relate the `term` with the new `unconstrained_term` created
     /// when computing the proof tree for this `NormalizesTo` goals.
     /// This handles nested obligations.
-    fn constrain(
-        self,
+    fn constrain_and(
+        &self,
         infcx: &InferCtxt<'tcx>,
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
+        f: impl FnOnce(&ObligationCtxt<'_, 'tcx>),
     ) -> Result<Certainty, NoSolution> {
-        infcx
-            .at(&ObligationCause::dummy_with_span(span), param_env)
-            .eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term)
-            .map_err(|_| NoSolution)
-            .and_then(|InferOk { value: (), obligations }| {
-                let ocx = ObligationCtxt::new(infcx);
-                ocx.register_obligations(obligations);
-                let errors = ocx.select_all_or_error();
-                if errors.is_empty() {
-                    Ok(Certainty::Yes)
-                } else if errors.iter().all(|e| !e.is_true_error()) {
-                    Ok(Certainty::AMBIGUOUS)
-                } else {
-                    Err(NoSolution)
-                }
-            })
+        let ocx = ObligationCtxt::new(infcx);
+        ocx.eq(
+            &ObligationCause::dummy_with_span(span),
+            param_env,
+            self.term,
+            self.unconstrained_term,
+        )?;
+        f(&ocx);
+        let errors = ocx.select_all_or_error();
+        if errors.is_empty() {
+            Ok(Certainty::Yes)
+        } else if errors.iter().all(|e| !e.is_true_error()) {
+            Ok(Certainty::AMBIGUOUS)
+        } else {
+            Err(NoSolution)
+        }
     }
 }
 
@@ -160,11 +162,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
         let () =
             instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state);
 
-        if let Some(term_hack) = self.goal.normalizes_to_term_hack {
+        if let Some(term_hack) = &self.goal.normalizes_to_term_hack {
             // FIXME: We ignore the expected term of `NormalizesTo` goals
             // when computing the result of its candidates. This is
             // scuffed.
-            let _ = term_hack.constrain(infcx, span, param_env);
+            let _ = term_hack.constrain_and(infcx, span, param_env, |_| {});
         }
 
         instantiated_goals
@@ -240,13 +242,39 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 // building their proof tree, the expected term was unconstrained, but when
                 // instantiating the candidate it is already constrained to the result of another
                 // candidate.
-                let proof_tree = infcx
-                    .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None).1);
+                let normalizes_to_term_hack = NormalizesToTermHack { term, unconstrained_term };
+                let (proof_tree, nested_goals_result) = infcx.probe(|_| {
+                    // Here, if we have any nested goals, then we make sure to apply them
+                    // considering the constrained RHS, and pass the resulting certainty to
+                    // `InspectGoal::new` so that the goal has the right result (and maintains
+                    // the impression that we don't do this normalizes-to infer hack at all).
+                    let (nested, proof_tree) =
+                        infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None);
+                    let proof_tree = proof_tree.unwrap();
+                    let nested_goals_result = nested.and_then(|(nested, _)| {
+                        normalizes_to_term_hack.constrain_and(
+                            infcx,
+                            span,
+                            proof_tree.uncanonicalized_goal.param_env,
+                            |ocx| {
+                                ocx.register_obligations(nested.0.into_iter().map(|(_, goal)| {
+                                    Obligation::new(
+                                        infcx.tcx,
+                                        ObligationCause::dummy_with_span(span),
+                                        goal.param_env,
+                                        goal.predicate,
+                                    )
+                                }));
+                            },
+                        )
+                    });
+                    (proof_tree, nested_goals_result)
+                });
                 InspectGoal::new(
                     infcx,
                     self.goal.depth + 1,
-                    proof_tree.unwrap(),
-                    Some(NormalizesToTermHack { term, unconstrained_term }),
+                    proof_tree,
+                    Some((normalizes_to_term_hack, nested_goals_result)),
                     source,
                 )
             }
@@ -393,20 +421,21 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         infcx: &'a InferCtxt<'tcx>,
         depth: usize,
         root: inspect::GoalEvaluation<TyCtxt<'tcx>>,
-        normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
+        term_hack_and_nested_certainty: Option<(
+            NormalizesToTermHack<'tcx>,
+            Result<Certainty, NoSolution>,
+        )>,
         source: GoalSource,
     ) -> Self {
         let infcx = <&SolverDelegate<'tcx>>::from(infcx);
 
         let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root;
+        // If there's a normalizes-to goal, AND the evaluation result with the result of
+        // constraining the normalizes-to RHS and computing the nested goals.
         let result = evaluation.result.and_then(|ok| {
-            if let Some(term_hack) = normalizes_to_term_hack {
-                infcx
-                    .probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env))
-                    .map(|certainty| ok.value.certainty.and(certainty))
-            } else {
-                Ok(ok.value.certainty)
-            }
+            let nested_goals_certainty =
+                term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?;
+            Ok(ok.value.certainty.and(nested_goals_certainty))
         });
 
         InspectGoal {
@@ -416,7 +445,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             goal: eager_resolve_vars(infcx, uncanonicalized_goal),
             result,
             evaluation_kind: evaluation.kind,
-            normalizes_to_term_hack,
+            normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n),
             source,
         }
     }
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
index 54ceec0aff5d7..5caf0eb2fd4e3 100644
--- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -1,9 +1,22 @@
-error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
-  --> $DIR/auto-trait-selection-freeze.rs:19:5
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection-freeze.rs:19:16
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
+   |                ^^^^^^^^ ----- type must be known at this point
+   |                |
+   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |
+   = note: cannot satisfy `_: Trait<_>`
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection-freeze.rs:11:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
+   |                        ++++++++
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
index 7acb9fd41b730..d34fdcc44967f 100644
--- a/tests/ui/impl-trait/auto-trait-selection.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -1,9 +1,22 @@
-error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
-  --> $DIR/auto-trait-selection.rs:15:5
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection.rs:15:16
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
+   |                ^^^^^^^^ ----- type must be known at this point
+   |                |
+   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |
+   = note: cannot satisfy `_: Trait<_>`
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection.rs:7:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
+   |                        ++++++++
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
index 9632d2ce6249a..f2e249f2cbf99 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
@@ -25,7 +25,7 @@ LL |     type LineStream<'c, 'd> = impl Stream;
    |
    = note: `LineStream` must be used in combination with a concrete type within the same impl
 
-error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
+error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to ()`
   --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
index 0b507ed948ae1..7cf155ce01ef4 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
@@ -29,7 +29,7 @@ impl X for Y {
     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
     //~^ ERROR method `line_stream` is not a member of trait `X`
     //[current]~^^ ERROR `()` is not a future
-    //[next]~^^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
+    //[next]~^^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to ()`
     //[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
     //[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
 }
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
index a3609b93cb3a8..db57be73acceb 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
-  --> $DIR/recursive-in-exhaustiveness.rs:19:17
+error[E0284]: type annotations needed: cannot normalize `build<_>::{opaque#0}`
+  --> $DIR/recursive-in-exhaustiveness.rs:20:5
    |
-LL |     let (x,) = (build(x),);
-   |                 ^^^^^^^^ cannot satisfy `impl Sized == _`
+LL |     build(x)
+   |     ^^^^^^^^ cannot normalize `build<_>::{opaque#0}`
 
 error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
   --> $DIR/recursive-in-exhaustiveness.rs:30:6
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
index fa8fa0e81743b..dabef22af8681 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
@@ -17,8 +17,8 @@
 fn build<T>(x: T) -> impl Sized {
     //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build(x),);
-    //[next]~^ ERROR type annotations needed
     build(x)
+    //[next]~^ ERROR type annotations needed: cannot normalize `build<_>::{opaque#0}`
 }
 
 // Opaque<T> = (Opaque<T>,)
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index 1a4c0f5f7eef5..fac4776905d06 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,9 +1,9 @@
-error[E0284]: type annotations needed: cannot satisfy `_ == A`
-  --> $DIR/two_tait_defining_each_other2.rs:12:8
+error[E0282]: type annotations needed
+  --> $DIR/two_tait_defining_each_other2.rs:12:11
    |
 LL | fn muh(x: A) -> B {
-   |        ^ cannot satisfy `_ == A`
+   |           ^ cannot infer type
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index 6c454bba5023f..ec2963249f9da 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -10,7 +10,7 @@ trait Foo {}
 
 #[define_opaque(A, B)]
 fn muh(x: A) -> B {
-    //[next]~^ ERROR: cannot satisfy `_ == A`
+    //[next]~^ ERROR: type annotations needed
     x // B's hidden type is A (opaquely)
     //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
 }
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
index ea6df93870474..14f0cbcc8b77c 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
@@ -13,9 +13,9 @@ fn main() {
 }
 
 fn weird0() -> impl Sized + !Sized {}
-//~^ ERROR type mismatch resolving
+//~^ ERROR the trait bound `(): !Sized` is not satisfied
 fn weird1() -> impl !Sized + Sized {}
-//~^ ERROR type mismatch resolving
+//~^ ERROR the trait bound `(): !Sized` is not satisfied
 fn weird2() -> impl !Sized {}
-//~^ ERROR type mismatch resolving
+//~^ ERROR the trait bound `(): !Sized` is not satisfied
 //~| ERROR the size for values of type
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
index 41d9e74f8076e..3ba3d8d8bd595 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
@@ -7,23 +7,23 @@ LL | fn weird2() -> impl !Sized {}
    = help: the trait `Sized` is not implemented for `impl !Sized`
    = note: the return type of a function must have a statically known size
 
-error[E0271]: type mismatch resolving `impl !Sized + Sized == ()`
+error[E0277]: the trait bound `(): !Sized` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:15:16
    |
 LL | fn weird0() -> impl Sized + !Sized {}
-   |                ^^^^^^^^^^^^^^^^^^^ types differ
+   |                ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
-error[E0271]: type mismatch resolving `impl !Sized + Sized == ()`
+error[E0277]: the trait bound `(): !Sized` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:17:16
    |
 LL | fn weird1() -> impl !Sized + Sized {}
-   |                ^^^^^^^^^^^^^^^^^^^ types differ
+   |                ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
-error[E0271]: type mismatch resolving `impl !Sized == ()`
+error[E0277]: the trait bound `(): !Sized` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:19:16
    |
 LL | fn weird2() -> impl !Sized {}
-   |                ^^^^^^^^^^^ types differ
+   |                ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
 error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:12:13
@@ -41,5 +41,4 @@ LL | fn consume(_: impl Trait) {}
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
index ce42bce0ad4e4..39422914afcdd 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
@@ -3,6 +3,6 @@
 #![feature(negative_bounds, unboxed_closures)]
 
 fn produce() -> impl !Fn<(u32,)> {}
-//~^ ERROR type mismatch resolving
+//~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
index e1b84e0df7a54..760e5aa62f2c1 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
@@ -1,9 +1,9 @@
-error[E0271]: type mismatch resolving `impl !Fn<(u32,)> == ()`
+error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied
   --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
    |
 LL | fn produce() -> impl !Fn<(u32,)> {}
-   |                 ^^^^^^^^^^^^^^^^ types differ
+   |                 ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
index 736c8c10da97b..6d2bbd8b08b4c 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
@@ -1,9 +1,16 @@
-error[E0284]: type annotations needed: cannot satisfy `Foo == _`
+error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
   --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
    |
 LL |     needs_send::<Foo>();
-   |                  ^^^ cannot satisfy `Foo == _`
+   |                  ^^^
+   |
+   = note: cannot satisfy `Foo: Send`
+note: required by a bound in `needs_send`
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
+   |
+LL | fn needs_send<T: Send>() {}
+   |                  ^^^^ required by this bound in `needs_send`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
index 736c8c10da97b..6d2bbd8b08b4c 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -1,9 +1,16 @@
-error[E0284]: type annotations needed: cannot satisfy `Foo == _`
+error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
   --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
    |
 LL |     needs_send::<Foo>();
-   |                  ^^^ cannot satisfy `Foo == _`
+   |                  ^^^
+   |
+   = note: cannot satisfy `Foo: Send`
+note: required by a bound in `needs_send`
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
+   |
+LL | fn needs_send<T: Send>() {}
+   |                  ^^^^ required by this bound in `needs_send`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
index 2a08a3b2b9481..fddf892e1ef1d 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
@@ -14,7 +14,7 @@ fn needs_send<T: Send>() {}
 #[define_opaque(Foo)]
 fn test(_: Foo) {
     needs_send::<Foo>();
-    //~^ ERROR type annotations needed: cannot satisfy `Foo == _`
+    //~^ ERROR type annotations needed
 }
 
 #[define_opaque(Foo)]
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
index 9e83de5375fd7..f7e0245bc8319 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
@@ -7,7 +7,7 @@ LL | impl<In, Out> Trait<Bar, In> for Out {
 LL | impl<In, Out> Trait<(), In> for Out {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
-error[E0284]: type annotations needed: cannot satisfy `Bar == _`
+error[E0282]: type annotations needed
   --> $DIR/issue-84660-unsoundness.rs:24:37
    |
 LL |       fn convert(_i: In) -> Self::Out {
@@ -16,9 +16,9 @@ LL | |
 LL | |
 LL | |         unreachable!();
 LL | |     }
-   | |_____^ cannot satisfy `Bar == _`
+   | |_____^ cannot infer type
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0119, E0284.
+Some errors have detailed explanations: E0119, E0282.
 For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index 7a540d2a57495..a385138b29502 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -22,7 +22,7 @@ impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     #[define_opaque(Bar)]
     fn convert(_i: In) -> Self::Out {
-        //[next]~^  ERROR: type annotations needed: cannot satisfy `Bar == _`
+        //[next]~^  ERROR: type annotations needed
         //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`
         unreachable!();
     }
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
index b733739e4c863..d2127976e7d22 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
@@ -1,9 +1,9 @@
-error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
+error[E0282]: type annotations needed
   --> $DIR/nested-tait-inference2.rs:20:5
    |
 LL |     ()
-   |     ^^ cannot satisfy `impl Foo<FooX> == ()`
+   |     ^^ cannot infer type
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
index 4aeecb9140c52..606336178e5ec 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
@@ -18,7 +18,7 @@ impl Foo<u32> for () {}
 fn foo() -> impl Foo<FooX> {
     //[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
     ()
-    //[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
+    //[next]~^ ERROR: type annotations needed
 }
 
 fn main() {}