about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-12-13 01:17:09 +0100
committerGitHub <noreply@github.com>2022-12-13 01:17:09 +0100
commit8917cc0f23f97e42e652f9130b7daa6a48193cef (patch)
treea1e2eb311bc21a165bb3612b180035dda68fde22
parent6dbaf86672397081f4b946b18acc37d1a27611d8 (diff)
parentf4ed2d1cca0106eb4aec99b61670ecac378ca087 (diff)
downloadrust-8917cc0f23f97e42e652f9130b7daa6a48193cef.tar.gz
rust-8917cc0f23f97e42e652f9130b7daa6a48193cef.zip
Rollup merge of #105332 - estebank:iterator-chains, r=oli-obk
Point out the type of associated types in every method call of iterator chains

Partially address #105184 by pointing out the type of associated types in every method call of iterator chains:

```
note: the expression is of type `Map<std::slice::Iter<'_, {integer}>, [closure@src/test/ui/iterators/invalid-iterator-chain.rs:12:18: 12:21]>`
    --> src/test/ui/iterators/invalid-iterator-chain.rs:12:14
     |
10   |         vec![0, 1]
     |         ---------- this expression has type `Vec<{integer}>`
11   |             .iter()
     |              ------ associated type `std::iter::Iterator::Item` is `&{integer}` here
12   |             .map(|x| { x; })
     |              ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
