diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 4c34bf88c7f96..3ad6b68d1299b 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -273,6 +273,8 @@ pub enum GoalSource {
     /// they are from an impl where-clause. This is necessary due to
     /// backwards compatability, cc trait-system-refactor-initiatitive#70.
     ImplWhereBound,
+    /// Instantiating a higher-ranked goal and re-proving it.
+    InstantiateHigherRanked,
 }
 
 /// Possible ways the given goal can be proven.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 2d73be387fdcd..11aa0e10931cb 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -127,6 +127,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                         let source = match source {
                             GoalSource::Misc => "misc",
                             GoalSource::ImplWhereBound => "impl where-bound",
+                            GoalSource::InstantiateHigherRanked => "higher-ranked goal",
                         };
                         writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")?
                     }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 280975f63bd3d..f2ca42a0be91e 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -58,15 +58,15 @@ pub(super) trait GoalKind<'tcx>:
     /// goal by equating it with the assumption.
     fn probe_and_consider_implied_clause(
         ecx: &mut EvalCtxt<'_, 'tcx>,
-        source: CandidateSource,
+        parent_source: CandidateSource,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-        requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
+        requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
     ) -> Result<Candidate<'tcx>, NoSolution> {
-        Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
-            // FIXME(-Znext-solver=coinductive): check whether this should be
-            // `GoalSource::ImplWhereBound` for any caller.
-            ecx.add_goals(GoalSource::Misc, requirements);
+        Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
+            for (nested_source, goal) in requirements {
+                ecx.add_goal(nested_source, goal);
+            }
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
@@ -85,9 +85,8 @@ pub(super) trait GoalKind<'tcx>:
             let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
                 bug!("expected object type in `probe_and_consider_object_bound_candidate`");
             };
-            // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
             ecx.add_goals(
-                GoalSource::Misc,
+                GoalSource::ImplWhereBound,
                 structural_traits::predicates_for_object_candidate(
                     ecx,
                     goal.param_env,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 6722abd709c31..d6bf2b596ef1e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -90,6 +90,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         &mut self,
         certainty: Certainty,
     ) -> QueryResult<'tcx> {
+        self.inspect.make_canonical_response(certainty);
+
         let goals_certainty = self.try_evaluate_added_goals()?;
         assert_eq!(
             self.tainted,
@@ -98,8 +100,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             previous call to `try_evaluate_added_goals!`"
         );
 
-        self.inspect.make_canonical_response(certainty);
-
         // When normalizing, we've replaced the expected term with an unconstrained
         // inference variable. This means that we dropped information which could
         // have been important. We handle this by instead returning the nested goals
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 1710746ae504e..bae1c6b60115e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -454,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         } else {
             self.infcx.enter_forall(kind, |kind| {
                 let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
-                self.add_goal(GoalSource::Misc, goal);
+                self.add_goal(GoalSource::InstantiateHigherRanked, goal);
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             })
         }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 3fa409eefffcd..796222129f180 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,15 +1,19 @@
 use std::mem;
+use std::ops::ControlFlow;
 
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::solve::MaybeCause;
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::solve::inspect::ProbeKind;
+use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
-    query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
-    PredicateObligation, SelectionError, TraitEngine,
+    self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
+    ObligationCause, PredicateObligation, SelectionError, TraitEngine,
 };
-use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::{self, TyCtxt};
 
 use super::eval_ctxt::GenerateProofTree;
+use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
 use super::{Certainty, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
@@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .collect();
 
         errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            root_obligation: obligation.clone(),
+            obligation: find_best_leaf_obligation(infcx, &obligation),
             code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
-            obligation,
+            root_obligation: obligation,
         }));
 
         errors
@@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
 
 fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    obligation: PredicateObligation<'tcx>,
+    root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
+    let obligation = find_best_leaf_obligation(infcx, &root_obligation);
+
     let code = match obligation.predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
             FulfillmentErrorCode::ProjectionError(
@@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>(
             bug!("unexpected goal: {obligation:?}")
         }
     };
-    FulfillmentError { root_obligation: obligation.clone(), code, obligation }
+
+    FulfillmentError { obligation, code, root_obligation }
 }
 
 fn fulfillment_error_for_stalled<'tcx>(
@@ -258,5 +265,136 @@ fn fulfillment_error_for_stalled<'tcx>(
         }
     });
 
