diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index ae53f1ac3bb49..392372fad531e 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
         Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
         | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
         | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
-        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl),
+        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
+        | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
+            Some(fn_decl)
+        }
         _ => None,
     }
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index cb99ae19ee72e..0908b6a1763d5 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1722,7 +1722,7 @@ rustc_queries! {
     /// span) for an *existing* error. Therefore, it is best-effort, and may never handle
     /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
     /// because the `ty::Ty`-based wfcheck is always run.
-    query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, hir::HirId)) -> Option<traits::ObligationCause<'tcx>> {
+    query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
         eval_always
         no_hash
         desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index f951e43fbfa35..a4a2e82463757 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -16,7 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Constness;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
@@ -327,17 +327,39 @@ pub enum ObligationCauseCode<'tcx> {
     /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
     OpaqueType,
 
-    /// Well-formed checking. If a `HirId` is provided,
-    /// it is used to perform HIR-based wf checking if an error
-    /// occurs, in order to generate a more precise error message.
+    /// Well-formed checking. If a `WellFormedLoc` is provided,
+    /// then it will be used to eprform HIR-based wf checking
+    /// after an error occurs, in order to generate a more precise error span.
     /// This is purely for diagnostic purposes - it is always
-    /// correct to use `MiscObligation` instead
-    WellFormed(Option<hir::HirId>),
+    /// correct to use `MiscObligation` instead, or to specify
+    /// `WellFormed(None)`
+    WellFormed(Option<WellFormedLoc>),
 
     /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
     MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId),
 }
 
+/// The 'location' at which we try to perform HIR-based wf checking.
+/// This information is used to obtain an `hir::Ty`, which
+/// we can walk in order to obtain precise spans for any
+/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum WellFormedLoc {
+    /// Use the type of the provided definition.
+    Ty(LocalDefId),
+    /// Use the type of the parameter of the provided function.
+    /// We cannot use `hir::Param`, since the function may
+    /// not have a body (e.g. a trait method definition)
+    Param {
+        /// The function to lookup the parameter in
+        function: LocalDefId,
+        /// The index of the parameter to use.
+        /// Parameters are indexed from 0, with the return type
+        /// being the last 'parameter'
+        param_idx: u16,
+    },
+}
+
 impl ObligationCauseCode<'_> {
     // Return the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b84058011066f..4ce49032398bc 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1682,7 +1682,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
-CloneLiftImpls! { for<'tcx> { Constness, } }
+CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
 
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs
index 1993e0a602fa5..0ad360c7d89c3 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_query_impl/src/keys.rs
@@ -1,9 +1,9 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::HirId;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::mir;
+use rustc_middle::traits;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -397,7 +397,7 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
     }
 }
 
-impl<'tcx> Key for (ty::Predicate<'tcx>, HirId) {
+impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
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 5c4aef529e5ac..13a6733fb478a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -242,11 +242,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             SelectionError::Unimplemented => {
                 // If this obligation was generated as a result of well-formed checking, see if we
                 // can get a better error message by performing HIR-based well formed checking.
-                if let ObligationCauseCode::WellFormed(Some(wf_hir_id)) =
+                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code.peel_derives()
                 {
                     if let Some(cause) =
-                        self.tcx.diagnostic_hir_wf_check((obligation.predicate, *wf_hir_id))
+                        self.tcx.diagnostic_hir_wf_check((obligation.predicate, wf_loc.clone()))
                     {
                         obligation.cause = cause;
                         span = obligation.cause.span;
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 4ed07ba358de3..865e4ccc0b63f 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -40,6 +40,7 @@ use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
+    WellFormedLoc,
 };
 
 use std::collections::hash_map::Entry;
@@ -419,13 +420,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         value: T,
-        hir_id: hir::HirId,
+        loc: WellFormedLoc,
     ) -> T
     where
         T: TypeFoldable<'tcx>,
     {
         self.inh.normalize_associated_types_in_with_cause(
-            ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(hir_id))),
+            ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))),
             self.param_env,
             value,
         )
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index b24d63917c1cf..98980c65bc815 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -22,8 +22,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::may_define_opaque_type;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
+use std::convert::TryInto;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -386,7 +387,7 @@ fn check_associated_item(
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
 ) {
-    let code = ObligationCauseCode::WellFormed(Some(item_id));
+    let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner())));
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
@@ -400,7 +401,11 @@ fn check_associated_item(
         match item.kind {
             ty::AssocKind::Const => {
                 let ty = fcx.tcx.type_of(item.def_id);
-                let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id);
+                let ty = fcx.normalize_associated_types_in_wf(
+                    span,
+                    ty,
+                    WellFormedLoc::Ty(item_id.expect_owner()),
+                );
                 fcx.register_wf_obligation(ty.into(), span, code.clone());
             }
             ty::AssocKind::Fn => {
@@ -422,7 +427,11 @@ fn check_associated_item(
                 }
                 if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
-                    let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id);
+                    let ty = fcx.normalize_associated_types_in_wf(
+                        span,
+                        ty,
+                        WellFormedLoc::Ty(item_id.expect_owner()),
+                    );
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
@@ -621,7 +630,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
 
     for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
         let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
-        let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, item_id);
+        let item_ty = fcx.normalize_associated_types_in_wf(
+            ty_span,
+            ty,
+            WellFormedLoc::Ty(item_id.expect_owner()),
+        );
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
@@ -634,7 +647,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         fcx.register_wf_obligation(
             item_ty.into(),
             ty_span,
-            ObligationCauseCode::WellFormed(Some(item_id)),
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))),
         );
         if forbid_unsized {
             fcx.register_bound(
@@ -684,7 +697,9 @@ fn check_impl<'tcx>(
                 fcx.register_wf_obligation(
                     self_ty.into(),
                     ast_self_ty.span,
-                    ObligationCauseCode::WellFormed(Some(item.hir_id())),
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(
+                        item.hir_id().expect_owner(),
+                    ))),
                 );
             }
         }