```

We also reduce the number of impls we mention when any of the candidates is an "exact match". This benefits the output of cases with numerics greatly.

Outstanding work would be to provide a structured suggestion for appropriate changes, like in this case detecting the spurious `;` in the closure.
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs74
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs401
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-101020.stderr6
-rw-r--r--src/test/ui/issues/issue-20162.stderr6
-rw-r--r--src/test/ui/issues/issue-31173.rs3
-rw-r--r--src/test/ui/issues/issue-31173.stderr32
-rw-r--r--src/test/ui/issues/issue-33941.stderr6
-rw-r--r--src/test/ui/issues/issue-34334.stderr16
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr27
-rw-r--r--src/test/ui/iterators/collect-into-array.rs1
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr6
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs1
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr6
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.rs41
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.stderr176
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches.stderr6
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr12
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr6
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.stderr2
-rw-r--r--src/test/ui/not-clone-closure.stderr6
-rw-r--r--src/test/ui/on-unimplemented/sum.stderr26
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr6
-rw-r--r--src/test/ui/suggestions/issue-71394-no-from-impl.stderr6
-rw-r--r--src/test/ui/traits/issue-97576.stderr6
-rw-r--r--src/test/ui/unsized/issue-71659.stderr6
33 files changed, 744 insertions, 185 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 06bb5edc090..6bc0c261565 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -370,7 +370,11 @@ impl Diagnostic {
         self.set_span(after);
         for span_label in before.span_labels() {
             if let Some(label) = span_label.label {
-                self.span.push_span_label(after, label);
+                if span_label.is_primary {
+                    self.span.push_span_label(after, label);
+                } else {
+                    self.span.push_span_label(span_label.span, label);
+                }
             }
         }
         self
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
new file mode 100644
index 00000000000..cb373d65772
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -0,0 +1,74 @@
+use crate::infer::InferCtxt;
+
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct CollectAllMismatches<'a, 'tcx> {
+    pub infcx: &'a InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub errors: Vec<TypeError<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
+    fn tag(&self) -> &'static str {
+        "CollectAllMismatches"
+    }
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+    fn intercrate(&self) -> bool {
+        false
+    }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+    fn a_is_expected(&self) -> bool {
+        true
+    } // irrelevant
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        _b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        Ok(a)
+    }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
+            return Ok(a);
+        }
+        relate::super_relate_tys(self, a, b).or_else(|e| {
+            self.errors.push(e);
+            Ok(a)
+        })
+    }
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        if a == b {
+            return Ok(a);
+        }
+        relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+    }
+    fn binders<T: Relate<'tcx>>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
+        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 82449a36b1d..30ff07ee6c3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,4 +1,5 @@
 mod ambiguity;
+pub mod method_chain;
 pub mod on_unimplemented;
 pub mod suggestions;
 
@@ -536,7 +537,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             |err| {
                 self.note_obligation_cause_code(
                     err,
-                    &predicate,
+                    predicate,
                     obligation.param_env,
                     obligation.cause.code(),
                     &mut vec![],
@@ -1587,7 +1588,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 {
                     self.note_obligation_cause_code(
                         &mut diag,
-                        &error.obligation.predicate,
+                        error.obligation.predicate,
                         error.obligation.param_env,
                         code,
                         &mut vec![],
@@ -2602,7 +2603,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(
                 err,
-                &obligation.predicate,
+                obligation.predicate,
                 obligation.param_env,
                 obligation.cause.code(),
                 &mut vec![],
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 9f5814a6bda..40c81025471 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,8 +1,9 @@
+// ignore-tidy-filelength
 use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
-use crate::traits::NormalizeExt;
+use crate::traits::{NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
 use hir::HirId;
@@ -22,17 +23,20 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
-    ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
+    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitable, TypeckResults,
 };
-use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use std::fmt;
+use std::ops::Deref;
 
+use super::method_chain::CollectAllMismatches;
 use super::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -292,13 +296,13 @@ pub trait TypeErrCtxtExt<'tcx> {
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>;
+        T: ToPredicate<'tcx>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -329,6 +333,23 @@ pub trait TypeErrCtxtExt<'tcx> {
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    );
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    );
 }
 
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
@@ -2336,7 +2357,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         debug!(?next_code);
         self.note_obligation_cause_code(
             err,
-            &obligation.predicate,
+            obligation.predicate,
             obligation.param_env,
             next_code.unwrap(),
             &mut Vec::new(),
@@ -2347,15 +2368,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>,
+        T: ToPredicate<'tcx>,
     {
         let tcx = self.tcx;
+        let predicate = predicate.to_predicate(tcx);
         match *cause_code {
             ObligationCauseCode::ExprAssignable
             | ObligationCauseCode::MatchExpressionArm { .. }
@@ -2390,12 +2412,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+                err.note(&format!("required so that the projection `{data}` is well-formed"));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
                 err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
+                    "required so that reference `{ref_ty}` does not outlive its referent"
                 ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
@@ -2689,7 +2710,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             &data.parent_code,
                             obligated_types,
@@ -2700,7 +2721,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             cause_code.peel_derives(),
                             obligated_types,
@@ -2809,7 +2830,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2824,7 +2845,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2837,43 +2858,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 call_hir_id,
                 ref parent_code,
             } => {
-                let hir = self.tcx.hir();
-                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
-                    hir.find(arg_hir_id)
-                {
-                    let parent_id = hir.get_parent_item(arg_hir_id);
-                    let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                        Some(t) if t.hir_owner == parent_id => t,
-                        _ => self.tcx.typeck(parent_id.def_id),
-                    };
-                    let expr = expr.peel_blocks();
-                    let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
-                    let span = expr.span;
-                    if Some(span) != err.span.primary_span() {
-                        err.span_label(
-                            span,
-                            if ty.references_error() {
-                                String::new()
-                            } else {
-                                format!("this tail expression is of type `{:?}`", ty)
-                            },
-                        );
-                    }
-                }
-                if let Some(Node::Expr(hir::Expr {
-                    kind:
-                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
-                        | hir::ExprKind::MethodCall(
-                            hir::PathSegment { ident: Ident { span, .. }, .. },
-                            ..,
-                        ),
-                    ..
-                })) = hir.find(call_hir_id)
-                {
-                    if Some(*span) != err.span.primary_span() {
-                        err.span_label(*span, "required by a bound introduced by this call");
-                    }
-                }
+                self.function_argument_obligation(
+                    arg_hir_id,
+                    err,
+                    parent_code,
+                    param_env,
+                    predicate,
+                    call_hir_id,
+                );
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
@@ -2888,9 +2880,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
                 let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
-                    "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
-                     corresponding trait's {kind}",
-                    predicate, item_name,
+                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
+                     `{item_name}` but not on the corresponding trait's {kind}",
                 );
                 let sp = self
                     .tcx
@@ -2900,7 +2891,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let mut assoc_span: MultiSpan = sp.into();
                 assoc_span.push_span_label(
                     sp,
-                    format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
+                    format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
                 );
                 if let Some(ident) = self
                     .tcx
@@ -2919,7 +2910,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 if let Some((expr_ty, expr_span)) = expr_info {
-                    let expr_ty = self.resolve_vars_if_possible(expr_ty);
+                    let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
                     err.span_label(
                         expr_span,
                         format!("return type was inferred to be `{expr_ty}` here"),
@@ -3099,6 +3090,298 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             );
         }
     }
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    ) {
+        let tcx = self.tcx;
+        let hir = tcx.hir();
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
+            let parent_id = hir.get_parent_item(arg_hir_id);
+            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
+                Some(t) if t.hir_owner == parent_id => t,
+                _ => self.tcx.typeck(parent_id.def_id),
+            };
+            if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
+                let expr = expr.peel_blocks();
+                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                let span = expr.span;
+                if Some(span) != err.span.primary_span() {
+                    err.span_label(
+                        span,
+                        if ty.references_error() {
+                            String::new()
+                        } else {
+                            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+                            format!("this tail expression is of type `{ty}`")
+                        },
+                    );
+                }
+            }
+
+            // FIXME: visit the ty to see if there's any closure involved, and if there is,
+            // check whether its evaluated return type is the same as the one corresponding
+            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
+            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
+            let mut type_diffs = vec![];
+
+            if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
+                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+                && let Some(pred) = predicates.predicates.get(*idx)
+                && let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                    _ => Err(()),
+                })
+            {
+                let mut c = CollectAllMismatches {
+                    infcx: self.infcx,
+                    param_env,
+                    errors: vec![],
+                };
+                if let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                    _ => Err(()),
+                }) {
+                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                        type_diffs = c.errors;
+                    }
+                }
+            }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+                && let Some(binding_expr) = local.init
+            {
+                // If the expression we're calling on is a binding, we want to point at the
+                // `let` when talking about the type. Otherwise we'll point at every part
+                // of the method chain with the type.
+                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+            } else {
+                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+            }
+        }
+        let call_node = hir.find(call_hir_id);
+        if let Some(Node::Expr(hir::Expr {
+            kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
+        })) = call_node
+        {
+            if Some(rcvr.span) == err.span.primary_span() {
+                err.replace_span_with(path.ident.span);
+            }
+        }
+        if let Some(Node::Expr(hir::Expr {
+            kind:
+                hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
+            ..
+        })) = hir.find(call_hir_id)
+        {
+            if Some(*span) != err.span.primary_span() {
+                err.span_label(*span, "required by a bound introduced by this call");
+            }
+        }
+    }
+
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        let mut primary_spans = vec![];
+        let mut span_labels = vec![];
+
+        let tcx = self.tcx;
+
+        let mut assocs = vec![];
+        // We still want to point at the different methods even if there hasn't
+        // been a change of assoc type.
+        let mut call_spans = vec![];
+        let mut expr = expr;
+        let mut prev_ty = self.resolve_vars_if_possible(
+            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+        );
+        while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
+            // Point at every method call in the chain with the resulting type.
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            //               ^^^^^^ ^^^^^^^^^^^
+            expr = rcvr_expr;
+            let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
+            call_spans.push(span);
+
+            let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+            for diff in &type_diffs {
+                let Sorts(expected_found) = diff else { continue; };
+                let ty::Projection(proj) = expected_found.expected.kind() else { continue; };
+
+                let origin =
+                    TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+                let trait_def_id = proj.trait_def_id(self.tcx);
+                // Make `Self` be equivalent to the type of the call chain
+                // expression we're looking at now, so that we can tell what
+                // for example `Iterator::Item` is at this point in the chain.
+                let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+                    match param.kind {
+                        ty::GenericParamDefKind::Type { .. } => {
+                            if param.index == 0 {
+                                return prev_ty.into();
+                            }
+                        }
+                        ty::GenericParamDefKind::Lifetime
+                        | ty::GenericParamDefKind::Const { .. } => {}
+                    }
+                    self.var_for_def(span, param)
+                });
+                // This will hold the resolved type of the associated type, if the
+                // current expression implements the trait that associated type is
+                // in. For example, this would be what `Iterator::Item` is here.
+                let ty_var = self.infcx.next_ty_var(origin);
+                // This corresponds to `<ExprTy as Iterator>::Item = _`.
+                let trait_ref = ty::Binder::dummy(ty::PredicateKind::Clause(
+                    ty::Clause::Projection(ty::ProjectionPredicate {
+                        projection_ty: ty::ProjectionTy { substs, item_def_id: proj.item_def_id },
+                        term: ty_var.into(),
+                    }),
+                ));
+                // Add `<ExprTy as Iterator>::Item = _` obligation.
+                ocx.register_obligation(Obligation::misc(
+                    self.tcx,
+                    span,
+                    expr.hir_id,
+                    param_env,
+                    trait_ref,
+                ));
+                if ocx.select_where_possible().is_empty() {
+                    // `ty_var` now holds the type that `Item` is for `ExprTy`.
+                    let ty_var = self.resolve_vars_if_possible(ty_var);
+                    assocs_in_this_method.push(Some((span, (proj.item_def_id, ty_var))));
+                } else {
+                    // `<ExprTy as Iterator>` didn't select, so likely we've
+                    // reached the end of the iterator chain, like the originating
+                    // `Vec<_>`.
+                    // Keep the space consistent for later zipping.
+                    assocs_in_this_method.push(None);
+                }
+            }
+            assocs.push(assocs_in_this_method);
+            prev_ty = self.resolve_vars_if_possible(
+                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+            );
+
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+                && let Some(binding_expr) = local.init
+            {
+                // We've reached the root of the method call chain and it is a
+                // binding. Get the binding creation and try to continue the chain.
+                expr = binding_expr;
+            }
+        }
+        // We want the type before deref coercions, otherwise we talk about `&[_]`
+        // instead of `Vec<_>`.
+        if let Some(ty) = typeck_results.expr_ty_opt(expr) {
+            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+            // Point at the root expression
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            // ^^^^^^^^^^^^^
+            span_labels.push((expr.span, format!("this expression has type `{ty}`")));
+        };
+        // Only show this if it is not a "trivial" expression (not a method
+        // chain) and there are associated types to talk about.
+        let mut assocs = assocs.into_iter().peekable();
+        while let Some(assocs_in_method) = assocs.next() {
+            let Some(prev_assoc_in_method) = assocs.peek() else {
+                for entry in assocs_in_method {
+                    let Some((span, (assoc, ty))) = entry else { continue; };
+                    if type_diffs.iter().any(|diff| {
+                        let Sorts(expected_found) = diff else { return false; };
+                        self.can_eq(param_env, expected_found.found, ty).is_ok()
+                    }) {
+                        // FIXME: this doesn't quite work for `Iterator::collect`
+                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
+                        // to point at the `.into_iter()` call, but as long as we
+                        // still point at the other method calls that might have
+                        // introduced the issue, this is fine for now.
+                        primary_spans.push(span);
+                    }
+                    span_labels.push((
+                        span,
+                        with_forced_trimmed_paths!(format!(
+                            "`{}` is `{ty}` here",
+                            self.tcx.def_path_str(assoc),
+                        )),
+                    ));
+                }
+                break;
+            };
+            for (entry, prev_entry) in
+                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
+            {
+                match (entry, prev_entry) {
+                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
+                        let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
+
+                        let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
+                        if ty != *prev_ty {
+                            if type_diffs.iter().any(|diff| {
+                                let Sorts(expected_found) = diff else { return false; };
+                                self.can_eq(param_env, expected_found.found, ty).is_ok()
+                            }) {
+                                primary_spans.push(span);
+                            }
+                            span_labels
+                                .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
+                        } else {
+                            span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
+                        }
+                    }
+                    (Some((span, (assoc, ty))), None) => {
+                        span_labels.push((
+                            span,
+                            with_forced_trimmed_paths!(format!(
+                                "`{}` is `{}` here",
+                                self.tcx.def_path_str(assoc),
+                                self.ty_to_string(ty),
+                            )),
+                        ));
+                    }
+                    (None, Some(_)) | (None, None) => {}
+                }
+            }
+        }
+        for span in call_spans {
+            if span_labels.iter().find(|(s, _)| *s == span).is_none() {
+                // Ensure we are showing the entire chain, even if the assoc types
+                // haven't changed.
+                span_labels.push((span, String::new()));
+            }
+        }
+        if !primary_spans.is_empty() {
+            let mut multi_span: MultiSpan = primary_spans.into();
+            for (span, label) in span_labels {
+                multi_span.push_span_label(span, label);
+            }
+            err.span_note(
+                multi_span,
+                format!(
+                    "the method call chain might not have had the expected \
+                                     associated types",
+                ),
+            );
+        }
+    }
 }
 
 /// Collect all the returned expressions within the input expression.
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
index 759d79493a9..c7ed8e0de38 100644
--- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
@@ -14,7 +14,7 @@ LL |       let p = Some(45).and_then({
 LL | |
 LL | |         |x| println!("doubling {}", x);
 LL | |         Some(x * 2)
-   | |         ----------- this tail expression is of type `std::option::Option<_>`
+   | |         ----------- this tail expression is of type `Option<_>`
 LL | |
 LL | |     });
    | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
diff --git a/src/test/ui/generic-associated-types/issue-101020.stderr b/src/test/ui/generic-associated-types/issue-101020.stderr
index b4e94cb83f7..422ac548427 100644
--- a/src/test/ui/generic-associated-types/issue-101020.stderr
+++ b/src/test/ui/generic-associated-types/issue-101020.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied
-  --> $DIR/issue-101020.rs:31:5
+  --> $DIR/issue-101020.rs:31:22
    |
 LL |     (&mut EmptyIter).consume(());
-   |     ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
+   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
 note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
   --> $DIR/issue-101020.rs:27:20
diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr
index 3f9b3be9851..d70bf6e1d92 100644
--- a/src/test/ui/issues/issue-20162.stderr
+++ b/src/test/ui/issues/issue-20162.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:5
+  --> $DIR/issue-20162.rs:5:7
    |
 LL |     b.sort();
-   |     ^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `Ord` is not implemented for `X`
+   |       ^^^^ the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs
index 04efa27189b..f678df5b42b 100644
--- a/src/test/ui/issues/issue-31173.rs
+++ b/src/test/ui/issues/issue-31173.rs
@@ -4,12 +4,11 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
-        .cloned()
+        .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index 58d9b564427..62d841f3789 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -1,16 +1,8 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:6:25
-   |
-LL |       let temp: Vec<u8> = it
-   |  _________________________^
-LL | |
-LL | |         .take_while(|&x| {
-LL | |             found_e = true;
-LL | |             false
-LL | |         })
-   | |__________^ expected reference, found `u8`
-LL |           .cloned()
-   |            ------ required by a bound introduced by this call
+error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:11:10
+   |
+LL |         .cloned()
+   |          ^^^^^^ expected reference, found `u8`
    |
    = note: expected reference `&_`
                    found type `u8`
@@ -20,11 +12,11 @@ note: required by a bound in `cloned`
 LL |         Self: Sized + Iterator<Item = &'a T>,
    |                                ^^^^^^^^^^^^ required by this bound in `Iterator::cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