-    FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation }
+    FulfillmentError {
+        obligation: find_best_leaf_obligation(infcx, &obligation),
+        code,
+        root_obligation: obligation,
+    }
+}
+
+fn find_best_leaf_obligation<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    obligation: &PredicateObligation<'tcx>,
+) -> PredicateObligation<'tcx> {
+    let obligation = infcx.resolve_vars_if_possible(obligation.clone());
+    infcx
+        .visit_proof_tree(
+            obligation.clone().into(),
+            &mut BestObligation { obligation: obligation.clone() },
+        )
+        .break_value()
+        .unwrap_or(obligation)
+}
+
+struct BestObligation<'tcx> {
+    obligation: PredicateObligation<'tcx>,
+}
+
+impl<'tcx> BestObligation<'tcx> {
+    fn with_derived_obligation(
+        &mut self,
+        derived_obligation: PredicateObligation<'tcx>,
+        and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
+    ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
+        let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
+        let res = and_then(self);
+        self.obligation = old_obligation;
+        res
+    }
+}
+
+impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
+    type Result = ControlFlow<PredicateObligation<'tcx>>;
+
+    fn span(&self) -> rustc_span::Span {
+        self.obligation.cause.span
+    }
+
+    fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
+        // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
+        // This most likely means that the goal just didn't unify at all, e.g. a param
+        // candidate with an alias in it.
+        let candidates = goal.candidates();
+
+        let [candidate] = candidates.as_slice() else {
+            return ControlFlow::Break(self.obligation.clone());
+        };
+
+        // FIXME: Could we extract a trait ref from a projection here too?
+        // FIXME: Also, what about considering >1 layer up the stack? May be necessary
+        // for normalizes-to.
+        let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
+            return ControlFlow::Break(self.obligation.clone());
+        };
+
+        let tcx = goal.infcx().tcx;
+        let mut impl_where_bound_count = 0;
+        for nested_goal in candidate.instantiate_nested_goals(self.span()) {
+            let obligation;
+            match nested_goal.source() {
+                GoalSource::Misc => {
+                    continue;
+                }
+                GoalSource::ImplWhereBound => {
+                    obligation = Obligation {
+                        cause: derive_cause(
+                            tcx,
+                            candidate.kind(),
+                            self.obligation.cause.clone(),
+                            impl_where_bound_count,
+                            parent_trait_pred,
+                        ),
+                        param_env: nested_goal.goal().param_env,
+                        predicate: nested_goal.goal().predicate,
+                        recursion_depth: self.obligation.recursion_depth + 1,
+                    };
+                    impl_where_bound_count += 1;
+                }
+                GoalSource::InstantiateHigherRanked => {
+                    obligation = self.obligation.clone();
+                }
+            }
+
+            // Skip nested goals that hold.
+            //FIXME: We should change the max allowed certainty based on if we're
+            // visiting an ambiguity or error obligation.
+            if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
+                continue;
+            }
+
+            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
+        }
+
+        ControlFlow::Break(self.obligation.clone())
+    }
+}
+
+fn derive_cause<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    candidate_kind: ProbeKind<'tcx>,
+    mut cause: ObligationCause<'tcx>,
+    idx: usize,
+    parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+) -> ObligationCause<'tcx> {
+    match candidate_kind {
+        ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => {
+            if let Some((_, span)) =
+                tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
+            {
+                cause = cause.derived_cause(parent_trait_pred, |derived| {
+                    traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
+                        derived,
+                        impl_or_alias_def_id: impl_def_id,
+                        impl_def_predicate_index: Some(idx),
+                        span,
+                    }))
+                })
+            }
+        }
+        ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => {
+            cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation);
+        }
+        _ => {}
+    };
+    cause
 }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 7c6dd4d3febc9..64a9a836b3dd4 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -42,6 +42,7 @@ pub struct InspectGoal<'a, 'tcx> {
     result: Result<Certainty, NoSolution>,
     evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>,
     normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
+    source: GoalSource,
 }
 
 /// The expected term of a `NormalizesTo` goal gets replaced