@@ -901,11 +916,48 @@ fn check_fn_or_method<'fcx, 'tcx>(
     implied_bounds: &mut Vec<Ty<'tcx>>,
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
-    let sig = fcx.normalize_associated_types_in(span, sig);
 
-    for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) {
-        fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::WellFormed(None));
+    // Normalize the input and output types one at a time, using a different
+    // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
+    // on the entire `FnSig`, since this would use the same `WellFormedLoc`
+    // for each type, preventing the HIR wf check from generating
+    // a nice error message.
+    let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
+    inputs_and_output =
+        fcx.tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
+            fcx.normalize_associated_types_in_wf(
+                span,
+                ty,
+                WellFormedLoc::Param {
+                    function: def_id.expect_local(),
+                    // Note that the `param_idx` of the output type is
+                    // one greater than the index of the last input type.
+                    param_idx: i.try_into().unwrap(),
+                },
+            )
+        }));
+    // Manually call `normalize_assocaited_types_in` on the other types
+    // in `FnSig`. This ensures that if the types of these fields
+    // ever change to include projections, we will start normalizing
+    // them automatically.
+    let sig = ty::FnSig {
+        inputs_and_output,
+        c_variadic: fcx.normalize_associated_types_in(span, c_variadic),
+        unsafety: fcx.normalize_associated_types_in(span, unsafety),
+        abi: fcx.normalize_associated_types_in(span, abi),
+    };
+
+    for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
+        fcx.register_wf_obligation(
+            input_ty.into(),
+            ty.span,
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param {
+                function: def_id.expect_local(),
+                param_idx: i.try_into().unwrap(),
+            })),
+        );
     }