-  --> $DIR/issue-31173.rs:13:10
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-31173.rs:12:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
+   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds
    |
   ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
@@ -37,10 +29,10 @@ LL | pub struct Cloned<I> {
    | -------------------- doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index c28986a2985..73a9b786fe2 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -1,10 +1,8 @@
 error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:14
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
-   |              |
-   |              expected reference, found tuple
+   |                                    ^^^^^^ expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 3188cd80cca..b610e5c1366 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -13,15 +13,23 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:33
+  --> $DIR/issue-34334.rs:5:87
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                                 |
-   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-34334.rs:5:43
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                               ------ this expression has type `Vec<(_, _, _)>`
+...
+LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+   |                                    ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                                    |
+   |                                    `Iterator::Item` is `&(_, _, _)` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
index ce38c3320bb..c6352978613 100644
--- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -1,13 +1,18 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                        |
-   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+LL |     let x2: Vec<f64> = x1.into_iter().collect();
+   |                           ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
@@ -15,15 +20,21 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |              |
-   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+...
+LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
+   |                 ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
index 4c424999b75..99d0d9bd735 100644
--- a/src/test/ui/iterators/collect-into-array.rs
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -3,5 +3,4 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
-    //~| NOTE required by a bound introduced by this call
 }
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
index 544b1da178a..7a07fed1fae 100644
--- a/src/test/ui/iterators/collect-into-array.stderr
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -1,10 +1,8 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:2:31
+  --> $DIR/collect-into-array.rs:2:39
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                               ^^^^^^^ ------- required by a bound introduced by this call
-   |                               |
-   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index 09832c260d0..5a8aacb1a6d 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -13,6 +13,5 @@ fn main() {
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
-    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index 65ef124a463..58da222e039 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -22,12 +22,10 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                ^ required by this bound in `Iterator::collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:6:30
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                              ^^^^^^^ ------- required by a bound introduced by this call
-   |                              |
-   |                              try explicitly collecting into a `Vec<{integer}>`
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs
new file mode 100644
index 00000000000..87116e49245
--- /dev/null
+++ b/src/test/ui/iterators/invalid-iterator-chain.rs
@@ -0,0 +1,41 @@
+fn main() {
+    let scores = vec![(0, 0)]
+        .iter()
+        .map(|(a, b)| {
+            a + b;
+        });
+    println!("{}", scores.sum::<i32>()); //~ ERROR E0277
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .map(|x| x as i64)
+            .filter(|x| *x > 0)
+            .map(|x| { x + 1 })
+            .map(|x| { x; })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .filter(|x| *x > 0.0)
+            .map(|x| { x + 1.0 })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
+    println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
+    let a = vec![0];
+    let b = a.into_iter();
+    let c = b.map(|x| x + 1);
+    let d = c.filter(|x| *x > 10 );
+    let e = d.map(|x| {
+        x + 1;
+    });
+    let f = e.filter(|_| false);
+    let g: Vec<i32> = f.collect(); //~ ERROR E0277
+}
diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr
new file mode 100644
index 00000000000..49651b20fb1
--- /dev/null
+++ b/src/test/ui/iterators/invalid-iterator-chain.stderr
@@ -0,0 +1,176 @@
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:7:27
+   |
+LL |     println!("{}", scores.sum::<i32>());
+   |                           ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:4:10
+   |
+LL |       let scores = vec![(0, 0)]
+   |                    ------------ this expression has type `Vec<({integer}, {integer})>`
+LL |           .iter()
+   |            ------ `Iterator::Item` is `&({integer}, {integer})` here
+LL |           .map(|(a, b)| {
+   |  __________^
+LL | |             a + b;
+LL | |         });
+   | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:18:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:12:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ----------------- `Iterator::Item` changed to `f64` here
+LL |             .map(|x| x as i64)
+   |              ----------------- `Iterator::Item` changed to `i64` here
+LL |             .filter(|x| *x > 0)
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x + 1 })
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x; })
+   |              ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
+  --> $DIR/invalid-iterator-chain.rs:28:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
+   |
+   = help: the trait `Sum<f64>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:24:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
+LL |             .filter(|x| *x > 0.0)
+   |              -------------------- `Iterator::Item` remains `f64` here
+LL |             .map(|x| { x + 1.0 })
+   |              -------------------- `Iterator::Item` remains `f64` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:30:54
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                                                      ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:30:38
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                    ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                    |          |
+   |                    |          `Iterator::Item` is `&{integer}` here
+   |                    this expression has type `Vec<{integer}>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/invalid-iterator-chain.rs:31:40
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                                        ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:31:33
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                    ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |                    |
+   |                    this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
+
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:40:25
+   |
+LL |     let g: Vec<i32> = f.collect();
+   |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:36:15
+   |
+LL |       let a = vec![0];
+   |               ------- this expression has type `Vec<{integer}>`
+LL |       let b = a.into_iter();
+   |                 ----------- `Iterator::Item` is `{integer}` here
+LL |       let c = b.map(|x| x + 1);
+   |                 -------------- `Iterator::Item` remains `{integer}` here
+LL |       let d = c.filter(|x| *x > 10 );
+   |                 -------------------- `Iterator::Item` remains `{integer}` here
+LL |       let e = d.map(|x| {
+   |  _______________^
+LL | |         x + 1;
+LL | |     });
+   | |______^ `Iterator::Item` changed to `()` here
+LL |       let f = e.filter(|_| false);
+   |                 ----------------- `Iterator::Item` remains `()` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
index 5a46027dd52..c66069c4d25 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
@@ -1,10 +1,8 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:9
+  --> $DIR/branches.rs:19:28
    |
 LL |         std::iter::empty().collect()
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
index a4b4968b7d2..a92c3a6809e 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
@@ -1,10 +1,8 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:9
+  --> $DIR/recursion4.rs:10:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
@@ -14,12 +12,10 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:9
+  --> $DIR/recursion4.rs:19:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 36748fae13c..c2515c40b1d 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,10 +1,8 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:5
+  --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
-   |     ^ ------ required by a bound introduced by this call
-   |     |
-   |     `Foo` cannot be formatted using `{:?}`
+   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 6dc039fc35d..2db1cc4b776 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -5,7 +5,7 @@ LL |     foo(panic!())
    |     --- ^^^^^^^^
    |     |   |
    |     |   the trait `T` is not implemented for `()`
-   |     |   this tail expression is of type `_`
+   |     |   this tail expression is of type `()`
    |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index f61ee661bb7..37d94cf0ebd 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -1,13 +1,11 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:17
+  --> $DIR/not-clone-closure.rs:11:23
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                 ^^^^^ ----- required by a bound introduced by this call
-   |                 |
-   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr
index c3103671178..70706541ad6 100644
--- a/src/test/ui/on-unimplemented/sum.stderr
+++ b/src/test/ui/on-unimplemented/sum.stderr
@@ -1,15 +1,20 @@
 error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
-  --> $DIR/sum.rs:4:5
+  --> $DIR/sum.rs:4:25
    |
 LL |     vec![(), ()].iter().sum::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |                         ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:4:18
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::sum`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
@@ -17,17 +22,22 @@ LL |         S: Sum<Self::Item>,
    |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
 
 error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
-  --> $DIR/sum.rs:7:5
+  --> $DIR/sum.rs:7:25
    |
 LL |     vec![(), ()].iter().product::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |                         ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Product<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Product<A>`:
              <i32 as Product<&'a i32>>
              <i32 as Product>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:7:18
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::product`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index c64930db9be..f9d0d1f7875 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:5
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
   --> $DIR/const-default-method-bodies.rs:24:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index 925ae53e324..633b7cc255a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
index 11db0c2b8f2..9e97d3f1137 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index c2c16921c2e..21ecddaffbb 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |         ^^ - required by a bound introduced by this call
-   |         |
-   |         the trait `~const Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
index b52eb2c0332..13fc719f28c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
index b52eb2c0332..13fc719f28c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
index 684db23e135..a5e6f5b5ffc 100644
--- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:20
+  --> $DIR/issue-71394-no-from-impl.rs:3:25
    |
 LL |     let _: &[i8] = data.into();
-   |                    ^^^^ ---- required by a bound introduced by this call
-   |                    |
-   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
diff --git a/src/test/ui/traits/issue-97576.stderr b/src/test/ui/traits/issue-97576.stderr
index 146d38d076a..9062a0fab63 100644
--- a/src/test/ui/traits/issue-97576.stderr
+++ b/src/test/ui/traits/issue-97576.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:18
+  --> $DIR/issue-97576.rs:8:22
    |
 LL |             bar: bar.into(),
-   |                  ^^^ ---- required by a bound introduced by this call
-   |                  |
-   |                  the trait `From<impl ToString>` is not implemented for `String`
+   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr
index 50060e53a49..d7b95f55769 100644
--- a/src/test/ui/unsized/issue-71659.stderr
+++ b/src/test/ui/unsized/issue-71659.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:13
+  --> $DIR/issue-71659.rs:30:15
    |
 LL |     let x = x.cast::<[i32]>();
-   |             ^ ---- required by a bound introduced by this call
-   |             |
-   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15