@@ -92,7 +93,7 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
 pub struct InspectCandidate<'a, 'tcx> {
     goal: &'a InspectGoal<'a, 'tcx>,
     kind: inspect::ProbeKind<'tcx>,
-    nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
+    nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
     final_state: inspect::CanonicalState<'tcx, ()>,
     result: QueryResult<'tcx>,
     shallow_certainty: Certainty,
@@ -127,10 +128,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
     /// back their inference constraints. This function modifies
     /// the state of the `infcx`.
     pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
-        if self.goal.depth < visitor.config().max_depth {
-            for goal in self.instantiate_nested_goals(visitor.span()) {
-                try_visit!(visitor.visit_goal(&goal));
-            }
+        for goal in self.instantiate_nested_goals(visitor.span()) {
+            try_visit!(goal.visit_with(visitor));
         }
 
         V::Result::output()
@@ -145,13 +144,16 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
         let instantiated_goals: Vec<_> = self
             .nested_goals
             .iter()
-            .map(|goal| {
-                canonical::instantiate_canonical_state(
-                    infcx,
-                    span,
-                    param_env,
-                    &mut orig_values,
-                    *goal,
+            .map(|(source, goal)| {
+                (
+                    *source,
+                    canonical::instantiate_canonical_state(
+                        infcx,
+                        span,
+                        param_env,
+                        &mut orig_values,
+                        *goal,
+                    ),
                 )
             })
             .collect();
@@ -173,7 +175,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
 
         instantiated_goals
             .into_iter()
-            .map(|goal| match goal.predicate.kind().no_bound_vars() {
+            .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
                 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
                     let unconstrained_term = match term.unpack() {
                         ty::TermKind::Ty(_) => infcx
@@ -197,6 +199,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                         self.goal.depth + 1,
                         proof_tree.unwrap(),
                         Some(NormalizesToTermHack { term, unconstrained_term }),
+                        source,
                     )
                 }
                 _ => InspectGoal::new(
@@ -204,6 +207,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                     self.goal.depth + 1,
                     infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
                     None,
+                    source,
                 ),
             })
             .collect()
@@ -229,16 +233,23 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         self.result
     }
 
+    pub fn source(&self) -> GoalSource {
+        self.source
+    }
+
     fn candidates_recur(
         &'a self,
         candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
-        nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
+        nested_goals: &mut Vec<(
+            GoalSource,
+            inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>,
+        )>,
         probe: &inspect::Probe<'tcx>,
     ) {
         let mut shallow_certainty = None;
         for step in &probe.steps {
             match step {
-                &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal),
+                &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
                 inspect::ProbeStep::NestedProbe(ref probe) => {
                     // Nested probes have to prove goals added in their parent
                     // but do not leak them, so we truncate the added goals
@@ -321,6 +332,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         depth: usize,
         root: inspect::GoalEvaluation<'tcx>,
         normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
+        source: GoalSource,
     ) -> Self {
         let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root;
         let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() };
@@ -343,8 +355,17 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             result,
             evaluation_kind: evaluation.kind,
             normalizes_to_term_hack,
+            source,
         }
     }
+
+    pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
+        if self.depth < visitor.config().max_depth {
+            try_visit!(visitor.visit_goal(self));
+        }
+
+        V::Result::output()
+    }
 }
 
 /// The public API to interact with proof trees.
@@ -369,6 +390,6 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> V::Result {
         let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
         let proof_tree = proof_tree.unwrap();
-        visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None))
+        visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc))
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index dab87fffe461e..f886c5886504c 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -389,7 +389,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             pred,
-            [goal.with(tcx, output_is_sized_pred)],
+            [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
         )
     }
 
@@ -473,7 +473,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             pred,
             [goal.with(tcx, output_is_sized_pred)]
                 .into_iter()
-                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
+                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
+                .map(|goal| (GoalSource::ImplWhereBound, goal)),
         )
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index c8cb14abb554d..d2b893d6383bd 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -321,7 +321,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             pred,
-            [goal.with(tcx, output_is_sized_pred)],
+            [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
         )
     }
 
@@ -367,7 +367,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             pred,
             [goal.with(tcx, output_is_sized_pred)]
                 .into_iter()
-                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
+                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
+                .map(|goal| (GoalSource::ImplWhereBound, goal)),
         )
     }
 
diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr
index a5182eb5d9c32..f6c5255a18693 100644
--- a/tests/ui/coherence/occurs-check/opaques.next.stderr
+++ b/tests/ui/coherence/occurs-check/opaques.next.stderr
@@ -11,7 +11,7 @@ error[E0282]: type annotations needed
   --> $DIR/opaques.rs:13:20
    |
 LL |     pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
-   |                    ^ cannot infer type for struct `Container<T, T>`
+   |                    ^ cannot infer type for associated type `<T as Trait<T>>::Assoc`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index 0669999cb82e1..6855e17df9aac 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -2,9 +2,14 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
   --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
+   |                 ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
    |
-   = help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+   = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
+   = note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
+help: consider mutably borrowing here
+   |
+LL |     for item in &mut *things { *item = 0 }
+   |                 ++++
 
 error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
   --> $DIR/issue-20605.rs:6:17
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
index 8a8118dea859b..5be683cd3191b 100644
--- 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
@@ -23,7 +23,20 @@ error[E0283]: type annotations needed
 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: 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 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
    |
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
index ac05dfb2d46f2..562d7ccf9fec0 100644
--- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -1,18 +1,26 @@
-error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/auto-with-drop_tracking_mir.rs:25:13
    |
 LL |     is_send(foo());
-   |     ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
-   |     |
-   |     required by a bound introduced by this call
+   |             ^^^^^ future returned by `foo` is not `Send`
    |
-   = help: the trait `Send` is not implemented for `impl Future<Output = ()>`
+   = help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/auto-with-drop_tracking_mir.rs:16:11
+   |
+LL |     let x = &NotSync;
+   |         - has type `&NotSync` which is not `Send`
+LL |     bar().await;
+   |           ^^^^^ await occurs here, with `x` maybe used later
 note: required by a bound in `is_send`
   --> $DIR/auto-with-drop_tracking_mir.rs:24:24
    |
 LL |     fn is_send(_: impl Send) {}
    |                        ^^^^ required by this bound in `is_send`
+help: consider dereferencing here
+   |
+LL |     is_send(*foo());
+   |             +
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs
index c82c17931194a..17741161b31bc 100644
--- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs
@@ -23,5 +23,5 @@ async fn bar() {}
 fn main() {
     fn is_send(_: impl Send) {}
     is_send(foo());
-    //[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely
+    //[fail]~^ ERROR future cannot be sent between threads safely
 }
diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs
index ccb10bab6c1bc..f8926b24e3fab 100644
--- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs
+++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs
@@ -13,5 +13,5 @@ fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
 
 fn main() {
     foo::<fn() -> str, _>(None, ());
-    //~^ expected a `Fn<_>` closure, found `fn() -> str`
+    //~^ the size for values of type `str` cannot be known at compilation time
 }
diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
index 08047852f203a..b487ceef1d42e 100644
--- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
+++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
@@ -1,10 +1,11 @@
-error[E0277]: expected a `Fn<_>` closure, found `fn() -> str`
+error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/builtin-fn-must-return-sized.rs:15:11
    |
 LL |     foo::<fn() -> str, _>(None, ());
-   |           ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str`
+   |           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Fn<_>` is not implemented for `fn() -> str`
+   = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>`
+   = note: required because it appears within the type `fn() -> str`
 note: required by a bound in `foo`
   --> $DIR/builtin-fn-must-return-sized.rs:10:11
    |
diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr
index 57cba790b5537..6e68646fbe4f4 100644
--- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr
@@ -1,12 +1,12 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>`
+error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
   --> $DIR/coherence-fulfill-overflow.rs:12:1
    |
 LL | impl<T: ?Sized + TwoW> Trait for W<T> {}
    | ------------------------------------- first implementation here
 LL | impl<T: ?Sized + TwoW> Trait for T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
    |
-   = note: overflow evaluating the requirement `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>: TwoW`
+   = note: overflow evaluating the requirement `W<W<W<W<_>>>>: TwoW`
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`)
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
index 8d7d8cee08ae3..df25150c21f8b 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
@@ -1,9 +1,16 @@
-error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+error[E0275]: overflow evaluating the requirement `_: Sized`
   --> $DIR/fixpoint-exponential-growth.rs:33:13
    |
 LL |     impls::<W<_>>();
    |             ^^^^
    |
+note: required for `W<(W<_>, W<_>)>` to implement `Trait`
+  --> $DIR/fixpoint-exponential-growth.rs:23:12
+   |
+LL | impl<T, U> Trait for W<(W<T>, W<U>)>
+   |      -     ^^^^^     ^^^^^^^^^^^^^^^
+   |      |
+   |      unsatisfied trait bound introduced here
 note: required by a bound in `impls`
   --> $DIR/fixpoint-exponential-growth.rs:30:13
    |
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
index 7eea81ce03c66..bc9bb6ce2d79e 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
@@ -61,7 +61,7 @@ where
     // entering the cycle from `A` fails, but would work if we were to use the cache
     // result of `B<X>`.
     impls_trait::<A<X>, _, _, _>();
-    //~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied
+    //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
 }
 
 fn main() {
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
index d4932191791fd..78116ebba8274 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
@@ -1,10 +1,21 @@
-error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
+error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
   --> $DIR/incompleteness-unstable-result.rs:63:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
-   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`
+   |                   ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>`
    |
-   = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
+   = help: the following other types implement trait `IncompleteGuidance<T, V>`:
+             <T as IncompleteGuidance<U, i16>>
+             <T as IncompleteGuidance<U, i8>>
+             <T as IncompleteGuidance<U, u8>>
+note: required for `A<X>` to implement `Trait<_, _, u8>`
+  --> $DIR/incompleteness-unstable-result.rs:32:50
+   |
+LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
+   |                                                  ^^^^^^^^^^^^^^     ^^^^
+LL | where
+LL |     T: IncompleteGuidance<U, V>,
+   |        ------------------------ unsatisfied trait bound introduced here
 note: required by a bound in `impls_trait`
   --> $DIR/incompleteness-unstable-result.rs:51:28
    |
diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr
index 7cedb4d36c98d..86c71ad92ff8a 100644
--- a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr
+++ b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr
@@ -1,21 +1,53 @@
-error[E0275]: overflow evaluating the requirement `(): Trait`
+error[E0275]: overflow evaluating the requirement `(): Inductive`
   --> $DIR/double-cycle-inductive-coinductive.rs:32:19
    |
 LL |     impls_trait::<()>();
    |                   ^^
    |
+note: required for `()` to implement `Trait`
+  --> $DIR/double-cycle-inductive-coinductive.rs:9:34
+   |
+LL | impl<T: Inductive + Coinductive> Trait for T {}
+   |         ---------                ^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `()` to implement `Inductive`
+  --> $DIR/double-cycle-inductive-coinductive.rs:12:16
+   |
+LL | impl<T: Trait> Inductive for T {}
+   |         -----  ^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 7 redundant requirements hidden
+   = note: required for `()` to implement `Trait`
 note: required by a bound in `impls_trait`
   --> $DIR/double-cycle-inductive-coinductive.rs:17:19
    |
 LL | fn impls_trait<T: Trait>() {}
    |                   ^^^^^ required by this bound in `impls_trait`
 
-error[E0275]: overflow evaluating the requirement `(): TraitRev`
+error[E0275]: overflow evaluating the requirement `(): CoinductiveRev`
   --> $DIR/double-cycle-inductive-coinductive.rs:35:23
    |
 LL |     impls_trait_rev::<()>();
    |                       ^^
    |
+note: required for `()` to implement `TraitRev`
+  --> $DIR/double-cycle-inductive-coinductive.rs:21:40
+   |
+LL | impl<T: CoinductiveRev + InductiveRev> TraitRev for T {}
+   |         --------------                 ^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `()` to implement `CoinductiveRev`
+  --> $DIR/double-cycle-inductive-coinductive.rs:27:19
+   |
+LL | impl<T: TraitRev> CoinductiveRev for T {}
+   |         --------  ^^^^^^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 7 redundant requirements hidden
+   = note: required for `()` to implement `TraitRev`
 note: required by a bound in `impls_trait_rev`
   --> $DIR/double-cycle-inductive-coinductive.rs:29:23
    |
diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr
index a2a5c028cf8d5..ea46c0fea97b8 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr
+++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr
@@ -1,9 +1,19 @@
-error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+error[E0275]: overflow evaluating the requirement `W<W<_>>: Trait`
   --> $DIR/inductive-fixpoint-hang.rs:31:19
    |
 LL |     impls_trait::<W<_>>();
    |                   ^^^^
    |
+note: required for `W<W<W<_>>>` to implement `Trait`
+  --> $DIR/inductive-fixpoint-hang.rs:22:17
+   |
+LL | impl<T: ?Sized> Trait for W<W<T>>
+   |                 ^^^^^     ^^^^^^^
+LL | where
+LL |     W<T>: Trait,
+   |           ----- unsatisfied trait bound introduced here
+   = note: 8 redundant requirements hidden
+   = note: required for `W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>` to implement `Trait`
 note: required by a bound in `impls_trait`
   --> $DIR/inductive-fixpoint-hang.rs:28:19
    |
diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs
index 78683372580be..9d0ea51b1b25e 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs
+++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs
@@ -39,7 +39,7 @@ fn impls_ar<T: AR>() {}
 
 fn main() {
     impls_a::<()>();
-    //~^ ERROR overflow evaluating the requirement `(): A`
+    //~^ ERROR overflow evaluating the requirement `(): B`
 
     impls_ar::<()>();
     //~^ ERROR overflow evaluating the requirement `(): AR`
diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr
index e9cc6bc6c81ad..fe02d3c407cab 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr
+++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr
@@ -1,9 +1,25 @@
-error[E0275]: overflow evaluating the requirement `(): A`
+error[E0275]: overflow evaluating the requirement `(): B`
   --> $DIR/inductive-not-on-stack.rs:41:15
    |
 LL |     impls_a::<()>();
    |               ^^
    |
+note: required for `()` to implement `A`
+  --> $DIR/inductive-not-on-stack.rs:21:16
+   |
+LL | impl<T: B + C> A for T {}
+   |         -      ^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `()` to implement `B`
+  --> $DIR/inductive-not-on-stack.rs:22:12
+   |
+LL | impl<T: A> B for T {}
+   |         -  ^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 7 redundant requirements hidden
+   = note: required for `()` to implement `A`
 note: required by a bound in `impls_a`
   --> $DIR/inductive-not-on-stack.rs:25:15
    |
@@ -16,6 +32,29 @@ error[E0275]: overflow evaluating the requirement `(): AR`
 LL |     impls_ar::<()>();
    |                ^^
    |
+note: required for `()` to implement `BR`
+  --> $DIR/inductive-not-on-stack.rs:35:13
+   |
+LL | impl<T: AR> BR for T {}
+   |         --  ^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `()` to implement `CR`
+  --> $DIR/inductive-not-on-stack.rs:36:13
+   |
+LL | impl<T: BR> CR for T {}
+   |         --  ^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required for `()` to implement `AR`
+  --> $DIR/inductive-not-on-stack.rs:34:18
+   |
+LL | impl<T: CR + BR> AR for T {}
+   |         --       ^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 6 redundant requirements hidden
+   = note: required for `()` to implement `AR`
 note: required by a bound in `impls_ar`
   --> $DIR/inductive-not-on-stack.rs:38:16
    |
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs
index 6d75d24186430..b90a354be1b61 100644
--- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs
@@ -35,5 +35,5 @@ fn impls_a<T: A>() {}
 
 fn main() {
     impls_a::<()>();
-    //~^ ERROR overflow evaluating the requirement `(): A`
+    //~^ ERROR overflow evaluating the requirement `(): CInd`
 }
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr
index 17544eb1da528..03e61dbf99c22 100644
--- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr
@@ -1,9 +1,46 @@
-error[E0275]: overflow evaluating the requirement `(): A`
+error[E0275]: overflow evaluating the requirement `(): CInd`
   --> $DIR/mixed-cycles-1.rs:37:15
    |
 LL |     impls_a::<()>();
    |               ^^
    |
+note: required for `()` to implement `B`
+  --> $DIR/mixed-cycles-1.rs:31:28
+   |
+LL | impl<T: ?Sized + CInd + C> B for T {}
+   |                  ----      ^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+note: required for `()` to implement `C`
+  --> $DIR/mixed-cycles-1.rs:32:25
+   |
+LL | impl<T: ?Sized + B + A> C for T {}
+   |                  -      ^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+note: required for `()` to implement `CInd`
+  --> $DIR/mixed-cycles-1.rs:28:21
+   |
+LL | impl<T: ?Sized + C> CInd for T {}
+   |                  -  ^^^^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+   = note: 4 redundant requirements hidden
+   = note: required for `()` to implement `B`
+note: required for `()` to implement `BInd`
+  --> $DIR/mixed-cycles-1.rs:23:21
+   |
+LL | impl<T: ?Sized + B> BInd for T {}
+   |                  -  ^^^^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+note: required for `()` to implement `A`
+  --> $DIR/mixed-cycles-1.rs:30:28
+   |
+LL | impl<T: ?Sized + BInd + C> A for T {}
+   |                  ----      ^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
 note: required by a bound in `impls_a`
   --> $DIR/mixed-cycles-1.rs:34:15
    |
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs
index c939a6e5ef2f7..a3ffcaafb3758 100644
--- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs
@@ -28,5 +28,5 @@ fn impls_a<T: A>() {}
 
 fn main() {
     impls_a::<()>();
-    //~^ ERROR overflow evaluating the requirement `(): A`
+    //~^ ERROR overflow evaluating the requirement `(): BInd`
 }
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr
index a9be1016c7412..892426abe82e6 100644
--- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr
@@ -1,9 +1,32 @@
-error[E0275]: overflow evaluating the requirement `(): A`
+error[E0275]: overflow evaluating the requirement `(): BInd`
   --> $DIR/mixed-cycles-2.rs:30:15
    |
 LL |     impls_a::<()>();
    |               ^^
    |
+note: required for `()` to implement `B`
+  --> $DIR/mixed-cycles-2.rs:25:24
+   |
+LL | impl<T: ?Sized + BInd> B for T {}
+   |                  ----  ^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+note: required for `()` to implement `BInd`
+  --> $DIR/mixed-cycles-2.rs:22:21
+   |
+LL | impl<T: ?Sized + B> BInd for T {}
+   |                  -  ^^^^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
+   = note: 6 redundant requirements hidden
+   = note: required for `()` to implement `BInd`
+note: required for `()` to implement `A`
+  --> $DIR/mixed-cycles-2.rs:24:28
+   |
+LL | impl<T: ?Sized + BInd + B> A for T {}
+   |                  ----      ^     ^
+   |                  |
+   |                  unsatisfied trait bound introduced here
 note: required by a bound in `impls_a`
   --> $DIR/mixed-cycles-2.rs:27:15
    |
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs
index ce7a380f07a6b..d11150ca55ae8 100644
--- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs
+++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs
@@ -25,7 +25,7 @@ fn foo<T: Foo>() {
     //
     //     https://github.com/rust-lang/trait-system-refactor-initiative/issues/76
     require_bar::<T>();
-    //~^ ERROR the trait bound `T: Bar` is not satisfied
+    //~^ ERROR type mismatch resolving `<T as Foo>::Assoc == i32`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
index 2785357e792de..3ef0afa38bff4 100644
--- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
+++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
@@ -1,19 +1,25 @@
-error[E0277]: the trait bound `T: Bar` is not satisfied
+error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
   --> $DIR/param-candidate-shadows-project.rs:27:19
    |
 LL |     require_bar::<T>();
-   |                   ^ the trait `Bar` is not implemented for `T`
+   |                   ^ type mismatch resolving `<T as Foo>::Assoc == i32`
    |
+note: types differ
+  --> $DIR/param-candidate-shadows-project.rs:10:18
+   |
+LL |     type Assoc = i32;
+   |                  ^^^
+note: required for `T` to implement `Bar`
+  --> $DIR/param-candidate-shadows-project.rs:13:9
+   |
+LL | impl<T> Bar for T where T: Foo<Assoc = i32> {}
+   |         ^^^     ^              ----------- unsatisfied trait bound introduced here
 note: required by a bound in `require_bar`
   --> $DIR/param-candidate-shadows-project.rs:15:19
    |
 LL | fn require_bar<T: Bar>() {}
    |                   ^^^ required by this bound in `require_bar`
-help: consider further restricting this bound
-   |
-LL | fn foo<T: Foo + Bar>() {
-   |               +++++
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs
index 511111af83f3d..3d3fdc926f658 100644
--- a/tests/ui/traits/next-solver/more-object-bound.rs
+++ b/tests/ui/traits/next-solver/more-object-bound.rs
@@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
 
 fn transmute<A, B>(x: A) -> B {
     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-    //~^ ERROR the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
+    //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
 }
 
 fn foo<A, B, T: ?Sized>(x: T::A) -> B
diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr
index 1b776d7198ea4..8cc2a51ee2b6c 100644
--- a/tests/ui/traits/next-solver/more-object-bound.stderr
+++ b/tests/ui/traits/next-solver/more-object-bound.stderr
@@ -1,9 +1,10 @@
-error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
+error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
   --> $DIR/more-object-bound.rs:12:5
    |
 LL |     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
    |
+   = note: required because it appears within the type `dyn Trait<A = A, B = B>`
 note: required by a bound in `foo`
   --> $DIR/more-object-bound.rs:18:8
    |
@@ -12,11 +13,7 @@ LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
 LL | where
 LL |     T: Trait<B = B>,
    |        ^^^^^^^^^^^^ required by this bound in `foo`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | fn transmute<A, B>(x: A) -> B where dyn Trait<A = A, B = B>: Trait {
-   |                               ++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
index 40d68dbaffdf0..12ea1bf142ab8 100644
--- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
+++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
@@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {}
 
 fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
     needs_bar::<T>();
-    //~^ ERROR type annotations needed: cannot satisfy `T: Bar`
+    //~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
index dfff9f11b8756..21f3fbfeb872e 100644
--- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
+++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
@@ -1,11 +1,14 @@
-error[E0283]: type annotations needed: cannot satisfy `T: Bar`
+error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
   --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
    |
 LL |     needs_bar::<T>();
-   |                 ^
+   |                 ^ cannot satisfy `<T as Foo>::Assoc == i32`
    |
-   = note: cannot satisfy `T: Bar`
-   = help: the trait `Bar` is implemented for `T`
+note: required for `T` to implement `Bar`
+  --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9
+   |
+LL | impl<T> Bar for T where T: Foo<Assoc = i32> {}
+   |         ^^^     ^              ----------- unsatisfied trait bound introduced here
 note: required by a bound in `needs_bar`
   --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17
    |
@@ -14,4 +17,4 @@ LL | fn needs_bar<T: Bar>() {}
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs
index 4222607b5bfe4..3aa1af4956e22 100644
--- a/tests/ui/traits/next-solver/object-unsafety.rs
+++ b/tests/ui/traits/next-solver/object-unsafety.rs
@@ -11,9 +11,9 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
 pub fn copy_any<T>(t: &T) -> T {
     copy::<dyn Setup<From=T>>(t)
     //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
-    //~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
     //~| ERROR mismatched types
     //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
+    //~| ERROR the trait bound `T: Copy` is not satisfied
 
     // FIXME(-Znext-solver): These error messages are horrible and some of them
     // are even simple fallout from previous error.
diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr
index a9cbb721511ca..7c9a6077fe7fd 100644
--- a/tests/ui/traits/next-solver/object-unsafety.stderr
+++ b/tests/ui/traits/next-solver/object-unsafety.stderr
@@ -1,18 +1,19 @@
-error[E0277]: the trait bound `dyn Setup<From = T>: Setup` is not satisfied
+error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
   --> $DIR/object-unsafety.rs:12:12
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |            ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup<From = T>`
+   |            ^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup`
    |
+   = note: required because it appears within the type `dyn Setup<From = T>`
 note: required by a bound in `copy`
   --> $DIR/object-unsafety.rs:7:12
    |
 LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
    |            ^^^^^ required by this bound in `copy`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+help: consider restricting type parameter `T`
    |
-LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup {
-   |                                ++++++++++++++++++++++++++++++++
+LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
+   |                  +++++++++++++++++++
 
 error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
   --> $DIR/object-unsafety.rs:12:31
diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs
index 186d0e8be56e8..052d803765d3c 100644
--- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs
+++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs
@@ -15,5 +15,5 @@ fn impls<T: Trait>() {}
 
 fn main() {
     impls::<W<_>>();
-    //~^ ERROR overflow evaluating the requirement `W<_>: Trait`
+    //~^ ERROR overflow evaluating the requirement `_: Sized`
 }
diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr
index b032ae3e740db..6583cae8bb9c1 100644
--- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr
+++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr
@@ -1,9 +1,16 @@
-error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+error[E0275]: overflow evaluating the requirement `_: Sized`
   --> $DIR/exponential-trait-goals.rs:17:13
    |
 LL |     impls::<W<_>>();
    |             ^^^^
    |
+note: required for `W<(W<_>, W<_>)>` to implement `Trait`
+  --> $DIR/exponential-trait-goals.rs:7:12
+   |
+LL | impl<T, U> Trait for W<(W<T>, W<U>)>
+   |      -     ^^^^^     ^^^^^^^^^^^^^^^
+   |      |
+   |      unsatisfied trait bound introduced here
 note: required by a bound in `impls`
   --> $DIR/exponential-trait-goals.rs:14:13
    |
diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr
index 67616619384c6..9e467721e83e3 100644
--- a/tests/ui/traits/next-solver/overflow/global-cache.stderr
+++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr
@@ -5,6 +5,15 @@ LL |     impls_trait::<Four<Four<Four<Four<()>>>>>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`)
+note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>` to implement `Trait`
+  --> $DIR/global-cache.rs:12:16
+   |
+LL | impl<T: Trait> Trait for Inc<T> {}
+   |         -----  ^^^^^     ^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: 5 redundant requirements hidden
+   = note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>>>>>>` to implement `Trait`
 note: required by a bound in `impls_trait`
   --> $DIR/global-cache.rs:15:19
    |