+
     implied_bounds.extend(sig.inputs());
 
     fcx.register_wf_obligation(
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs
index a8ec7b79e571f..c1af10f5ce451 100644
--- a/compiler/rustc_typeck/src/hir_wf_check.rs
+++ b/compiler/rustc_typeck/src/hir_wf_check.rs
@@ -3,10 +3,10 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::HirId;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::TraitEngine;
+use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, ToPredicate, TyCtxt};
+use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_trait_selection::traits;
 
 pub fn provide(providers: &mut Providers) {
@@ -17,21 +17,20 @@ pub fn provide(providers: &mut Providers) {
 // need access to `ItemCtxt`
 fn diagnostic_hir_wf_check<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (predicate, hir_id): (ty::Predicate<'tcx>, HirId),
+    (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
 ) -> Option<ObligationCause<'tcx>> {
     let hir = tcx.hir();
-    // HIR wfcheck should only ever happen as part of improving an existing error
-    tcx.sess.delay_span_bug(hir.span(hir_id), "Performed HIR wfcheck without an existing error!");
 
-    // Currently, we only handle WF checking for items (e.g. associated items).
-    // It would be nice to extend this to handle wf checks inside functions.
-    let def_id = match tcx.hir().opt_local_def_id(hir_id) {
-        Some(def_id) => def_id,
-        None => return None,
+    let def_id = match loc {
+        WellFormedLoc::Ty(def_id) => def_id,
+        WellFormedLoc::Param { function, param_idx: _ } => function,
     };
+    let hir_id = HirId::make_owner(def_id);
+
+    // HIR wfcheck should only ever happen as part of improving an existing error
+    tcx.sess
+        .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
 
-    // FIXME - figure out how we want to handle wf-checking for
-    // things inside a function body.
     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
     // To perform HIR-based WF checking, we iterate over all HIR types
@@ -72,7 +71,8 @@ fn diagnostic_hir_wf_check<'tcx>(
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
             self.tcx.infer_ctxt().enter(|infcx| {
                 let mut fulfill = traits::FulfillmentContext::new();
-                let tcx_ty = self.icx.to_ty(ty);
+                let tcx_ty =
+                    self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
                 let cause = traits::ObligationCause::new(
                     ty.span,
                     self.hir_id,
@@ -119,19 +119,66 @@ fn diagnostic_hir_wf_check<'tcx>(
         depth: 0,
     };
 
-    let ty = match tcx.hir().get(hir_id) {
-        hir::Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::TyAlias(ty) => Some(ty),
-            _ => None,
-        },
-        hir::Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Type(_, ty) => ty,
-            _ => None,
+    // Get the starting `hir::Ty` using our `WellFormedLoc`.
+    // We will walk 'into' this type to try to find
+    // a more precise span for our predicate.
+    let ty = match loc {
+        WellFormedLoc::Ty(_) => match hir.get(hir_id) {
+            hir::Node::ImplItem(item) => match item.kind {
+                hir::ImplItemKind::TyAlias(ty) => Some(ty),
+                ref item => bug!("Unexpected ImplItem {:?}", item),
+            },
+            hir::Node::TraitItem(item) => match item.kind {
+                hir::TraitItemKind::Type(_, ty) => ty,
+                ref item => bug!("Unexpected TraitItem {:?}", item),
+            },
+            hir::Node::Item(item) => match item.kind {
+                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty),
+                hir::ItemKind::Impl(ref impl_) => {
+                    assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_);
+                    Some(impl_.self_ty)
+                }
+                ref item => bug!("Unexpected item {:?}", item),
+            },
+            ref node => bug!("Unexpected node {:?}", node),
         },
-        _ => None,
+        WellFormedLoc::Param { function: _, param_idx } => {
+            let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap();
+            // Get return type
+            if param_idx as usize == fn_decl.inputs.len() {
+                match fn_decl.output {
+                    hir::FnRetTy::Return(ty) => Some(ty),
+                    // The unit type `()` is always well-formed
+                    hir::FnRetTy::DefaultReturn(_span) => None,
+                }
+            } else {
+                Some(&fn_decl.inputs[param_idx as usize])
+            }
+        }
     };
     if let Some(ty) = ty {
         visitor.visit_ty(ty);
     }
     visitor.cause
 }
+
+struct EraseAllBoundRegions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+// Higher ranked regions are complicated.
+// To make matters worse, the HIR WF check can instantiate them
+// outside of a `Binder`, due to the way we (ab)use
+// `ItemCtxt::to_ty`. To make things simpler, we just erase all
+// of them, regardless of depth. At worse, this will give
+// us an inaccurate span for an error message, but cannot
+// lead to unsoundess (we call `delay_span_bug` at the start
+// of `diagnostic_hir_wf_check`).
+impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+        if let ty::ReLateBound(..) = r { &ty::ReErased } else { r }
+    }
+}
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
index e8c11a32bf7fd..25e80159b0b18 100644
--- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:8
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
index e3be434698ab9..19500f58aa688 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:8
+  --> $DIR/associated-types-no-suitable-bound.rs:11:21
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `T`
+   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
index 9dc3414e9edf0..0e978f20a6634 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:8
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index c2aed3f9de548..1ec3c05983aef 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:8
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
@@ -10,10 +13,13 @@ LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Ge
    |                                                              ^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:8
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `(T, U)`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
index fb842d968676d..b6ee1ed733c3e 100644
--- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:8
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
index e0e6029252c00..319e6c2c032a0 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-ret.rs:17:15
+  --> $DIR/object-safety-err-ret.rs:17:16
    |
 LL | fn use_dyn(v: &dyn Foo) {
-   |               ^^^^^^^^ `Foo` cannot be made into an object
+   |                ^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `test` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr
index eb68a6298d1ac..cead9776e4abb 100644
--- a/src/test/ui/error-codes/E0038.stderr
+++ b/src/test/ui/error-codes/E0038.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/E0038.rs:5:16
+  --> $DIR/E0038.rs:5:20
    |
 LL | fn call_foo(x: Box<dyn Trait>) {
-   |                ^^^^^^^^^^^^^^ `Trait` cannot be made into an object
+   |                    ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
index 12195bc1071a0..c13c05f146a7e 100644
--- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
+++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39
    |
 LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
-   |                                      ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23
@@ -35,10 +35,10 @@ LL |     fn static_fn() where Self: Sized {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39
    |
 LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
index eb8e101a83d79..8651789688eaa 100644
--- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/gat-in-trait-path.rs:21:13
+  --> $DIR/gat-in-trait-path.rs:21:17
    |
 LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
index 8cc9f2816a166..b4b89ab047363 100644
--- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `X` cannot be made into an object
-  --> $DIR/issue-67510-pass.rs:7:19
+  --> $DIR/issue-67510-pass.rs:7:23
    |
 LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
    |
    = help: consider moving `Y` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr
index a121566bbd884..6429bb8159e1f 100644
--- a/src/test/ui/generic-associated-types/trait-objects.stderr
+++ b/src/test/ui/generic-associated-types/trait-objects.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `StreamingIterator` cannot be made into an object
-  --> $DIR/trait-objects.rs:10:16
+  --> $DIR/trait-objects.rs:10:21
    |
 LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
    |
    = help: consider moving `Item` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr
index 8872f51753c94..0e942e80e2544 100644
--- a/src/test/ui/issues/issue-18611.stderr
+++ b/src/test/ui/issues/issue-18611.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:4
+  --> $DIR/issue-18611.rs:1:18
    |
 LL | fn add_state(op: <isize as HasState>::State) {
-   |    ^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+...
+LL | trait HasState {
+   | -------------- required by this bound in `HasState`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr
index 86b530e85a80a..2a5416ce85ba6 100644
--- a/src/test/ui/issues/issue-18959.stderr
+++ b/src/test/ui/issues/issue-18959.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/issue-18959.rs:11:11
+  --> $DIR/issue-18959.rs:11:12
    |
 LL | fn foo(b: &dyn Bar) {
-   |           ^^^^^^^^ `Bar` cannot be made into an object
+   |            ^^^^^^^ `Bar` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
index 797406f869fe6..f332b7213d8bc 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
+++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:6:11
+  --> $DIR/object-unsafe-trait-references-self.rs:6:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `baz` to another trait
    = help: consider moving `bat` to another trait
@@ -17,10 +17,10 @@ LL |     fn bat(&self) -> Self {}
    |                      ^^^^ ...because method `bat` references the `Self` type in its return type
 
 error[E0038]: the trait `Other` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:10:11
+  --> $DIR/object-unsafe-trait-references-self.rs:10:12
    |
 LL | fn foo(x: &dyn Other) {}
-   |           ^^^^^^^^^^ `Other` cannot be made into an object
+   |            ^^^^^^^^^ `Other` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-references-self.rs:8:14
diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
index a2caf846cc5fe..4c18f6d79d077 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
+++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11
+  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8
diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
index a0eb7d10bd94a..f6b48938f9b04 100644
--- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
+++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:12
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
    |
+LL | pub trait Foo {
+   | ------------- required by this bound in `Foo`
+...
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |            ^^^^^^^ the trait `Foo` is not implemented for `()`
+   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr
index 9687658feba43..ca90e9222dea9 100644
--- a/src/test/ui/wf/wf-in-fn-arg.stderr
+++ b/src/test/ui/wf/wf-in-fn-arg.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-arg.rs:10:14
+  --> $DIR/wf-in-fn-arg.rs:10:15
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL | fn bar<T>(_: &MustBeCopy<T>)
-   |              ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |               ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
index c3d5d2b9669b8..2a129538f7633 100644
--- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-default-fn-arg.rs:11:22
+  --> $DIR/wf-trait-default-fn-arg.rs:11:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>) {
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr
index 4510f50feea58..7693aa6d2d583 100644
--- a/src/test/ui/wf/wf-trait-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-fn-arg.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-fn-arg.rs:10:22
+  --> $DIR/wf-trait-fn-arg.rs:10:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>);
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |