about summary refs log tree commit diff
path: root/compiler/rustc_infer/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src')
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/mod.rs2221
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs163
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs236
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs127
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs93
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs92
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs496
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs86
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs618
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs162
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs166
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/note.rs421
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs940
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/region.rs1428
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs81
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/suggest.rs899
-rw-r--r--compiler/rustc_infer/src/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs1623
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs183
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs127
-rw-r--r--compiler/rustc_infer/src/infer/need_type_info.rs1298
-rw-r--r--compiler/rustc_infer/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs203
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs1
24 files changed, 46 insertions, 11620 deletions
diff --git a/compiler/rustc_infer/src/error_reporting/infer/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/mod.rs
deleted file mode 100644
index 9998fbca056..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/mod.rs
+++ /dev/null
@@ -1,2221 +0,0 @@
-//! Error Reporting Code for the inference engine
-//!
-//! Because of the way inference, and in particular region inference,
-//! works, it often happens that errors are not detected until far after
-//! the relevant line of code has been type-checked. Therefore, there is
-//! an elaborate system to track why a particular constraint in the
-//! inference graph arose so that we can explain to the user what gave
-//! rise to a particular error.
-//!
-//! The system is based around a set of "origin" types. An "origin" is the
-//! reason that a constraint or inference variable arose. There are
-//! different "origin" enums for different kinds of constraints/variables
-//! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
-//! a span, but also more information so that we can generate a meaningful
-//! error message.
-//!
-//! Having a catalog of all the different reasons an error can arise is
-//! also useful for other reasons, like cross-referencing FAQs etc, though
-//! we are not really taking advantage of this yet.
-//!
-//! # Region Inference
-//!
-//! Region inference is particularly tricky because it always succeeds "in
-//! the moment" and simply registers a constraint. Then, at the end, we
-//! can compute the full graph and report errors, so we need to be able to
-//! store and later report what gave rise to the conflicting constraints.
-//!
-//! # Subtype Trace
-//!
-//! Determining whether `T1 <: T2` often involves a number of subtypes and
-//! subconstraints along the way. A "TypeTrace" is an extended version
-//! of an origin that traces the types and other values that were being
-//! compared. It is not necessarily comprehensive (in fact, at the time of
-//! this writing it only tracks the root values being compared) but I'd
-//! like to extend it to include significant "waypoints". For example, if
-//! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
-//! <: T4` fails, I'd like the trace to include enough information to say
-//! "in the 2nd element of the tuple". Similarly, failures when comparing
-//! arguments or return types in fn types should be able to cite the
-//! specific position, etc.
-//!
-//! # Reality vs plan
-//!
-//! Of course, there is still a LOT of code in typeck that has yet to be
-//! ported to this system, and which relies on string concatenation at the
-//! time of error detection.
-
-use std::borrow::Cow;
-use std::ops::{ControlFlow, Deref};
-use std::path::PathBuf;
-use std::{cmp, fmt, iter};
-
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_errors::{
-    pluralize, Applicability, Diag, DiagCtxtHandle, DiagStyledString, IntoDiagArg, StringPart,
-};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::lang_items::LangItem;
-use rustc_hir::{self as hir};
-use rustc_macros::extension;
-use rustc_middle::bug;
-use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::error::TypeErrorToStringExt;
-use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
-use rustc_middle::ty::{
-    self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt,
-};
-use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
-use rustc_target::spec::abi;
-
-use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
-use crate::infer;
-use crate::infer::relate::{self, RelateResult, TypeRelation};
-use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
-use crate::traits::{
-    IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
-    PredicateObligation,
-};
-
-mod note_and_explain;
-mod suggest;
-
-pub mod region;
-pub mod sub_relations;
-
-pub mod nice_region_error;
-
-/// Makes a valid string literal from a string by escaping special characters (" and \),
-/// unless they are already escaped.
-fn escape_literal(s: &str) -> String {
-    let mut escaped = String::with_capacity(s.len());
-    let mut chrs = s.chars().peekable();
-    while let Some(first) = chrs.next() {
-        match (first, chrs.peek()) {
-            ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
-                escaped.push('\\');
-                escaped.push(delim);
-                chrs.next();
-            }
-            ('"' | '\'', _) => {
-                escaped.push('\\');
-                escaped.push(first)
-            }
-            (c, _) => escaped.push(c),
-        };
-    }
-    escaped
-}
-
-/// A helper for building type related errors. The `typeck_results`
-/// field is only populated during an in-progress typeck.
-/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
-///
-/// You must only create this if you intend to actually emit an error (or
-/// perhaps a warning, though preferably not.) It provides a lot of utility
-/// methods which should not be used during the happy path.
-pub struct TypeErrCtxt<'a, 'tcx> {
-    pub infcx: &'a InferCtxt<'tcx>,
-    pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
-
-    pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
-    pub fallback_has_occurred: bool,
-
-    pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
-
-    pub autoderef_steps:
-        Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
-}
-
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
-        self.infcx.dcx()
-    }
-
-    /// This is just to avoid a potential footgun of accidentally
-    /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
-    #[deprecated(note = "you already have a `TypeErrCtxt`")]
-    #[allow(unused)]
-    pub fn err_ctxt(&self) -> ! {
-        bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
-    }
-}
-
-impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
-    type Target = InferCtxt<'tcx>;
-    fn deref(&self) -> &InferCtxt<'tcx> {
-        self.infcx
-    }
-}
-
-impl<'tcx> InferCtxt<'tcx> {
-    pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-        let (def_id, args) = match *ty.kind() {
-            ty::Alias(_, ty::AliasTy { def_id, args, .. })
-                if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
-            {
-                (def_id, args)
-            }
-            ty::Alias(_, ty::AliasTy { def_id, args, .. })
-                if self.tcx.is_impl_trait_in_trait(def_id) =>
-            {
-                (def_id, args)
-            }
-            _ => return None,
-        };
-
-        let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
-        let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
-
-        self.tcx
-            .explicit_item_super_predicates(def_id)
-            .iter_instantiated_copied(self.tcx, args)
-            .find_map(|(predicate, _)| {
-                predicate
-                    .kind()
-                    .map_bound(|kind| match kind {
-                        ty::ClauseKind::Projection(projection_predicate)
-                            if projection_predicate.projection_term.def_id == item_def_id =>
-                        {
-                            projection_predicate.term.as_type()
-                        }
-                        _ => None,
-                    })
-                    .no_bound_vars()
-                    .flatten()
-            })
-    }
-}
-
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    /// Adds a note if the types come from similarly named crates
-    fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) {
-        use hir::def_id::CrateNum;
-        use rustc_hir::definitions::DisambiguatedDefPathData;
-        use ty::print::Printer;
-        use ty::GenericArg;
-
-        struct AbsolutePathPrinter<'tcx> {
-            tcx: TyCtxt<'tcx>,
-            segments: Vec<String>,
-        }
-
-        impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
-            fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
-                self.tcx
-            }
-
-            fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-
-            fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-
-            fn print_dyn_existential(
-                &mut self,
-                _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-            ) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-
-            fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-
-            fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
-                self.segments = vec![self.tcx.crate_name(cnum).to_string()];
-                Ok(())
-            }
-            fn path_qualified(
-                &mut self,
-                _self_ty: Ty<'tcx>,
-                _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-
-            fn path_append_impl(
-                &mut self,
-                _print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
-                _disambiguated_data: &DisambiguatedDefPathData,
-                _self_ty: Ty<'tcx>,
-                _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<(), PrintError> {
-                Err(fmt::Error)
-            }
-            fn path_append(
-                &mut self,
-                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
-                disambiguated_data: &DisambiguatedDefPathData,
-            ) -> Result<(), PrintError> {
-                print_prefix(self)?;
-                self.segments.push(disambiguated_data.to_string());
-                Ok(())
-            }
-            fn path_generic_args(
-                &mut self,
-                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
-                _args: &[GenericArg<'tcx>],
-            ) -> Result<(), PrintError> {
-                print_prefix(self)
-            }
-        }
-
-        let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId| {
-            // Only report definitions from different crates. If both definitions
-            // are from a local module we could have false positives, e.g.
-            // let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
-            if did1.krate != did2.krate {
-                let abs_path = |def_id| {
-                    let mut printer = AbsolutePathPrinter { tcx: self.tcx, segments: vec![] };
-                    printer.print_def_path(def_id, &[]).map(|_| printer.segments)
-                };
-
-                // We compare strings because DefPath can be different
-                // for imported and non-imported crates
-                let same_path = || -> Result<_, PrintError> {
-                    Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
-                        || abs_path(did1)? == abs_path(did2)?)
-                };
-                if same_path().unwrap_or(false) {
-                    let crate_name = self.tcx.crate_name(did1.krate);
-                    let msg = if did1.is_local() || did2.is_local() {
-                        format!(
-                            "the crate `{crate_name}` is compiled multiple times, possibly with different configurations"
-                        )
-                    } else {
-                        format!(
-                            "perhaps two different versions of crate `{crate_name}` are being used?"
-                        )
-                    };
-                    err.note(msg);
-                }
-            }
-        };
-        match terr {
-            TypeError::Sorts(ref exp_found) => {
-                // if they are both "path types", there's a chance of ambiguity
-                // due to different versions of the same crate
-                if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
-                    (exp_found.expected.kind(), exp_found.found.kind())
-                {
-                    report_path_match(err, exp_adt.did(), found_adt.did());
-                }
-            }
-            TypeError::Traits(ref exp_found) => {
-                report_path_match(err, exp_found.expected, exp_found.found);
-            }
-            _ => (), // FIXME(#22750) handle traits and stuff
-        }
-    }
-
-    fn note_error_origin(
-        &self,
-        err: &mut Diag<'_>,
-        cause: &ObligationCause<'tcx>,
-        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
-        terr: TypeError<'tcx>,
-    ) {
-        match *cause.code() {
-            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
-                let ty = self.resolve_vars_if_possible(root_ty);
-                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
-                {
-                    // don't show type `_`
-                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-                        && let ty::Adt(def, args) = ty.kind()
-                        && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
-                    {
-                        err.span_label(
-                            span,
-                            format!("this is an iterator with items of type `{}`", args.type_at(0)),
-                        );
-                    } else {
-                        err.span_label(span, format!("this expression has type `{ty}`"));
-                    }
-                }
-                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
-                    && ty.is_box()
-                    && ty.boxed_ty() == found
-                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-                {
-                    err.span_suggestion(
-                        span,
-                        "consider dereferencing the boxed value",
-                        format!("*{snippet}"),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
-                err.span_label(span, "expected due to this");
-            }
-            ObligationCauseCode::BlockTailExpression(
-                _,
-                hir::MatchSource::TryDesugar(scrut_hir_id),
-            ) => {
-                if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                    let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
-                    let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
-                        let arg_expr = args.first().expect("try desugaring call w/out arg");
-                        self.typeck_results
-                            .as_ref()
-                            .and_then(|typeck_results| typeck_results.expr_ty_opt(arg_expr))
-                    } else {
-                        bug!("try desugaring w/out call expr as scrutinee");
-                    };
-
-                    match scrut_ty {
-                        Some(ty) if expected == ty => {
-                            let source_map = self.tcx.sess.source_map();
-                            err.span_suggestion(
-                                source_map.end_point(cause.span()),
-                                "try removing this `?`",
-                                "",
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                        _ => {}
-                    }
-                }
-            }
-            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                arm_block_id,
-                arm_span,
-                arm_ty,
-                prior_arm_block_id,
-                prior_arm_span,
-                prior_arm_ty,
-                source,
-                ref prior_non_diverging_arms,
-                scrut_span,
-                ..
-            }) => match source {
-                hir::MatchSource::TryDesugar(scrut_hir_id) => {
-                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
-                        let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
-                            let arg_expr = args.first().expect("try desugaring call w/out arg");
-                            self.typeck_results
-                                .as_ref()
-                                .and_then(|typeck_results| typeck_results.expr_ty_opt(arg_expr))
-                        } else {
-                            bug!("try desugaring w/out call expr as scrutinee");
-                        };
-
-                        match scrut_ty {
-                            Some(ty) if expected == ty => {
-                                let source_map = self.tcx.sess.source_map();
-                                err.span_suggestion(
-                                    source_map.end_point(cause.span()),
-                                    "try removing this `?`",
-                                    "",
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                            _ => {}
-                        }
-                    }
-                }
-                _ => {
-                    // `prior_arm_ty` can be `!`, `expected` will have better info when present.
-                    let t = self.resolve_vars_if_possible(match exp_found {
-                        Some(ty::error::ExpectedFound { expected, .. }) => expected,
-                        _ => prior_arm_ty,
-                    });
-                    let source_map = self.tcx.sess.source_map();
-                    let mut any_multiline_arm = source_map.is_multiline(arm_span);
-                    if prior_non_diverging_arms.len() <= 4 {
-                        for sp in prior_non_diverging_arms {
-                            any_multiline_arm |= source_map.is_multiline(*sp);
-                            err.span_label(*sp, format!("this is found to be of type `{t}`"));
-                        }
-                    } else if let Some(sp) = prior_non_diverging_arms.last() {
-                        any_multiline_arm |= source_map.is_multiline(*sp);
-                        err.span_label(
-                            *sp,
-                            format!("this and all prior arms are found to be of type `{t}`"),
-                        );
-                    }
-                    let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) {
-                        // Cover just `match` and the scrutinee expression, not
-                        // the entire match body, to reduce diagram noise.
-                        cause.span.shrink_to_lo().to(scrut_span)
-                    } else {
-                        cause.span
-                    };
-                    let msg = "`match` arms have incompatible types";
-                    err.span_label(outer, msg);
-                    if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
-                        prior_arm_block_id,
-                        prior_arm_ty,
-                        prior_arm_span,
-                        arm_block_id,
-                        arm_ty,
-                        arm_span,
-                    ) {
-                        err.subdiagnostic(subdiag);
-                    }
-                }
-            },
-            ObligationCauseCode::IfExpression(box IfExpressionCause {
-                then_id,
-                else_id,
-                then_ty,
-                else_ty,
-                outer_span,
-                ..
-            }) => {
-                let then_span = self.find_block_span_from_hir_id(then_id);
-                let else_span = self.find_block_span_from_hir_id(else_id);
-                err.span_label(then_span, "expected because of this");
-                if let Some(sp) = outer_span {
-                    err.span_label(sp, "`if` and `else` have incompatible types");
-                }
-                if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
-                    Some(then_id),
-                    then_ty,
-                    then_span,
-                    Some(else_id),
-                    else_ty,
-                    else_span,
-                ) {
-                    err.subdiagnostic(subdiag);
-                }
-            }
-            ObligationCauseCode::LetElse => {
-                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
-                err.help("...or use `match` instead of `let...else`");
-            }
-            _ => {
-                if let ObligationCauseCode::WhereClause(_, span)
-                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
-                    cause.code().peel_derives()
-                    && !span.is_dummy()
-                    && let TypeError::RegionsPlaceholderMismatch = terr
-                {
-                    err.span_note(*span, "the lifetime requirement is introduced here");
-                }
-            }
-        }
-    }
-
-    /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
-    /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
-    /// populate `other_value` with `other_ty`.
-    ///
-    /// ```text
-    /// Foo<Bar<Qux>>
-    /// ^^^^--------^ this is highlighted
-    /// |   |
-    /// |   this type argument is exactly the same as the other type, not highlighted
-    /// this is highlighted
-    /// Bar<Qux>
-    /// -------- this type is the same as a type argument in the other type, not highlighted
-    /// ```
-    fn highlight_outer(
-        &self,
-        value: &mut DiagStyledString,
-        other_value: &mut DiagStyledString,
-        name: String,
-        sub: ty::GenericArgsRef<'tcx>,
-        pos: usize,
-        other_ty: Ty<'tcx>,
-    ) {
-        // `value` and `other_value` hold two incomplete type representation for display.
-        // `name` is the path of both types being compared. `sub`
-        value.push_highlighted(name);
-        let len = sub.len();
-        if len > 0 {
-            value.push_highlighted("<");
-        }
-
-        // Output the lifetimes for the first type
-        let lifetimes = sub
-            .regions()
-            .map(|lifetime| {
-                let s = lifetime.to_string();
-                if s.is_empty() { "'_".to_string() } else { s }
-            })
-            .collect::<Vec<_>>()
-            .join(", ");
-        if !lifetimes.is_empty() {
-            if sub.regions().count() < len {
-                value.push_normal(lifetimes + ", ");
-            } else {
-                value.push_normal(lifetimes);
-            }
-        }
-
-        // Highlight all the type arguments that aren't at `pos` and compare the type argument at
-        // `pos` and `other_ty`.
-        for (i, type_arg) in sub.types().enumerate() {
-            if i == pos {
-                let values = self.cmp(type_arg, other_ty);
-                value.0.extend((values.0).0);
-                other_value.0.extend((values.1).0);
-            } else {
-                value.push_highlighted(type_arg.to_string());
-            }
-
-            if len > 0 && i != len - 1 {
-                value.push_normal(", ");
-            }
-        }
-        if len > 0 {
-            value.push_highlighted(">");
-        }
-    }
-
-    /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
-    /// as that is the difference to the other type.
-    ///
-    /// For the following code:
-    ///
-    /// ```ignore (illustrative)
-    /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
-    /// ```
-    ///
-    /// The type error output will behave in the following way:
-    ///
-    /// ```text
-    /// Foo<Bar<Qux>>
-    /// ^^^^--------^ this is highlighted
-    /// |   |
-    /// |   this type argument is exactly the same as the other type, not highlighted
-    /// this is highlighted
-    /// Bar<Qux>
-    /// -------- this type is the same as a type argument in the other type, not highlighted
-    /// ```
-    fn cmp_type_arg(
-        &self,
-        t1_out: &mut DiagStyledString,
-        t2_out: &mut DiagStyledString,
-        path: String,
-        sub: &'tcx [ty::GenericArg<'tcx>],
-        other_path: String,
-        other_ty: Ty<'tcx>,
-    ) -> Option<()> {
-        // FIXME/HACK: Go back to `GenericArgsRef` to use its inherent methods,
-        // ideally that shouldn't be necessary.
-        let sub = self.tcx.mk_args(sub);
-        for (i, ta) in sub.types().enumerate() {
-            if ta == other_ty {
-                self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
-                return Some(());
-            }
-            if let ty::Adt(def, _) = ta.kind() {
-                let path_ = self.tcx.def_path_str(def.did());
-                if path_ == other_path {
-                    self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
-                    return Some(());
-                }
-            }
-        }
-        None
-    }
-
-    /// Adds a `,` to the type representation only if it is appropriate.
-    fn push_comma(
-        &self,
-        value: &mut DiagStyledString,
-        other_value: &mut DiagStyledString,
-        len: usize,
-        pos: usize,
-    ) {
-        if len > 0 && pos != len - 1 {
-            value.push_normal(", ");
-            other_value.push_normal(", ");
-        }
-    }
-
-    /// Given two `fn` signatures highlight only sub-parts that are different.
-    fn cmp_fn_sig(
-        &self,
-        sig1: &ty::PolyFnSig<'tcx>,
-        sig2: &ty::PolyFnSig<'tcx>,
-    ) -> (DiagStyledString, DiagStyledString) {
-        let sig1 = &(self.normalize_fn_sig)(*sig1);
-        let sig2 = &(self.normalize_fn_sig)(*sig2);
-
-        let get_lifetimes = |sig| {
-            use rustc_hir::def::Namespace;
-            let (sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
-                .name_all_regions(sig)
-                .unwrap();
-            let lts: Vec<String> =
-                reg.into_items().map(|(_, kind)| kind.to_string()).into_sorted_stable_ord();
-            (if lts.is_empty() { String::new() } else { format!("for<{}> ", lts.join(", ")) }, sig)
-        };
-
-        let (lt1, sig1) = get_lifetimes(sig1);
-        let (lt2, sig2) = get_lifetimes(sig2);
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        let mut values =
-            (DiagStyledString::normal("".to_string()), DiagStyledString::normal("".to_string()));
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        // ^^^^^^
-        values.0.push(sig1.safety.prefix_str(), sig1.safety != sig2.safety);
-        values.1.push(sig2.safety.prefix_str(), sig1.safety != sig2.safety);
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //        ^^^^^^^^^^
-        if sig1.abi != abi::Abi::Rust {
-            values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi);
-        }
-        if sig2.abi != abi::Abi::Rust {
-            values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi);
-        }
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //                   ^^^^^^^^
-        let lifetime_diff = lt1 != lt2;
-        values.0.push(lt1, lifetime_diff);
-        values.1.push(lt2, lifetime_diff);
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //                           ^^^
-        values.0.push_normal("fn(");
-        values.1.push_normal("fn(");
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //                              ^^^^^
-        let len1 = sig1.inputs().len();
-        let len2 = sig2.inputs().len();
-        if len1 == len2 {
-            for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() {
-                let (x1, x2) = self.cmp(*l, *r);
-                (values.0).0.extend(x1.0);
-                (values.1).0.extend(x2.0);
-                self.push_comma(&mut values.0, &mut values.1, len1, i);
-            }
-        } else {
-            for (i, l) in sig1.inputs().iter().enumerate() {
-                values.0.push_highlighted(l.to_string());
-                if i != len1 - 1 {
-                    values.0.push_highlighted(", ");
-                }
-            }
-            for (i, r) in sig2.inputs().iter().enumerate() {
-                values.1.push_highlighted(r.to_string());
-                if i != len2 - 1 {
-                    values.1.push_highlighted(", ");
-                }
-            }
-        }
-
-        if sig1.c_variadic {
-            if len1 > 0 {
-                values.0.push_normal(", ");
-            }
-            values.0.push("...", !sig2.c_variadic);
-        }
-        if sig2.c_variadic {
-            if len2 > 0 {
-                values.1.push_normal(", ");
-            }
-            values.1.push("...", !sig1.c_variadic);
-        }
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //                                   ^
-        values.0.push_normal(")");
-        values.1.push_normal(")");
-
-        // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
-        //                                     ^^^^^^^^
-        let output1 = sig1.output();
-        let output2 = sig2.output();
-        let (x1, x2) = self.cmp(output1, output2);
-        let output_diff = x1 != x2;
-        if !output1.is_unit() || output_diff {
-            values.0.push_normal(" -> ");
-            (values.0).0.extend(x1.0);
-        }
-        if !output2.is_unit() || output_diff {
-            values.1.push_normal(" -> ");
-            (values.1).0.extend(x2.0);
-        }
-
-        values
-    }
-
-    /// Compares two given types, eliding parts that are the same between them and highlighting
-    /// relevant differences, and return two representation of those types for highlighted printing.
-    pub fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagStyledString, DiagStyledString) {
-        debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
-
-        // helper functions
-        let recurse = |t1, t2, values: &mut (DiagStyledString, DiagStyledString)| {
-            let (x1, x2) = self.cmp(t1, t2);
-            (values.0).0.extend(x1.0);
-            (values.1).0.extend(x2.0);
-        };
-
-        fn fmt_region<'tcx>(region: ty::Region<'tcx>) -> String {
-            let mut r = region.to_string();
-            if r == "'_" {
-                r.clear();
-            } else {
-                r.push(' ');
-            }
-            format!("&{r}")
-        }
-
-        fn push_ref<'tcx>(
-            region: ty::Region<'tcx>,
-            mutbl: hir::Mutability,
-            s: &mut DiagStyledString,
-        ) {
-            s.push_highlighted(fmt_region(region));
-            s.push_highlighted(mutbl.prefix_str());
-        }
-
-        fn maybe_highlight<T: Eq + ToString>(
-            t1: T,
-            t2: T,
-            (buf1, buf2): &mut (DiagStyledString, DiagStyledString),
-            tcx: TyCtxt<'_>,
-        ) {
-            let highlight = t1 != t2;
-            let (t1, t2) = if highlight || tcx.sess.opts.verbose {
-                (t1.to_string(), t2.to_string())
-            } else {
-                // The two types are the same, elide and don't highlight.
-                ("_".into(), "_".into())
-            };
-            buf1.push(t1, highlight);
-            buf2.push(t2, highlight);
-        }
-
-        fn cmp_ty_refs<'tcx>(
-            r1: ty::Region<'tcx>,
-            mut1: hir::Mutability,
-            r2: ty::Region<'tcx>,
-            mut2: hir::Mutability,
-            ss: &mut (DiagStyledString, DiagStyledString),
-        ) {
-            let (r1, r2) = (fmt_region(r1), fmt_region(r2));
-            if r1 != r2 {
-                ss.0.push_highlighted(r1);
-                ss.1.push_highlighted(r2);
-            } else {
-                ss.0.push_normal(r1);
-                ss.1.push_normal(r2);
-            }
-
-            if mut1 != mut2 {
-                ss.0.push_highlighted(mut1.prefix_str());
-                ss.1.push_highlighted(mut2.prefix_str());
-            } else {
-                ss.0.push_normal(mut1.prefix_str());
-                ss.1.push_normal(mut2.prefix_str());
-            }
-        }
-
-        // process starts here
-        match (t1.kind(), t2.kind()) {
-            (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
-                let did1 = def1.did();
-                let did2 = def2.did();
-
-                let generics1 = self.tcx.generics_of(did1);
-                let generics2 = self.tcx.generics_of(did2);
-
-                let non_default_after_default = generics1
-                    .check_concrete_type_after_default(self.tcx, sub1)
-                    || generics2.check_concrete_type_after_default(self.tcx, sub2);
-                let sub_no_defaults_1 = if non_default_after_default {
-                    generics1.own_args(sub1)
-                } else {
-                    generics1.own_args_no_defaults(self.tcx, sub1)
-                };
-                let sub_no_defaults_2 = if non_default_after_default {
-                    generics2.own_args(sub2)
-                } else {
-                    generics2.own_args_no_defaults(self.tcx, sub2)
-                };
-                let mut values = (DiagStyledString::new(), DiagStyledString::new());
-                let path1 = self.tcx.def_path_str(did1);
-                let path2 = self.tcx.def_path_str(did2);
-                if did1 == did2 {
-                    // Easy case. Replace same types with `_` to shorten the output and highlight
-                    // the differing ones.
-                    //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
-                    //     Foo<Bar, _>
-                    //     Foo<Quz, _>
-                    //         ---  ^ type argument elided
-                    //         |
-                    //         highlighted in output
-                    values.0.push_normal(path1);
-                    values.1.push_normal(path2);
-
-                    // Avoid printing out default generic parameters that are common to both
-                    // types.
-                    let len1 = sub_no_defaults_1.len();
-                    let len2 = sub_no_defaults_2.len();
-                    let common_len = cmp::min(len1, len2);
-                    let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
-                    let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
-                    let common_default_params =
-                        iter::zip(remainder1.iter().rev(), remainder2.iter().rev())
-                            .filter(|(a, b)| a == b)
-                            .count();
-                    let len = sub1.len() - common_default_params;
-                    let consts_offset = len - sub1.consts().count();
-
-                    // Only draw `<...>` if there are lifetime/type arguments.
-                    if len > 0 {
-                        values.0.push_normal("<");
-                        values.1.push_normal("<");
-                    }
-
-                    fn lifetime_display(lifetime: Region<'_>) -> String {
-                        let s = lifetime.to_string();
-                        if s.is_empty() { "'_".to_string() } else { s }
-                    }
-                    // At one point we'd like to elide all lifetimes here, they are irrelevant for
-                    // all diagnostics that use this output
-                    //
-                    //     Foo<'x, '_, Bar>
-                    //     Foo<'y, '_, Qux>
-                    //         ^^  ^^  --- type arguments are not elided
-                    //         |   |
-                    //         |   elided as they were the same
-                    //         not elided, they were different, but irrelevant
-                    //
-                    // For bound lifetimes, keep the names of the lifetimes,
-                    // even if they are the same so that it's clear what's happening
-                    // if we have something like
-                    //
-                    // for<'r, 's> fn(Inv<'r>, Inv<'s>)
-                    // for<'r> fn(Inv<'r>, Inv<'r>)
-                    let lifetimes = sub1.regions().zip(sub2.regions());
-                    for (i, lifetimes) in lifetimes.enumerate() {
-                        let l1 = lifetime_display(lifetimes.0);
-                        let l2 = lifetime_display(lifetimes.1);
-                        if lifetimes.0 != lifetimes.1 {
-                            values.0.push_highlighted(l1);
-                            values.1.push_highlighted(l2);
-                        } else if lifetimes.0.is_bound() || self.tcx.sess.opts.verbose {
-                            values.0.push_normal(l1);
-                            values.1.push_normal(l2);
-                        } else {
-                            values.0.push_normal("'_");
-                            values.1.push_normal("'_");
-                        }
-                        self.push_comma(&mut values.0, &mut values.1, len, i);
-                    }
-
-                    // We're comparing two types with the same path, so we compare the type
-                    // arguments for both. If they are the same, do not highlight and elide from the
-                    // output.
-                    //     Foo<_, Bar>
-                    //     Foo<_, Qux>
-                    //         ^ elided type as this type argument was the same in both sides
-                    let type_arguments = sub1.types().zip(sub2.types());
-                    let regions_len = sub1.regions().count();
-                    let num_display_types = consts_offset - regions_len;
-                    for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
-                        let i = i + regions_len;
-                        if ta1 == ta2 && !self.tcx.sess.opts.verbose {
-                            values.0.push_normal("_");
-                            values.1.push_normal("_");
-                        } else {
-                            recurse(ta1, ta2, &mut values);
-                        }
-                        self.push_comma(&mut values.0, &mut values.1, len, i);
-                    }
-
-                    // Do the same for const arguments, if they are equal, do not highlight and
-                    // elide them from the output.
-                    let const_arguments = sub1.consts().zip(sub2.consts());
-                    for (i, (ca1, ca2)) in const_arguments.enumerate() {
-                        let i = i + consts_offset;
-                        maybe_highlight(ca1, ca2, &mut values, self.tcx);
-                        self.push_comma(&mut values.0, &mut values.1, len, i);
-                    }
-
-                    // Close the type argument bracket.
-                    // Only draw `<...>` if there are lifetime/type arguments.
-                    if len > 0 {
-                        values.0.push_normal(">");
-                        values.1.push_normal(">");
-                    }
-                    values
-                } else {
-                    // Check for case:
-                    //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
-                    //     Foo<Bar<Qux>
-                    //         ------- this type argument is exactly the same as the other type
-                    //     Bar<Qux>
-                    if self
-                        .cmp_type_arg(
-                            &mut values.0,
-                            &mut values.1,
-                            path1.clone(),
-                            sub_no_defaults_1,
-                            path2.clone(),
-                            t2,
-                        )
-                        .is_some()
-                    {
-                        return values;
-                    }
-                    // Check for case:
-                    //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
-                    //     Bar<Qux>
-                    //     Foo<Bar<Qux>>
-                    //         ------- this type argument is exactly the same as the other type
-                    if self
-                        .cmp_type_arg(
-                            &mut values.1,
-                            &mut values.0,
-                            path2,
-                            sub_no_defaults_2,
-                            path1,
-                            t1,
-                        )
-                        .is_some()
-                    {
-                        return values;
-                    }
-
-                    // We can't find anything in common, highlight relevant part of type path.
-                    //     let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>();
-                    //     foo::bar::Baz<Qux>
-                    //     foo::bar::Bar<Zar>
-                    //               -------- this part of the path is different
-
-                    let t1_str = t1.to_string();
-                    let t2_str = t2.to_string();
-                    let min_len = t1_str.len().min(t2_str.len());
-
-                    const SEPARATOR: &str = "::";
-                    let separator_len = SEPARATOR.len();
-                    let split_idx: usize =
-                        iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR))
-                            .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
-                            .map(|(mod_str, _)| mod_str.len() + separator_len)
-                            .sum();
-
-                    debug!(?separator_len, ?split_idx, ?min_len, "cmp");
-
-                    if split_idx >= min_len {
-                        // paths are identical, highlight everything
-                        (
-                            DiagStyledString::highlighted(t1_str),
-                            DiagStyledString::highlighted(t2_str),
-                        )
-                    } else {
-                        let (common, uniq1) = t1_str.split_at(split_idx);
-                        let (_, uniq2) = t2_str.split_at(split_idx);
-                        debug!(?common, ?uniq1, ?uniq2, "cmp");
-
-                        values.0.push_normal(common);
-                        values.0.push_highlighted(uniq1);
-                        values.1.push_normal(common);
-                        values.1.push_highlighted(uniq2);
-
-                        values
-                    }
-                }
-            }
-
-            // When finding `&T != &T`, compare the references, then recurse into pointee type
-            (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2)) => {
-                let mut values = (DiagStyledString::new(), DiagStyledString::new());
-                cmp_ty_refs(r1, mutbl1, r2, mutbl2, &mut values);
-                recurse(ref_ty1, ref_ty2, &mut values);
-                values
-            }
-            // When finding T != &T, highlight the borrow
-            (&ty::Ref(r1, ref_ty1, mutbl1), _) => {
-                let mut values = (DiagStyledString::new(), DiagStyledString::new());
-                push_ref(r1, mutbl1, &mut values.0);
-                recurse(ref_ty1, t2, &mut values);
-                values
-            }
-            (_, &ty::Ref(r2, ref_ty2, mutbl2)) => {
-                let mut values = (DiagStyledString::new(), DiagStyledString::new());
-                push_ref(r2, mutbl2, &mut values.1);
-                recurse(t1, ref_ty2, &mut values);
-                values
-            }
-
-            // When encountering tuples of the same size, highlight only the differing types
-            (&ty::Tuple(args1), &ty::Tuple(args2)) if args1.len() == args2.len() => {
-                let mut values = (DiagStyledString::normal("("), DiagStyledString::normal("("));
-                let len = args1.len();
-                for (i, (left, right)) in args1.iter().zip(args2).enumerate() {
-                    recurse(left, right, &mut values);
-                    self.push_comma(&mut values.0, &mut values.1, len, i);
-                }
-                if len == 1 {
-                    // Keep the output for single element tuples as `(ty,)`.
-                    values.0.push_normal(",");
-                    values.1.push_normal(",");
-                }
-                values.0.push_normal(")");
-                values.1.push_normal(")");
-                values
-            }
-
-            (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
-                let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1);
-                let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2);
-                let mut values = self.cmp_fn_sig(&sig1, &sig2);
-                let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_args(*did1, args1));
-                let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2));
-                let same_path = path1 == path2;
-                values.0.push(path1, !same_path);
-                values.1.push(path2, !same_path);
-                values
-            }
-
-            (ty::FnDef(did1, args1), ty::FnPtr(sig2)) => {
-                let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1);
-                let mut values = self.cmp_fn_sig(&sig1, sig2);
-                values.0.push_highlighted(format!(
-                    " {{{}}}",
-                    self.tcx.def_path_str_with_args(*did1, args1)
-                ));
-                values
-            }
-
-            (ty::FnPtr(sig1), ty::FnDef(did2, args2)) => {
-                let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2);
-                let mut values = self.cmp_fn_sig(sig1, &sig2);
-                values
-                    .1
-                    .push_normal(format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2)));
-                values
-            }
-
-            (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
-
-            _ => {
-                let mut strs = (DiagStyledString::new(), DiagStyledString::new());
-                maybe_highlight(t1, t2, &mut strs, self.tcx);
-                strs
-            }
-        }
-    }
-
-    /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and
-    /// the return type of `async fn`s.
-    ///
-    /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`.
-    ///
-    /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using
-    /// the message in `secondary_span` as the primary label, and apply the message that would
-    /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
-    /// E0271, like `tests/ui/issues/issue-39970.stderr`.
-    #[instrument(
-        level = "debug",
-        skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label)
-    )]
-    pub fn note_type_err(
-        &self,
-        diag: &mut Diag<'_>,
-        cause: &ObligationCause<'tcx>,
-        secondary_span: Option<(Span, Cow<'static, str>)>,
-        mut values: Option<ValuePairs<'tcx>>,
-        terr: TypeError<'tcx>,
-        swap_secondary_and_primary: bool,
-        prefer_label: bool,
-    ) {
-        let span = cause.span();
-
-        // For some types of errors, expected-found does not make
-        // sense, so just ignore the values we were given.
-        if let TypeError::CyclicTy(_) = terr {
-            values = None;
-        }
-        struct OpaqueTypesVisitor<'tcx> {
-            types: FxIndexMap<TyCategory, FxIndexSet<Span>>,
-            expected: FxIndexMap<TyCategory, FxIndexSet<Span>>,
-            found: FxIndexMap<TyCategory, FxIndexSet<Span>>,
-            ignore_span: Span,
-            tcx: TyCtxt<'tcx>,
-        }
-
-        impl<'tcx> OpaqueTypesVisitor<'tcx> {
-            fn visit_expected_found(
-                tcx: TyCtxt<'tcx>,
-                expected: impl TypeVisitable<TyCtxt<'tcx>>,
-                found: impl TypeVisitable<TyCtxt<'tcx>>,
-                ignore_span: Span,
-            ) -> Self {
-                let mut types_visitor = OpaqueTypesVisitor {
-                    types: Default::default(),
-                    expected: Default::default(),
-                    found: Default::default(),
-                    ignore_span,
-                    tcx,
-                };
-                // The visitor puts all the relevant encountered types in `self.types`, but in
-                // here we want to visit two separate types with no relation to each other, so we
-                // move the results from `types` to `expected` or `found` as appropriate.
-                expected.visit_with(&mut types_visitor);
-                std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
-                found.visit_with(&mut types_visitor);
-                std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
-                types_visitor
-            }
-
-            fn report(&self, err: &mut Diag<'_>) {
-                self.add_labels_for_types(err, "expected", &self.expected);
-                self.add_labels_for_types(err, "found", &self.found);
-            }
-
-            fn add_labels_for_types(
-                &self,
-                err: &mut Diag<'_>,
-                target: &str,
-                types: &FxIndexMap<TyCategory, FxIndexSet<Span>>,
-            ) {
-                for (kind, values) in types.iter() {
-                    let count = values.len();
-                    for &sp in values {
-                        err.span_label(
-                            sp,
-                            format!(
-                                "{}{} {:#}{}",
-                                if count == 1 { "the " } else { "one of the " },
-                                target,
-                                kind,
-                                pluralize!(count),
-                            ),
-                        );
-                    }
-                }
-            }
-        }
-
-        impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> {
-            fn visit_ty(&mut self, t: Ty<'tcx>) {
-                if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
-                    let span = self.tcx.def_span(def_id);
-                    // Avoid cluttering the output when the "found" and error span overlap:
-                    //
-                    // error[E0308]: mismatched types
-                    //   --> $DIR/issue-20862.rs:2:5
-                    //    |
-                    // LL |     |y| x + y
-                    //    |     ^^^^^^^^^
-                    //    |     |
-                    //    |     the found closure
-                    //    |     expected `()`, found closure
-                    //    |
-                    //    = note: expected unit type `()`
-                    //                 found closure `{closure@$DIR/issue-20862.rs:2:5: 2:14 x:_}`
-                    //
-                    // Also ignore opaque `Future`s that come from async fns.
-                    if !self.ignore_span.overlaps(span)
-                        && !span.is_desugaring(DesugaringKind::Async)
-                    {
-                        self.types.entry(kind).or_default().insert(span);
-                    }
-                }
-                t.super_visit_with(self)
-            }
-        }
-
-        debug!("note_type_err(diag={:?})", diag);
-        enum Mismatch<'a> {
-            Variable(ty::error::ExpectedFound<Ty<'a>>),
-            Fixed(&'static str),
-        }
-        let (expected_found, exp_found, is_simple_error, values) = match values {
-            None => (None, Mismatch::Fixed("type"), false, None),
-            Some(values) => {
-                let values = self.resolve_vars_if_possible(values);
-                let (is_simple_error, exp_found) = match values {
-                    ValuePairs::Terms(ExpectedFound { expected, found }) => {
-                        match (expected.unpack(), found.unpack()) {
-                            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
-                                let is_simple_err = expected.is_simple_text(self.tcx)
-                                    && found.is_simple_text(self.tcx);
-                                OpaqueTypesVisitor::visit_expected_found(
-                                    self.tcx, expected, found, span,
-                                )
-                                .report(diag);
-
-                                (
-                                    is_simple_err,
-                                    Mismatch::Variable(ExpectedFound { expected, found }),
-                                )
-                            }
-                            (ty::TermKind::Const(_), ty::TermKind::Const(_)) => {
-                                (false, Mismatch::Fixed("constant"))
-                            }
-                            _ => (false, Mismatch::Fixed("type")),
-                        }
-                    }
-                    ValuePairs::PolySigs(ExpectedFound { expected, found }) => {
-                        OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span)
-                            .report(diag);
-                        (false, Mismatch::Fixed("signature"))
-                    }
-                    ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
-                    ValuePairs::Aliases(ExpectedFound { expected, .. }) => {
-                        (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id)))
-                    }
-                    ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
-                    ValuePairs::ExistentialTraitRef(_) => {
-                        (false, Mismatch::Fixed("existential trait ref"))
-                    }
-                    ValuePairs::ExistentialProjection(_) => {
-                        (false, Mismatch::Fixed("existential projection"))
-                    }
-                    ValuePairs::Dummy => {
-                        bug!("do not expect to report a type error from a ValuePairs::Dummy")
-                    }
-                };
-                let Some(vals) = self.values_str(values) else {
-                    // Derived error. Cancel the emitter.
-                    // NOTE(eddyb) this was `.cancel()`, but `diag`
-                    // is borrowed, so we can't fully defuse it.
-                    diag.downgrade_to_delayed_bug();
-                    return;
-                };
-                (Some(vals), exp_found, is_simple_error, Some(values))
-            }
-        };
-
-        let mut label_or_note = |span: Span, msg: Cow<'static, str>| {
-            if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
-                diag.span_label(span, msg);
-            } else {
-                diag.span_note(span, msg);
-            }
-        };
-        if let Some((sp, msg)) = secondary_span {
-            if swap_secondary_and_primary {
-                let terr = if let Some(infer::ValuePairs::Terms(ExpectedFound {
-                    expected, ..
-                })) = values
-                {
-                    Cow::from(format!("expected this to be `{expected}`"))
-                } else {
-                    terr.to_string(self.tcx)
-                };
-                label_or_note(sp, terr);
-                label_or_note(span, msg);
-            } else {
-                label_or_note(span, terr.to_string(self.tcx));
-                label_or_note(sp, msg);
-            }
-        } else {
-            if let Some(values) = values
-                && let Some((e, f)) = values.ty()
-                && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
-            {
-                let e = self.tcx.erase_regions(e);
-                let f = self.tcx.erase_regions(f);
-                let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
-                let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
-                if expected == found {
-                    label_or_note(span, terr.to_string(self.tcx));
-                } else {
-                    label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
-                }
-            } else {
-                label_or_note(span, terr.to_string(self.tcx));
-            }
-        }
-
-        if let Some((expected, found, path)) = expected_found {
-            let (expected_label, found_label, exp_found) = match exp_found {
-                Mismatch::Variable(ef) => (
-                    ef.expected.prefix_string(self.tcx),
-                    ef.found.prefix_string(self.tcx),
-                    Some(ef),
-                ),
-                Mismatch::Fixed(s) => (s.into(), s.into(), None),
-            };
-
-            enum Similar<'tcx> {
-                Adts { expected: ty::AdtDef<'tcx>, found: ty::AdtDef<'tcx> },
-                PrimitiveFound { expected: ty::AdtDef<'tcx>, found: Ty<'tcx> },
-                PrimitiveExpected { expected: Ty<'tcx>, found: ty::AdtDef<'tcx> },
-            }
-
-            let similarity = |ExpectedFound { expected, found }: ExpectedFound<Ty<'tcx>>| {
-                if let ty::Adt(expected, _) = expected.kind()
-                    && let Some(primitive) = found.primitive_symbol()
-                {
-                    let path = self.tcx.def_path(expected.did()).data;
-                    let name = path.last().unwrap().data.get_opt_name();
-                    if name == Some(primitive) {
-                        return Some(Similar::PrimitiveFound { expected: *expected, found });
-                    }
-                } else if let Some(primitive) = expected.primitive_symbol()
-                    && let ty::Adt(found, _) = found.kind()
-                {
-                    let path = self.tcx.def_path(found.did()).data;
-                    let name = path.last().unwrap().data.get_opt_name();
-                    if name == Some(primitive) {
-                        return Some(Similar::PrimitiveExpected { expected, found: *found });
-                    }
-                } else if let ty::Adt(expected, _) = expected.kind()
-                    && let ty::Adt(found, _) = found.kind()
-                {
-                    if !expected.did().is_local() && expected.did().krate == found.did().krate {
-                        // Most likely types from different versions of the same crate
-                        // are in play, in which case this message isn't so helpful.
-                        // A "perhaps two different versions..." error is already emitted for that.
-                        return None;
-                    }
-                    let f_path = self.tcx.def_path(found.did()).data;
-                    let e_path = self.tcx.def_path(expected.did()).data;
-
-                    if let (Some(e_last), Some(f_last)) = (e_path.last(), f_path.last())
-                        && e_last == f_last
-                    {
-                        return Some(Similar::Adts { expected: *expected, found: *found });
-                    }
-                }
-                None
-            };
-
-            match terr {
-                // If two types mismatch but have similar names, mention that specifically.
-                TypeError::Sorts(values) if let Some(s) = similarity(values) => {
-                    let diagnose_primitive =
-                        |prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| {
-                            let name = shadow.sort_string(self.tcx);
-                            diag.note(format!(
-                                "{prim} and {name} have similar names, but are actually distinct types"
-                            ));
-                            diag.note(format!("{prim} is a primitive defined by the language"));
-                            let def_span = self.tcx.def_span(defid);
-                            let msg = if defid.is_local() {
-                                format!("{name} is defined in the current crate")
-                            } else {
-                                let crate_name = self.tcx.crate_name(defid.krate);
-                                format!("{name} is defined in crate `{crate_name}`")
-                            };
-                            diag.span_note(def_span, msg);
-                        };
-
-                    let diagnose_adts =
-                        |expected_adt: ty::AdtDef<'tcx>,
-                         found_adt: ty::AdtDef<'tcx>,
-                         diag: &mut Diag<'_>| {
-                            let found_name = values.found.sort_string(self.tcx);
-                            let expected_name = values.expected.sort_string(self.tcx);
-
-                            let found_defid = found_adt.did();
-                            let expected_defid = expected_adt.did();
-
-                            diag.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
-                            for (defid, name) in
-                                [(found_defid, found_name), (expected_defid, expected_name)]
-                            {
-                                let def_span = self.tcx.def_span(defid);
-
-                                let msg = if found_defid.is_local() && expected_defid.is_local() {
-                                    let module = self
-                                        .tcx
-                                        .parent_module_from_def_id(defid.expect_local())
-                                        .to_def_id();
-                                    let module_name =
-                                        self.tcx.def_path(module).to_string_no_crate_verbose();
-                                    format!(
-                                        "{name} is defined in module `crate{module_name}` of the current crate"
-                                    )
-                                } else if defid.is_local() {
-                                    format!("{name} is defined in the current crate")
-                                } else {
-                                    let crate_name = self.tcx.crate_name(defid.krate);
-                                    format!("{name} is defined in crate `{crate_name}`")
-                                };
-                                diag.span_note(def_span, msg);
-                            }
-                        };
-
-                    match s {
-                        Similar::Adts { expected, found } => diagnose_adts(expected, found, diag),
-                        Similar::PrimitiveFound { expected, found: prim } => {
-                            diagnose_primitive(prim, values.expected, expected.did(), diag)
-                        }
-                        Similar::PrimitiveExpected { expected: prim, found } => {
-                            diagnose_primitive(prim, values.found, found.did(), diag)
-                        }
-                    }
-                }
-                TypeError::Sorts(values) => {
-                    let extra = expected == found;
-                    let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
-                        (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
-                            format!(
-                                " (opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
-                        }
-                        (true, ty::Alias(ty::Projection, proj))
-                            if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
-                        {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
-                            format!(
-                                " (trait associated opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
-                        }
-                        (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
-                        (false, _) => "".to_string(),
-                    };
-                    if !(values.expected.is_simple_text(self.tcx)
-                        && values.found.is_simple_text(self.tcx))
-                        || (exp_found.is_some_and(|ef| {
-                            // This happens when the type error is a subset of the expectation,
-                            // like when you have two references but one is `usize` and the other
-                            // is `f32`. In those cases we still want to show the `note`. If the
-                            // value from `ef` is `Infer(_)`, then we ignore it.
-                            if !ef.expected.is_ty_or_numeric_infer() {
-                                ef.expected != values.expected
-                            } else if !ef.found.is_ty_or_numeric_infer() {
-                                ef.found != values.found
-                            } else {
-                                false
-                            }
-                        }))
-                    {
-                        if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
-                            // `Future` is a special opaque type that the compiler
-                            // will try to hide in some case such as `async fn`, so
-                            // to make an error more use friendly we will
-                            // avoid to suggest a mismatch type with a
-                            // type that the user usually are not using
-                            // directly such as `impl Future<Output = u8>`.
-                            if !self.tcx.ty_is_opaque_future(found_ty) {
-                                diag.note_expected_found_extra(
-                                    &expected_label,
-                                    expected,
-                                    &found_label,
-                                    found,
-                                    &sort_string(values.expected),
-                                    &sort_string(values.found),
-                                );
-                                if let Some(path) = path {
-                                    diag.note(format!(
-                                        "the full type name has been written to '{}'",
-                                        path.display(),
-                                    ));
-                                    diag.note("consider using `--verbose` to print the full type name to the console");
-                                }
-                            }
-                        }
-                    }
-                }
-                _ => {
-                    debug!(
-                        "note_type_err: exp_found={:?}, expected={:?} found={:?}",
-                        exp_found, expected, found
-                    );
-                    if !is_simple_error || terr.must_include_note() {
-                        diag.note_expected_found(&expected_label, expected, &found_label, found);
-
-                        if let Some(ty::Closure(_, args)) =
-                            exp_found.map(|expected_type_found| expected_type_found.found.kind())
-                        {
-                            diag.highlighted_note(vec![
-                                StringPart::normal("closure has signature: `"),
-                                StringPart::highlighted(
-                                    self.tcx
-                                        .signature_unclosure(
-                                            args.as_closure().sig(),
-                                            rustc_hir::Safety::Safe,
-                                        )
-                                        .to_string(),
-                                ),
-                                StringPart::normal("`"),
-                            ]);
-                        }
-                    }
-                }
-            }
-        }
-        let exp_found = match exp_found {
-            Mismatch::Variable(exp_found) => Some(exp_found),
-            Mismatch::Fixed(_) => None,
-        };
-        let exp_found = match terr {
-            // `terr` has more accurate type information than `exp_found` in match expressions.
-            ty::error::TypeError::Sorts(terr)
-                if exp_found.is_some_and(|ef| terr.found == ef.found) =>
-            {
-                Some(terr)
-            }
-            _ => exp_found,
-        };
-        debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code());
-        if let Some(exp_found) = exp_found {
-            let should_suggest_fixes =
-                if let ObligationCauseCode::Pattern { root_ty, .. } = cause.code() {
-                    // Skip if the root_ty of the pattern is not the same as the expected_ty.
-                    // If these types aren't equal then we've probably peeled off a layer of arrays.
-                    self.same_type_modulo_infer(*root_ty, exp_found.expected)
-                } else {
-                    true
-                };
-
-            // FIXME(#73154): For now, we do leak check when coercing function
-            // pointers in typeck, instead of only during borrowck. This can lead
-            // to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
-            if should_suggest_fixes
-                && !matches!(terr, TypeError::RegionsInsufficientlyPolymorphic(..))
-            {
-                self.suggest_tuple_pattern(cause, &exp_found, diag);
-                self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
-                self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
-                self.suggest_function_pointers(cause, span, &exp_found, diag);
-                self.suggest_turning_stmt_into_expr(cause, &exp_found, diag);
-            }
-        }
-
-        self.check_and_note_conflicting_crates(diag, terr);
-
-        self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
-        if let Some(exp_found) = exp_found
-            && let exp_found = TypeError::Sorts(exp_found)
-            && exp_found != terr
-        {
-            self.note_and_explain_type_err(diag, exp_found, cause, span, cause.body_id.to_def_id());
-        }
-
-        if let Some(ValuePairs::TraitRefs(exp_found)) = values
-            && let ty::Closure(def_id, _) = exp_found.expected.self_ty().kind()
-            && let Some(def_id) = def_id.as_local()
-            && terr.involves_regions()
-        {
-            let span = self.tcx.def_span(def_id);
-            diag.span_note(span, "this closure does not fulfill the lifetime requirements");
-            self.suggest_for_all_lifetime_closure(
-                span,
-                self.tcx.hir_node_by_def_id(def_id),
-                &exp_found,
-                diag,
-            );
-        }
-
-        // It reads better to have the error origin as the final
-        // thing.
-        self.note_error_origin(diag, cause, exp_found, terr);
-
-        debug!(?diag);
-    }
-
-    pub fn type_error_additional_suggestions(
-        &self,
-        trace: &TypeTrace<'tcx>,
-        terr: TypeError<'tcx>,
-    ) -> Vec<TypeErrorAdditionalDiags> {
-        let mut suggestions = Vec::new();
-        let span = trace.cause.span();
-        let values = self.resolve_vars_if_possible(trace.values);
-        if let Some((expected, found)) = values.ty() {
-            match (expected.kind(), found.kind()) {
-                (ty::Tuple(_), ty::Tuple(_)) => {}
-                // If a tuple of length one was expected and the found expression has
-                // parentheses around it, perhaps the user meant to write `(expr,)` to
-                // build a tuple (issue #86100)
-                (ty::Tuple(fields), _) => {
-                    suggestions.extend(self.suggest_wrap_to_build_a_tuple(span, found, fields))
-                }
-                // If a byte was expected and the found expression is a char literal
-                // containing a single ASCII character, perhaps the user meant to write `b'c'` to
-                // specify a byte literal
-                (ty::Uint(ty::UintTy::U8), ty::Char) => {
-                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-                        && let Some(code) =
-                            code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
-                        // forbid all Unicode escapes
-                        && !code.starts_with("\\u")
-                        // forbids literal Unicode characters beyond ASCII
-                        && code.chars().next().is_some_and(|c| c.is_ascii())
-                    {
-                        suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral {
-                            span,
-                            code: escape_literal(code),
-                        })
-                    }
-                }
-                // If a character was expected and the found expression is a string literal
-                // containing a single character, perhaps the user meant to write `'c'` to
-                // specify a character literal (issue #92479)
-                (ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
-                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-                        && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
-                        && code.chars().count() == 1
-                    {
-                        suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral {
-                            span,
-                            code: escape_literal(code),
-                        })
-                    }
-                }
-                // If a string was expected and the found expression is a character literal,
-                // perhaps the user meant to write `"s"` to specify a string literal.
-                (ty::Ref(_, r, _), ty::Char) if r.is_str() => {
-                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-                        && code.starts_with("'")
-                        && code.ends_with("'")
-                    {
-                        suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
-                            start: span.with_hi(span.lo() + BytePos(1)),
-                            end: span.with_lo(span.hi() - BytePos(1)),
-                        });
-                    }
-                }
-                // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
-                // we try to suggest to add the missing `let` for `if let Some(..) = expr`
-                (ty::Bool, ty::Tuple(list)) => {
-                    if list.len() == 0 {
-                        suggestions.extend(self.suggest_let_for_letchains(&trace.cause, span));
-                    }
-                }
-                (ty::Array(_, _), ty::Array(_, _)) => {
-                    suggestions.extend(self.suggest_specify_actual_length(terr, trace, span))
-                }
-                _ => {}
-            }
-        }
-        let code = trace.cause.code();
-        if let &(ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-            source,
-            ..
-        })
-        | ObligationCauseCode::BlockTailExpression(.., source)) = code
-            && let hir::MatchSource::TryDesugar(_) = source
-            && let Some((expected_ty, found_ty, _)) = self.values_str(trace.values)
-        {
-            suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
-                found: found_ty.content(),
-                expected: expected_ty.content(),
-            });
-        }
-        suggestions
-    }
-
-    fn suggest_specify_actual_length(
-        &self,
-        terr: TypeError<'_>,
-        trace: &TypeTrace<'_>,
-        span: Span,
-    ) -> Option<TypeErrorAdditionalDiags> {
-        let hir = self.tcx.hir();
-        let TypeError::FixedArraySize(sz) = terr else {
-            return None;
-        };
-        let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => {
-                let body = hir.body(*body_id);
-                struct LetVisitor {
-                    span: Span,
-                }
-                impl<'v> Visitor<'v> for LetVisitor {
-                    type Result = ControlFlow<&'v hir::TyKind<'v>>;
-                    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result {
-                        // Find a local statement where the initializer has
-                        // the same span as the error and the type is specified.
-                        if let hir::Stmt {
-                            kind:
-                                hir::StmtKind::Let(hir::LetStmt {
-                                    init: Some(hir::Expr { span: init_span, .. }),
-                                    ty: Some(array_ty),
-                                    ..
-                                }),
-                            ..
-                        } = s
-                            && init_span == &self.span
-                        {
-                            ControlFlow::Break(&array_ty.peel_refs().kind)
-                        } else {
-                            ControlFlow::Continue(())
-                        }
-                    }
-                }
-                LetVisitor { span }.visit_body(body).break_value()
-            }
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }) => {
-                Some(&ty.peel_refs().kind)
-            }
-            _ => None,
-        };
-        if let Some(tykind) = tykind
-            && let hir::TyKind::Array(_, length) = tykind
-            && let hir::ArrayLen::Body(ct) = length
-        {
-            let span = ct.span();
-            Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
-        } else {
-            None
-        }
-    }
-
-    pub fn report_and_explain_type_error(
-        &self,
-        trace: TypeTrace<'tcx>,
-        terr: TypeError<'tcx>,
-    ) -> Diag<'a> {
-        debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
-
-        let span = trace.cause.span();
-        let failure_code = trace.cause.as_failure_code_diag(
-            terr,
-            span,
-            self.type_error_additional_suggestions(&trace, terr),
-        );
-        let mut diag = self.dcx().create_err(failure_code);
-        self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
-        diag
-    }
-
-    fn suggest_wrap_to_build_a_tuple(
-        &self,
-        span: Span,
-        found: Ty<'tcx>,
-        expected_fields: &List<Ty<'tcx>>,
-    ) -> Option<TypeErrorAdditionalDiags> {
-        let [expected_tup_elem] = expected_fields[..] else { return None };
-
-        if !self.same_type_modulo_infer(expected_tup_elem, found) {
-            return None;
-        }
-
-        let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) else { return None };
-
-        let sugg = if code.starts_with('(') && code.ends_with(')') {
-            let before_close = span.hi() - BytePos::from_u32(1);
-            TypeErrorAdditionalDiags::TupleOnlyComma {
-                span: span.with_hi(before_close).shrink_to_hi(),
-            }
-        } else {
-            TypeErrorAdditionalDiags::TupleAlsoParentheses {
-                span_low: span.shrink_to_lo(),
-                span_high: span.shrink_to_hi(),
-            }
-        };
-        Some(sugg)
-    }
-
-    fn values_str(
-        &self,
-        values: ValuePairs<'tcx>,
-    ) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
-        match values {
-            ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
-            ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::TraitRefs(exp_found) => {
-                let pretty_exp_found = ty::error::ExpectedFound {
-                    expected: exp_found.expected.print_trait_sugared(),
-                    found: exp_found.found.print_trait_sugared(),
-                };
-                match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found, _)) if expected == found => {
-                        self.expected_found_str(exp_found)
-                    }
-                    ret => ret,
-                }
-            }
-            ValuePairs::PolySigs(exp_found) => {
-                let exp_found = self.resolve_vars_if_possible(exp_found);
-                if exp_found.references_error() {
-                    return None;
-                }
-                let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
-                Some((exp, fnd, None))
-            }
-            ValuePairs::Dummy => {
-                bug!("do not expect to report a type error from a ValuePairs::Dummy")
-            }
-        }
-    }
-
-    fn expected_found_str_term(
-        &self,
-        exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-    ) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
-        let exp_found = self.resolve_vars_if_possible(exp_found);
-        if exp_found.references_error() {
-            return None;
-        }
-
-        Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
-            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
-                let (mut exp, mut fnd) = self.cmp(expected, found);
-                // Use the terminal width as the basis to determine when to compress the printed
-                // out type, but give ourselves some leeway to avoid ending up creating a file for
-                // a type that is somewhat shorter than the path we'd write to.
-                let len = self.tcx.sess().diagnostic_width() + 40;
-                let exp_s = exp.content();
-                let fnd_s = fnd.content();
-                let mut path = None;
-                if exp_s.len() > len {
-                    let exp_s = self.tcx.short_ty_string(expected, &mut path);
-                    exp = DiagStyledString::highlighted(exp_s);
-                }
-                if fnd_s.len() > len {
-                    let fnd_s = self.tcx.short_ty_string(found, &mut path);
-                    fnd = DiagStyledString::highlighted(fnd_s);
-                }
-                (exp, fnd, path)
-            }
-            _ => (
-                DiagStyledString::highlighted(exp_found.expected.to_string()),
-                DiagStyledString::highlighted(exp_found.found.to_string()),
-                None,
-            ),
-        })
-    }
-
-    /// Returns a string of the form "expected `{}`, found `{}`".
-    fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
-        &self,
-        exp_found: ty::error::ExpectedFound<T>,
-    ) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
-        let exp_found = self.resolve_vars_if_possible(exp_found);
-        if exp_found.references_error() {
-            return None;
-        }
-
-        Some((
-            DiagStyledString::highlighted(exp_found.expected.to_string()),
-            DiagStyledString::highlighted(exp_found.found.to_string()),
-            None,
-        ))
-    }
-
-    /// Determine whether an error associated with the given span and definition
-    /// should be treated as being caused by the implicit `From` conversion
-    /// within `?` desugaring.
-    pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
-        span.is_desugaring(DesugaringKind::QuestionMark)
-            && self.tcx.is_diagnostic_item(sym::From, trait_def_id)
-    }
-
-    /// Structurally compares two types, modulo any inference variables.
-    ///
-    /// Returns `true` if two types are equal, or if one type is an inference variable compatible
-    /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
-    /// FloatVar inference type are compatible with themselves or their concrete types (Int and
-    /// Float types, respectively). When comparing two ADTs, these rules apply recursively.
-    pub fn same_type_modulo_infer<T: relate::Relate<TyCtxt<'tcx>>>(&self, a: T, b: T) -> bool {
-        let (a, b) = self.resolve_vars_if_possible((a, b));
-        SameTypeModuloInfer(self).relate(a, b).is_ok()
-    }
-}
-
-struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
-
-impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.0.tcx
-    }
-
-    fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
-        &mut self,
-        _variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
-        a: T,
-        b: T,
-    ) -> relate::RelateResult<'tcx, T> {
-        self.relate(a, b)
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        match (a.kind(), b.kind()) {
-            (ty::Int(_) | ty::Uint(_), ty::Infer(ty::InferTy::IntVar(_)))
-            | (
-                ty::Infer(ty::InferTy::IntVar(_)),
-                ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)),
-            )
-            | (ty::Float(_), ty::Infer(ty::InferTy::FloatVar(_)))
-            | (
-                ty::Infer(ty::InferTy::FloatVar(_)),
-                ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)),
-            )
-            | (ty::Infer(ty::InferTy::TyVar(_)), _)
-            | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
-            (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
-            _ => relate::structurally_relate_tys(self, a, b),
-        }
-    }
-
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        b: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        if (a.is_var() && b.is_free())
-            || (b.is_var() && a.is_free())
-            || (a.is_var() && b.is_var())
-            || a == b
-        {
-            Ok(a)
-        } else {
-            Err(TypeError::Mismatch)
-        }
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: relate::Relate<TyCtxt<'tcx>>,
-    {
-        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
-    }
-
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        _b: ty::Const<'tcx>,
-    ) -> relate::RelateResult<'tcx, ty::Const<'tcx>> {
-        // FIXME(compiler-errors): This could at least do some first-order
-        // relation
-        Ok(a)
-    }
-}
-
-pub enum FailureCode {
-    Error0317,
-    Error0580,
-    Error0308,
-    Error0644,
-}
-
-#[extension(pub trait ObligationCauseExt<'tcx>)]
-impl<'tcx> ObligationCause<'tcx> {
-    fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode {
-        match self.code() {
-            ObligationCauseCode::IfExpressionWithNoElse => FailureCode::Error0317,
-            ObligationCauseCode::MainFunctionType => FailureCode::Error0580,
-            ObligationCauseCode::CompareImplItem { .. }
-            | ObligationCauseCode::MatchExpressionArm(_)
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::LetElse
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::LangFunctionType(_)
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver => FailureCode::Error0308,
-
-            // In the case where we have no more specific thing to
-            // say, also take a look at the error code, maybe we can
-            // tailor to that.
-            _ => match terr {
-                TypeError::CyclicTy(ty)
-                    if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() =>
-                {
-                    FailureCode::Error0644
-                }
-                TypeError::IntrinsicCast => FailureCode::Error0308,
-                _ => FailureCode::Error0308,
-            },
-        }
-    }
-    fn as_failure_code_diag(
-        &self,
-        terr: TypeError<'tcx>,
-        span: Span,
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    ) -> ObligationCauseFailureCode {
-        match self.code() {
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
-                ObligationCauseFailureCode::MethodCompat { span, subdiags }
-            }
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
-                ObligationCauseFailureCode::TypeCompat { span, subdiags }
-            }
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
-                ObligationCauseFailureCode::ConstCompat { span, subdiags }
-            }
-            ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
-                ObligationCauseFailureCode::TryCompat { span, subdiags }
-            }
-            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                source, ..
-            }) => match source {
-                hir::MatchSource::TryDesugar(_) => {
-                    ObligationCauseFailureCode::TryCompat { span, subdiags }
-                }
-                _ => ObligationCauseFailureCode::MatchCompat { span, subdiags },
-            },
-            ObligationCauseCode::IfExpression { .. } => {
-                ObligationCauseFailureCode::IfElseDifferent { span, subdiags }
-            }
-            ObligationCauseCode::IfExpressionWithNoElse => {
-                ObligationCauseFailureCode::NoElse { span }
-            }
-            ObligationCauseCode::LetElse => {
-                ObligationCauseFailureCode::NoDiverge { span, subdiags }
-            }
-            ObligationCauseCode::MainFunctionType => {
-                ObligationCauseFailureCode::FnMainCorrectType { span }
-            }
-            ObligationCauseCode::StartFunctionType => {
-                ObligationCauseFailureCode::FnStartCorrectType { span, subdiags }
-            }
-            &ObligationCauseCode::LangFunctionType(lang_item_name) => {
-                ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name }
-            }
-            ObligationCauseCode::IntrinsicType => {
-                ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags }
-            }
-            ObligationCauseCode::MethodReceiver => {
-                ObligationCauseFailureCode::MethodCorrectType { span, subdiags }
-            }
-
-            // In the case where we have no more specific thing to
-            // say, also take a look at the error code, maybe we can
-            // tailor to that.
-            _ => match terr {
-                TypeError::CyclicTy(ty)
-                    if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() =>
-                {
-                    ObligationCauseFailureCode::ClosureSelfref { span }
-                }
-                TypeError::IntrinsicCast => {
-                    ObligationCauseFailureCode::CantCoerce { span, subdiags }
-                }
-                _ => ObligationCauseFailureCode::Generic { span, subdiags },
-            },
-        }
-    }
-
-    fn as_requirement_str(&self) -> &'static str {
-        match self.code() {
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
-                "method type is compatible with trait"
-            }
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
-                "associated type is compatible with trait"
-            }
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
-                "const is compatible with trait"
-            }
-            ObligationCauseCode::MainFunctionType => "`main` function has the correct type",
-            ObligationCauseCode::StartFunctionType => "`#[start]` function has the correct type",
-            ObligationCauseCode::LangFunctionType(_) => "lang item function has the correct type",
-            ObligationCauseCode::IntrinsicType => "intrinsic has the correct type",
-            ObligationCauseCode::MethodReceiver => "method receiver has the correct type",
-            _ => "types are compatible",
-        }
-    }
-}
-
-/// Newtype to allow implementing IntoDiagArg
-pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
-
-impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        let kind = match self.0.code() {
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",
-            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
-                "const_compat"
-            }
-            ObligationCauseCode::MainFunctionType => "fn_main_correct_type",
-            ObligationCauseCode::StartFunctionType => "fn_start_correct_type",
-            ObligationCauseCode::LangFunctionType(_) => "fn_lang_correct_type",
-            ObligationCauseCode::IntrinsicType => "intrinsic_correct_type",
-            ObligationCauseCode::MethodReceiver => "method_correct_type",
-            _ => "other",
-        }
-        .into();
-        rustc_errors::DiagArgValue::Str(kind)
-    }
-}
-
-/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
-/// extra information about each type, but we only care about the category.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub enum TyCategory {
-    Closure,
-    Opaque,
-    OpaqueFuture,
-    Coroutine(hir::CoroutineKind),
-    Foreign,
-}
-
-impl fmt::Display for TyCategory {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Closure => "closure".fmt(f),
-            Self::Opaque => "opaque type".fmt(f),
-            Self::OpaqueFuture => "future".fmt(f),
-            Self::Coroutine(gk) => gk.fmt(f),
-            Self::Foreign => "foreign type".fmt(f),
-        }
-    }
-}
-
-impl TyCategory {
-    pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
-        match *ty.kind() {
-            ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
-                let kind =
-                    if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque };
-                Some((kind, def_id))
-            }
-            ty::Coroutine(def_id, ..) => {
-                Some((Self::Coroutine(tcx.coroutine_kind(def_id).unwrap()), def_id))
-            }
-            ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
-            _ => None,
-        }
-    }
-}
-
-impl<'tcx> InferCtxt<'tcx> {
-    /// Given a [`hir::Block`], get the span of its last expression or
-    /// statement, peeling off any inner blocks.
-    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
-        let block = block.innermost_block();
-        if let Some(expr) = &block.expr {
-            expr.span
-        } else if let Some(stmt) = block.stmts.last() {
-            // possibly incorrect trailing `;` in the else arm
-            stmt.span
-        } else {
-            // empty block; point at its entirety
-            block.span
-        }
-    }
-
-    /// Given a [`hir::HirId`] for a block, get the span of its last expression
-    /// or statement, peeling off any inner blocks.
-    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
-        match self.tcx.hir_node(hir_id) {
-            hir::Node::Block(blk) => self.find_block_span(blk),
-            // The parser was in a weird state if either of these happen, but
-            // it's better not to panic.
-            hir::Node::Expr(e) => e.span,
-            _ => rustc_span::DUMMY_SP,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
deleted file mode 100644
index 74dcde03639..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
+++ /dev/null
@@ -1,163 +0,0 @@
-//! Error Reporting for Anonymous Region Lifetime Errors
-//! where both the regions are anonymous.
-
-use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
-use crate::error_reporting::infer::nice_region_error::util::AnonymousParamInfo;
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::AddLifetimeParamsSuggestion;
-use crate::errors::LifetimeMismatch;
-use crate::errors::LifetimeMismatchLabels;
-use crate::infer::RegionResolutionError;
-use crate::infer::SubregionOrigin;
-
-use rustc_errors::Subdiagnostic;
-use rustc_errors::{Diag, ErrorGuaranteed};
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::Ty;
-use rustc_middle::ty::{Region, TyCtxt};
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// Print the error message for lifetime errors when both the concerned regions are anonymous.
-    ///
-    /// Consider a case where we have
-    ///
-    /// ```compile_fail
-    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
-    ///     x.push(y);
-    /// }
-    /// ```
-    ///
-    /// The example gives
-    ///
-    /// ```text
-    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
-    ///                    ---      --- these references are declared with different lifetimes...
-    ///     x.push(y);
-    ///     ^ ...but data from `y` flows into `x` here
-    /// ```
-    ///
-    /// It has been extended for the case of structs too.
-    ///
-    /// Consider the example
-    ///
-    /// ```no_run
-    /// struct Ref<'a> { x: &'a u32 }
-    /// ```
-    ///
-    /// ```text
-    /// fn foo(mut x: Vec<Ref>, y: Ref) {
-    ///                   ---      --- these structs are declared with different lifetimes...
-    ///     x.push(y);
-    ///     ^ ...but data from `y` flows into `x` here
-    /// }
-    /// ```
-    ///
-    /// It will later be extended to trait objects.
-    pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorGuaranteed> {
-        let (span, sub, sup) = self.regions()?;
-
-        if let Some(RegionResolutionError::ConcreteFailure(
-            SubregionOrigin::ReferenceOutlivesReferent(..),
-            ..,
-        )) = self.error
-        {
-            // This error doesn't make much sense in this case.
-            return None;
-        }
-
-        // Determine whether the sub and sup consist of both anonymous (elided) regions.
-        let anon_reg_sup = self.tcx().is_suitable_region(self.generic_param_scope, sup)?;
-
-        let anon_reg_sub = self.tcx().is_suitable_region(self.generic_param_scope, sub)?;
-        let scope_def_id_sup = anon_reg_sup.def_id;
-        let bregion_sup = anon_reg_sup.bound_region;
-        let scope_def_id_sub = anon_reg_sub.def_id;
-        let bregion_sub = anon_reg_sub.bound_region;
-
-        let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup, &bregion_sup)?;
-
-        let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub, &bregion_sub)?;
-
-        debug!(
-            "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
-            ty_sub, sup, bregion_sup
-        );
-        debug!(
-            "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
-            ty_sup, sub, bregion_sub
-        );
-
-        let (ty_sup, ty_fndecl_sup) = ty_sup;
-        let (ty_sub, ty_fndecl_sub) = ty_sub;
-
-        let AnonymousParamInfo { param: anon_param_sup, .. } =
-            self.find_param_with_region(sup, sup)?;
-        let AnonymousParamInfo { param: anon_param_sub, .. } =
-            self.find_param_with_region(sub, sub)?;
-
-        let sup_is_ret_type =
-            self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
-        let sub_is_ret_type =
-            self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
-
-        debug!(
-            "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",
-            sub_is_ret_type, sup_is_ret_type
-        );
-
-        let labels = match (sup_is_ret_type, sub_is_ret_type) {
-            (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => {
-                let param_span =
-                    if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span };
-                LifetimeMismatchLabels::InRet {
-                    param_span,
-                    ret_span,
-                    span,
-                    label_var1: anon_param_sup.pat.simple_ident(),
-                }
-            }
-
-            (None, None) => LifetimeMismatchLabels::Normal {
-                hir_equal: ty_sup.hir_id == ty_sub.hir_id,
-                ty_sup: ty_sup.span,
-                ty_sub: ty_sub.span,
-                span,
-                sup: anon_param_sup.pat.simple_ident(),
-                sub: anon_param_sub.pat.simple_ident(),
-            },
-        };
-
-        let suggestion = AddLifetimeParamsSuggestion {
-            tcx: self.tcx(),
-            sub,
-            ty_sup,
-            ty_sub,
-            add_note: true,
-            generic_param_scope: self.generic_param_scope,
-        };
-        let err = LifetimeMismatch { span, labels, suggestion };
-        let reported = self.tcx().dcx().emit_err(err);
-        Some(reported)
-    }
-}
-
-/// Currently only used in rustc_borrowck, probably should be
-/// removed in favour of public_errors::AddLifetimeParamsSuggestion
-pub fn suggest_adding_lifetime_params<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    err: &mut Diag<'_>,
-    generic_param_scope: LocalDefId,
-    sub: Region<'tcx>,
-    ty_sup: &'tcx Ty<'_>,
-    ty_sub: &'tcx Ty<'_>,
-) {
-    let suggestion = AddLifetimeParamsSuggestion {
-        tcx,
-        sub,
-        ty_sup,
-        ty_sub,
-        add_note: false,
-        generic_param_scope,
-    };
-    suggestion.add_to_diag(err);
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs
deleted file mode 100644
index b91b755d683..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ /dev/null
@@ -1,236 +0,0 @@
-use core::ops::ControlFlow;
-use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::hir::map::Map;
-use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_bound_vars as rbv;
-use rustc_middle::ty::{self, Region, TyCtxt};
-
-/// This function calls the `visit_ty` method for the parameters
-/// corresponding to the anonymous regions. The `nested_visitor.found_type`
-/// contains the anonymous type.
-///
-/// # Arguments
-/// region - the anonymous region corresponding to the anon_anon conflict
-/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
-///
-/// # Example
-/// ```compile_fail
-/// fn foo(x: &mut Vec<&u8>, y: &u8)
-///    { x.push(y); }
-/// ```
-/// The function returns the nested type corresponding to the anonymous region
-/// for e.g., `&u8` and `Vec<&u8>`.
-pub fn find_anon_type<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    generic_param_scope: LocalDefId,
-    region: Region<'tcx>,
-    br: &ty::BoundRegionKind,
-) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
-    let anon_reg = tcx.is_suitable_region(generic_param_scope, region)?;
-    let fn_sig = tcx.hir_node_by_def_id(anon_reg.def_id).fn_sig()?;
-
-    fn_sig
-        .decl
-        .inputs
-        .iter()
-        .find_map(|arg| find_component_for_bound_region(tcx, arg, br))
-        .map(|ty| (ty, fn_sig))
-}
-
-// This method creates a FindNestedTypeVisitor which returns the type corresponding
-// to the anonymous region.
-fn find_component_for_bound_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    arg: &'tcx hir::Ty<'tcx>,
-    br: &ty::BoundRegionKind,
-) -> Option<&'tcx hir::Ty<'tcx>> {
-    FindNestedTypeVisitor { tcx, bound_region: *br, current_index: ty::INNERMOST }
-        .visit_ty(arg)
-        .break_value()
-}
-
-// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
-// anonymous region. The example above would lead to a conflict between
-// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
-// would be invoked twice, once for each lifetime, and would
-// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
-// where that lifetime appears. This allows us to highlight the
-// specific part of the type in the error message.
-struct FindNestedTypeVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    // The bound_region corresponding to the Refree(freeregion)
-    // associated with the anonymous region we are looking for.
-    bound_region: ty::BoundRegionKind,
-    current_index: ty::DebruijnIndex,
-}
-
-impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
-    type Result = ControlFlow<&'tcx hir::Ty<'tcx>>;
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
-        match arg.kind {
-            hir::TyKind::BareFn(_) => {
-                self.current_index.shift_in(1);
-                intravisit::walk_ty(self, arg);
-                self.current_index.shift_out(1);
-                return ControlFlow::Continue(());
-            }
-
-            hir::TyKind::TraitObject(bounds, ..) => {
-                for bound in bounds {
-                    self.current_index.shift_in(1);
-                    self.visit_poly_trait_ref(bound);
-                    self.current_index.shift_out(1);
-                }
-            }
-
-            hir::TyKind::Ref(lifetime, _) => {
-                // the lifetime of the Ref
-                let hir_id = lifetime.hir_id;
-                match (self.tcx.named_bound_var(hir_id), self.bound_region) {
-                    // Find the index of the named region that was part of the
-                    // error. We will then search the function parameters for a bound
-                    // region at the right depth with the same index
-                    (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
-                        debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
-                        if id == def_id {
-                            return ControlFlow::Break(arg);
-                        }
-                    }
-
-                    // Find the index of the named region that was part of the
-                    // error. We will then search the function parameters for a bound
-                    // region at the right depth with the same index
-                    (
-                        Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
-                        ty::BrNamed(def_id, _),
-                    ) => {
-                        debug!(
-                            "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
-                            debruijn_index
-                        );
-                        debug!("LateBound id={:?} def_id={:?}", id, def_id);
-                        if debruijn_index == self.current_index && id == def_id {
-                            return ControlFlow::Break(arg);
-                        }
-                    }
-
-                    (
-                        Some(
-                            rbv::ResolvedArg::StaticLifetime
-                            | rbv::ResolvedArg::Free(_, _)
-                            | rbv::ResolvedArg::EarlyBound(_)
-                            | rbv::ResolvedArg::LateBound(_, _, _)
-                            | rbv::ResolvedArg::Error(_),
-                        )
-                        | None,
-                        _,
-                    ) => {
-                        debug!("no arg found");
-                    }
-                }
-            }
-            // Checks if it is of type `hir::TyKind::Path` which corresponds to a struct.
-            hir::TyKind::Path(_) => {
-                // Prefer using the lifetime in type arguments rather than lifetime arguments.
-                intravisit::walk_ty(self, arg)?;
-
-                // Call `walk_ty` as `visit_ty` is empty.
-                return if intravisit::walk_ty(
-                    &mut TyPathVisitor {
-                        tcx: self.tcx,
-                        bound_region: self.bound_region,
-                        current_index: self.current_index,
-                    },
-                    arg,
-                )
-                .is_break()
-                {
-                    ControlFlow::Break(arg)
-                } else {
-                    ControlFlow::Continue(())
-                };
-            }
-            _ => {}
-        }
-        // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
-        // go on to visit `&Foo`
-        intravisit::walk_ty(self, arg)
-    }
-}
-
-// The visitor captures the corresponding `hir::Ty` of the anonymous region
-// in the case of structs ie. `hir::TyKind::Path`.
-// This visitor would be invoked for each lifetime corresponding to a struct,
-// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
-// where that lifetime appears. This allows us to highlight the
-// specific part of the type in the error message.
-struct TyPathVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    bound_region: ty::BoundRegionKind,
-    current_index: ty::DebruijnIndex,
-}
-
-impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
-    type Result = ControlFlow<()>;
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Map<'tcx> {
-        self.tcx.hir()
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
-        match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
-            // the lifetime of the TyPath!
-            (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
-                debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
-                if id == def_id {
-                    return ControlFlow::Break(());
-                }
-            }
-
-            (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
-                debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
-                debug!("id={:?}", id);
-                debug!("def_id={:?}", def_id);
-                if debruijn_index == self.current_index && id == def_id {
-                    return ControlFlow::Break(());
-                }
-            }
-
-            (
-                Some(
-                    rbv::ResolvedArg::StaticLifetime
-                    | rbv::ResolvedArg::EarlyBound(_)
-                    | rbv::ResolvedArg::LateBound(_, _, _)
-                    | rbv::ResolvedArg::Free(_, _)
-                    | rbv::ResolvedArg::Error(_),
-                )
-                | None,
-                _,
-            ) => {
-                debug!("no arg found");
-            }
-        }
-        ControlFlow::Continue(())
-    }
-
-    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
-        // ignore nested types
-        //
-        // If you have a type like `Foo<'a, &Ty>` we
-        // are only interested in the immediate lifetimes ('a).
-        //
-        // Making `visit_ty` empty will ignore the `&Ty` embedded
-        // inside, it will get reached by the outer visitor.
-        debug!("`Ty` corresponding to a struct is {:?}", arg);
-        ControlFlow::Continue(())
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
deleted file mode 100644
index 550cc455e01..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-//! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
-//! to hold.
-
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
-use crate::errors::{
-    DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::ObligationCauseCode;
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{ErrorGuaranteed, MultiSpan};
-use rustc_hir as hir;
-use rustc_hir::intravisit::Visitor;
-use rustc_middle::bug;
-use rustc_middle::ty::TypeVisitor;
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaranteed> {
-        let error = self.error.as_ref()?;
-        debug!("try_report_mismatched_static_lifetime {:?}", error);
-
-        let RegionResolutionError::ConcreteFailure(origin, sub, sup) = error.clone() else {
-            return None;
-        };
-        if !sub.is_static() {
-            return None;
-        }
-        let SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) = origin else {
-            return None;
-        };
-        // If we added a "points at argument expression" obligation, we remove it here, we care
-        // about the original obligation only.
-        let code = match cause.code() {
-            ObligationCauseCode::FunctionArg { parent_code, .. } => &*parent_code,
-            code => code,
-        };
-        let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
-            return None;
-        };
-        let (ObligationCauseCode::WhereClause(_, binding_span)
-        | ObligationCauseCode::WhereClauseInExpr(_, binding_span, ..)) = *parent.code()
-        else {
-            return None;
-        };
-        if binding_span.is_dummy() {
-            return None;
-        }
-
-        // FIXME: we should point at the lifetime
-        let multi_span: MultiSpan = vec![binding_span].into();
-        let multispan_subdiag = IntroducesStaticBecauseUnmetLifetimeReq {
-            unmet_requirements: multi_span,
-            binding_span,
-        };
-
-        let expl = note_and_explain::RegionExplanation::new(
-            self.tcx(),
-            self.generic_param_scope,
-            sup,
-            Some(binding_span),
-            note_and_explain::PrefixKind::Empty,
-            note_and_explain::SuffixKind::Continues,
-        );
-        let mut impl_span = None;
-        let mut implicit_static_lifetimes = Vec::new();
-        if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
-            // If an impl is local, then maybe this isn't what they want. Try to
-            // be as helpful as possible with implicit lifetimes.
-
-            // First, let's get the hir self type of the impl
-            let hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, .. }),
-                ..
-            }) = impl_node
-            else {
-                bug!("Node not an impl.");
-            };
-
-            // Next, let's figure out the set of trait objects with implicit static bounds
-            let ty = self.tcx().type_of(*impl_def_id).instantiate_identity();
-            let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default());
-            v.visit_ty(ty);
-            let mut traits = vec![];
-            for matching_def_id in v.0 {
-                let mut hir_v =
-                    super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
-                hir_v.visit_ty(impl_self_ty);
-            }
-
-            if traits.is_empty() {
-                // If there are no trait object traits to point at, either because
-                // there aren't trait objects or because none are implicit, then just
-                // write a single note on the impl itself.
-
-                impl_span = Some(self.tcx().def_span(*impl_def_id));
-            } else {
-                // Otherwise, point at all implicit static lifetimes
-
-                for span in &traits {
-                    implicit_static_lifetimes
-                        .push(ImplicitStaticLifetimeSubdiag::Note { span: *span });
-                    // It would be nice to put this immediately under the above note, but they get
-                    // pushed to the end.
-                    implicit_static_lifetimes
-                        .push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() });
-                }
-            }
-        } else {
-            // Otherwise just point out the impl.
-
-            impl_span = Some(self.tcx().def_span(*impl_def_id));
-        }
-        let err = MismatchedStaticLifetime {
-            cause_span: cause.span,
-            unmet_lifetime_reqs: multispan_subdiag,
-            expl,
-            does_not_outlive_static_from_impl: impl_span
-                .map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
-                .unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
-            implicit_static_lifetimes,
-        };
-        let reported = self.tcx().dcx().emit_err(err);
-        Some(reported)
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs
deleted file mode 100644
index ced4c384f02..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use crate::error_reporting::infer::TypeErrCtxt;
-use crate::infer::RegionResolutionError;
-use crate::infer::RegionResolutionError::*;
-use rustc_errors::{Diag, ErrorGuaranteed};
-use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::Span;
-
-mod different_lifetimes;
-pub mod find_anon_type;
-mod mismatched_static_lifetime;
-mod named_anon_conflict;
-pub(crate) mod placeholder_error;
-mod placeholder_relation;
-mod static_impl_trait;
-mod trait_impl_difference;
-mod util;
-
-pub use different_lifetimes::suggest_adding_lifetime_params;
-pub use find_anon_type::find_anon_type;
-pub use static_impl_trait::{suggest_new_region_bound, HirTraitObjectVisitor, TraitObjectVisitor};
-pub use util::find_param_with_region;
-
-impl<'cx, 'tcx> TypeErrCtxt<'cx, 'tcx> {
-    pub fn try_report_nice_region_error(
-        &'cx self,
-        generic_param_scope: LocalDefId,
-        error: &RegionResolutionError<'tcx>,
-    ) -> Option<ErrorGuaranteed> {
-        NiceRegionError::new(self, generic_param_scope, error.clone()).try_report()
-    }
-}
-
-pub struct NiceRegionError<'cx, 'tcx> {
-    cx: &'cx TypeErrCtxt<'cx, 'tcx>,
-    /// The innermost definition that introduces generic parameters that may be involved in
-    /// the region errors we are dealing with.
-    generic_param_scope: LocalDefId,
-    error: Option<RegionResolutionError<'tcx>>,
-    regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
-}
-
-impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
-    pub fn new(
-        cx: &'cx TypeErrCtxt<'cx, 'tcx>,
-        generic_param_scope: LocalDefId,
-        error: RegionResolutionError<'tcx>,
-    ) -> Self {
-        Self { cx, error: Some(error), regions: None, generic_param_scope }
-    }
-
-    pub fn new_from_span(
-        cx: &'cx TypeErrCtxt<'cx, 'tcx>,
-        generic_param_scope: LocalDefId,
-        span: Span,
-        sub: ty::Region<'tcx>,
-        sup: ty::Region<'tcx>,
-    ) -> Self {
-        Self { cx, error: None, regions: Some((span, sub, sup)), generic_param_scope }
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.cx.tcx
-    }
-
-    pub fn try_report_from_nll(&self) -> Option<Diag<'tcx>> {
-        // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
-        // the nice region errors are required when running under the MIR borrow checker.
-        self.try_report_named_anon_conflict()
-            .or_else(|| self.try_report_placeholder_conflict())
-            .or_else(|| self.try_report_placeholder_relation())
-    }
-
-    pub fn try_report(&self) -> Option<ErrorGuaranteed> {
-        self.try_report_from_nll()
-            .map(|diag| diag.emit())
-            .or_else(|| self.try_report_impl_not_conforming_to_trait())
-            .or_else(|| self.try_report_anon_anon_conflict())
-            .or_else(|| self.try_report_static_impl_trait())
-            .or_else(|| self.try_report_mismatched_static_lifetime())
-    }
-
-    pub(super) fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
-        match (&self.error, self.regions) {
-            (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)),
-            (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
-                Some((origin.span(), *sub, *sup))
-            }
-            (None, Some((span, sub, sup))) => Some((span, sub, sup)),
-            _ => None,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
deleted file mode 100644
index d1802d2f5ee..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-//! Error Reporting for Anonymous Region Lifetime Errors
-//! where one region is named and the other is anonymous.
-
-use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::ExplicitLifetimeRequired;
-use rustc_errors::Diag;
-use rustc_middle::ty;
-use rustc_span::symbol::kw;
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// When given a `ConcreteFailure` for a function with parameters containing a named region and
-    /// an anonymous region, emit an descriptive diagnostic error.
-    pub(super) fn try_report_named_anon_conflict(&self) -> Option<Diag<'tcx>> {
-        let (span, sub, sup) = self.regions()?;
-
-        debug!(
-            "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
-            sub, sup, self.error,
-        );
-
-        // Determine whether the sub and sup consist of one named region ('a)
-        // and one anonymous (elided) region. If so, find the parameter arg
-        // where the anonymous region appears (there must always be one; we
-        // only introduced anonymous regions in parameters) as well as a
-        // version new_ty of its type where the anonymous region is replaced
-        // with the named one.
-        let (named, anon, anon_param_info, region_info) = if sub.has_name()
-            && let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sup)
-            && let Some(anon_param_info) = self.find_param_with_region(sup, sub)
-        {
-            (sub, sup, anon_param_info, region_info)
-        } else if sup.has_name()
-            && let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sub)
-            && let Some(anon_param_info) = self.find_param_with_region(sub, sup)
-        {
-            (sup, sub, anon_param_info, region_info)
-        } else {
-            return None; // inapplicable
-        };
-
-        // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect,
-        // and can steer users down the wrong path.
-        if named.is_static() {
-            return None;
-        }
-
-        debug!("try_report_named_anon_conflict: named = {:?}", named);
-        debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
-        debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
-
-        let param = anon_param_info.param;
-        let new_ty = anon_param_info.param_ty;
-        let new_ty_span = anon_param_info.param_ty_span;
-        let br = anon_param_info.bound_region;
-        let is_first = anon_param_info.is_first;
-        let scope_def_id = region_info.def_id;
-        let is_impl_item = region_info.is_impl_item;
-
-        match br {
-            ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon => {}
-            _ => {
-                /* not an anonymous region */
-                debug!("try_report_named_anon_conflict: not an anonymous region");
-                return None;
-            }
-        }
-
-        if is_impl_item {
-            debug!("try_report_named_anon_conflict: impl item, bail out");
-            return None;
-        }
-
-        if find_anon_type(self.tcx(), self.generic_param_scope, anon, &br).is_some()
-            && self.is_self_anon(is_first, scope_def_id)
-        {
-            return None;
-        }
-        let named = named.to_string();
-        let err = match param.pat.simple_ident() {
-            Some(simple_ident) => ExplicitLifetimeRequired::WithIdent {
-                span,
-                simple_ident,
-                named,
-                new_ty_span,
-                new_ty,
-            },
-            None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty },
-        };
-        Some(self.tcx().sess.dcx().create_err(err))
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs
deleted file mode 100644
index 476ac3f1720..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs
+++ /dev/null
@@ -1,496 +0,0 @@
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{
-    ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
-    TraitPlaceholderMismatch, TyOrSig,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::ValuePairs;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::{ObligationCause, ObligationCauseCode};
-use rustc_data_structures::intern::Interned;
-use rustc_errors::{Diag, IntoDiagArg};
-use rustc_hir::def::Namespace;
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
-use rustc_middle::bug;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
-
-use std::fmt;
-
-// HACK(eddyb) maybe move this in a more central location.
-#[derive(Copy, Clone)]
-pub struct Highlighted<'tcx, T> {
-    tcx: TyCtxt<'tcx>,
-    highlight: RegionHighlightMode<'tcx>,
-    value: T,
-}
-
-impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
-where
-    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
-{
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        rustc_errors::DiagArgValue::Str(self.to_string().into())
-    }
-}
-
-impl<'tcx, T> Highlighted<'tcx, T> {
-    fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
-        Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) }
-    }
-}
-
-impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
-where
-    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
-        printer.region_highlight_mode = self.highlight;
-
-        self.value.print(&mut printer)?;
-        f.write_str(&printer.into_buffer())
-    }
-}
-
-impl<'tcx> NiceRegionError<'_, 'tcx> {
-    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
-    /// an anonymous region, emit a descriptive diagnostic error.
-    pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
-        match &self.error {
-            ///////////////////////////////////////////////////////////////////////////
-            // NB. The ordering of cases in this match is very
-            // sensitive, because we are often matching against
-            // specific cases and then using an `_` to match all
-            // others.
-
-            ///////////////////////////////////////////////////////////////////////////
-            // Check for errors from comparing trait failures -- first
-            // with two placeholders, then with one.
-            Some(RegionResolutionError::SubSupConflict(
-                vid,
-                _,
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
-                _,
-                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
-                _,
-            )) => self.try_report_trait_placeholder_mismatch(
-                Some(ty::Region::new_var(self.tcx(), *vid)),
-                cause,
-                Some(*sub_placeholder),
-                Some(*sup_placeholder),
-                values,
-            ),
-
-            Some(RegionResolutionError::SubSupConflict(
-                vid,
-                _,
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
-                _,
-                _,
-                _,
-            )) => self.try_report_trait_placeholder_mismatch(
-                Some(ty::Region::new_var(self.tcx(), *vid)),
-                cause,
-                Some(*sub_placeholder),
-                None,
-                values,
-            ),
-
-            Some(RegionResolutionError::SubSupConflict(
-                vid,
-                _,
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                _,
-                _,
-                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
-                _,
-            )) => self.try_report_trait_placeholder_mismatch(
-                Some(ty::Region::new_var(self.tcx(), *vid)),
-                cause,
-                None,
-                Some(*sup_placeholder),
-                values,
-            ),
-
-            Some(RegionResolutionError::SubSupConflict(
-                vid,
-                _,
-                _,
-                _,
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
-                _,
-            )) => self.try_report_trait_placeholder_mismatch(
-                Some(ty::Region::new_var(self.tcx(), *vid)),
-                cause,
-                None,
-                Some(*sup_placeholder),
-                values,
-            ),
-
-            Some(RegionResolutionError::UpperBoundUniverseConflict(
-                vid,
-                _,
-                _,
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
-            )) => self.try_report_trait_placeholder_mismatch(
-                Some(ty::Region::new_var(self.tcx(), *vid)),
-                cause,
-                None,
-                Some(*sup_placeholder),
-                values,
-            ),
-
-            Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sub_region @ Region(Interned(RePlaceholder(_), _)),
-                sup_region @ Region(Interned(RePlaceholder(_), _)),
-            )) => self.try_report_trait_placeholder_mismatch(
-                None,
-                cause,
-                Some(*sub_region),
-                Some(*sup_region),
-                values,
-            ),
-
-            Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sub_region @ Region(Interned(RePlaceholder(_), _)),
-                sup_region,
-            )) => self.try_report_trait_placeholder_mismatch(
-                (!sup_region.has_name()).then_some(*sup_region),
-                cause,
-                Some(*sub_region),
-                None,
-                values,
-            ),
-
-            Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
-                sub_region,
-                sup_region @ Region(Interned(RePlaceholder(_), _)),
-            )) => self.try_report_trait_placeholder_mismatch(
-                (!sub_region.has_name()).then_some(*sub_region),
-                cause,
-                None,
-                Some(*sup_region),
-                values,
-            ),
-
-            _ => None,
-        }
-    }
-
-    fn try_report_trait_placeholder_mismatch(
-        &self,
-        vid: Option<Region<'tcx>>,
-        cause: &ObligationCause<'tcx>,
-        sub_placeholder: Option<Region<'tcx>>,
-        sup_placeholder: Option<Region<'tcx>>,
-        value_pairs: &ValuePairs<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        let (expected_args, found_args, trait_def_id) = match value_pairs {
-            ValuePairs::TraitRefs(ExpectedFound { expected, found })
-                if expected.def_id == found.def_id =>
-            {
-                // It's possible that the placeholders come from a binder
-                // outside of this value pair. Use `no_bound_vars` as a
-                // simple heuristic for that.
-                (expected.args, found.args, expected.def_id)
-            }
-            _ => return None,
-        };
-
-        Some(self.report_trait_placeholder_mismatch(
-            vid,
-            cause,
-            sub_placeholder,
-            sup_placeholder,
-            trait_def_id,
-            expected_args,
-            found_args,
-        ))
-    }
-
-    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
-    //   --> /home/nmatsakis/tmp/foo.rs:12:5
-    //    |
-    // 12 |     all::<&'static u32>();
-    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
-    //    |
-    //    = note: Due to a where-clause on the function `all`,
-    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
-    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
-    #[instrument(level = "debug", skip(self))]
-    fn report_trait_placeholder_mismatch(
-        &self,
-        vid: Option<Region<'tcx>>,
-        cause: &ObligationCause<'tcx>,
-        sub_placeholder: Option<Region<'tcx>>,
-        sup_placeholder: Option<Region<'tcx>>,
-        trait_def_id: DefId,
-        expected_args: GenericArgsRef<'tcx>,
-        actual_args: GenericArgsRef<'tcx>,
-    ) -> Diag<'tcx> {
-        let span = cause.span();
-
-        let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
-            if let ObligationCauseCode::WhereClause(def_id, span)
-            | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code()
-                && def_id != CRATE_DEF_ID.to_def_id()
-            {
-                (
-                    true,
-                    Some(span),
-                    Some(self.tcx().def_span(def_id)),
-                    None,
-                    self.tcx().def_path_str(def_id),
-                )
-            } else {
-                (false, None, None, Some(span), String::new())
-            };
-
-        let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
-            self.cx.tcx,
-            trait_def_id,
-            expected_args,
-        ));
-        let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
-            self.cx.tcx,
-            trait_def_id,
-            actual_args,
-        ));
-
-        // Search the expected and actual trait references to see (a)
-        // whether the sub/sup placeholders appear in them (sometimes
-        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
-        // placeholder was created as part of an inner type) and (b)
-        // whether the inference variable appears. In each case,
-        // assign a counter value in each case if so.
-        let mut counter = 0;
-        let mut has_sub = None;
-        let mut has_sup = None;
-
-        let mut actual_has_vid = None;
-        let mut expected_has_vid = None;
-
-        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
-            if Some(r) == sub_placeholder && has_sub.is_none() {
-                has_sub = Some(counter);
-                counter += 1;
-            } else if Some(r) == sup_placeholder && has_sup.is_none() {
-                has_sup = Some(counter);
-                counter += 1;
-            }
-
-            if Some(r) == vid && expected_has_vid.is_none() {
-                expected_has_vid = Some(counter);
-                counter += 1;
-            }
-        });
-
-        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
-            if Some(r) == vid && actual_has_vid.is_none() {
-                actual_has_vid = Some(counter);
-                counter += 1;
-            }
-        });
-
-        let actual_self_ty_has_vid =
-            self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
-
-        let expected_self_ty_has_vid =
-            self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
-
-        let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
-
-        debug!(
-            ?actual_has_vid,
-            ?expected_has_vid,
-            ?has_sub,
-            ?has_sup,
-            ?actual_self_ty_has_vid,
-            ?expected_self_ty_has_vid,
-        );
-
-        let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
-            sub_placeholder,
-            sup_placeholder,
-            has_sub,
-            has_sup,
-            expected_trait_ref,
-            actual_trait_ref,
-            vid,
-            expected_has_vid,
-            actual_has_vid,
-            any_self_ty_has_vid,
-            leading_ellipsis,
-        );
-
-        self.tcx().dcx().create_err(TraitPlaceholderMismatch {
-            span,
-            satisfy_span,
-            where_span,
-            dup_span,
-            def_id,
-            trait_def_id: self.tcx().def_path_str(trait_def_id),
-            actual_impl_expl_notes,
-        })
-    }
-
-    /// Add notes with details about the expected and actual trait refs, with attention to cases
-    /// when placeholder regions are involved: either the trait or the self type containing
-    /// them needs to be mentioned the closest to the placeholders.
-    /// This makes the error messages read better, however at the cost of some complexity
-    /// due to the number of combinations we have to deal with.
-    fn explain_actual_impl_that_was_found(
-        &self,
-        sub_placeholder: Option<Region<'tcx>>,
-        sup_placeholder: Option<Region<'tcx>>,
-        has_sub: Option<usize>,
-        has_sup: Option<usize>,
-        expected_trait_ref: ty::TraitRef<'tcx>,
-        actual_trait_ref: ty::TraitRef<'tcx>,
-        vid: Option<Region<'tcx>>,
-        expected_has_vid: Option<usize>,
-        actual_has_vid: Option<usize>,
-        any_self_ty_has_vid: bool,
-        leading_ellipsis: bool,
-    ) -> Vec<ActualImplExplNotes<'tcx>> {
-        // The weird thing here with the `maybe_highlighting_region` calls and the
-        // the match inside is meant to be like this:
-        //
-        // - The match checks whether the given things (placeholders, etc) appear
-        //   in the types are about to print
-        // - Meanwhile, the `maybe_highlighting_region` calls set up
-        //   highlights so that, if they do appear, we will replace
-        //   them `'0` and whatever. (This replacement takes place
-        //   inside the closure given to `maybe_highlighting_region`.)
-        //
-        // There is some duplication between the calls -- i.e., the
-        // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
-        // None, an then we check again inside the closure, but this
-        // setup sort of minimized the number of calls and so form.
-
-        let highlight_trait_ref = |trait_ref| Highlighted {
-            tcx: self.tcx(),
-            highlight: RegionHighlightMode::default(),
-            value: trait_ref,
-        };
-
-        let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
-
-        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
-        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
-        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
-
-        let passive_voice = match (has_sub, has_sup) {
-            (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
-            (None, None) => {
-                expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
-                match expected_has_vid {
-                    Some(_) => true,
-                    None => any_self_ty_has_vid,
-                }
-            }
-        };
-
-        let (kind, ty_or_sig, trait_path) = if same_self_type {
-            let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
-            self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
-
-            if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
-            {
-                let closure_sig = self_ty.map(|closure| {
-                    if let ty::Closure(_, args) = closure.kind() {
-                        self.tcx()
-                            .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
-                    } else {
-                        bug!("type is not longer closure");
-                    }
-                });
-                (
-                    ActualImplExpectedKind::Signature,
-                    TyOrSig::ClosureSig(closure_sig),
-                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-                )
-            } else {
-                (
-                    ActualImplExpectedKind::Other,
-                    TyOrSig::Ty(self_ty),
-                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-                )
-            }
-        } else if passive_voice {
-            (
-                ActualImplExpectedKind::Passive,
-                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
-                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-            )
-        } else {
-            (
-                ActualImplExpectedKind::Other,
-                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
-                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-            )
-        };
-
-        let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
-            (Some(n1), Some(n2)) => {
-                (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
-            }
-            (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
-            (None, None) => {
-                if let Some(n) = expected_has_vid {
-                    (ActualImplExpectedLifetimeKind::Some, n, 0)
-                } else {
-                    (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
-                }
-            }
-        };
-
-        let note_1 = ActualImplExplNotes::new_expected(
-            kind,
-            lt_kind,
-            leading_ellipsis,
-            ty_or_sig,
-            trait_path,
-            lifetime_1,
-            lifetime_2,
-        );
-
-        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
-        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
-
-        let passive_voice = match actual_has_vid {
-            Some(_) => any_self_ty_has_vid,
-            None => true,
-        };
-
-        let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
-        let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
-        let has_lifetime = actual_has_vid.is_some();
-        let lifetime = actual_has_vid.unwrap_or_default();
-
-        let note_2 = if same_self_type {
-            ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
-        } else if passive_voice {
-            ActualImplExplNotes::ButActuallyImplementedForTy {
-                trait_path,
-                ty,
-                has_lifetime,
-                lifetime,
-            }
-        } else {
-            ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
-        };
-
-        vec![note_1, note_2]
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
deleted file mode 100644
index e9f17a3e3e2..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::PlaceholderRelationLfNotSatisfied;
-use crate::infer::{RegionResolutionError, SubregionOrigin};
-use rustc_data_structures::intern::Interned;
-use rustc_errors::Diag;
-use rustc_middle::ty::{self, RePlaceholder, Region};
-
-impl<'tcx> NiceRegionError<'_, 'tcx> {
-    /// Emitted wwhen given a `ConcreteFailure` when relating two placeholders.
-    pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> {
-        match &self.error {
-            Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::RelateRegionParamBound(span),
-                Region(Interned(
-                    RePlaceholder(ty::Placeholder {
-                        bound: ty::BoundRegion { kind: sub_name, .. },
-                        ..
-                    }),
-                    _,
-                )),
-                Region(Interned(
-                    RePlaceholder(ty::Placeholder {
-                        bound: ty::BoundRegion { kind: sup_name, .. },
-                        ..
-                    }),
-                    _,
-                )),
-            )) => {
-                let span = *span;
-                let (sub_span, sub_symbol) = match sub_name {
-                    ty::BrNamed(def_id, symbol) => {
-                        (Some(self.tcx().def_span(def_id)), Some(symbol))
-                    }
-                    ty::BrAnon | ty::BrEnv => (None, None),
-                };
-                let (sup_span, sup_symbol) = match sup_name {
-                    ty::BrNamed(def_id, symbol) => {
-                        (Some(self.tcx().def_span(def_id)), Some(symbol))
-                    }
-                    ty::BrAnon | ty::BrEnv => (None, None),
-                };
-                let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
-                    (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
-                        PlaceholderRelationLfNotSatisfied::HasBoth {
-                            span,
-                            sub_span,
-                            sup_span,
-                            sub_symbol,
-                            sup_symbol,
-                            note: (),
-                        }
-                    }
-                    (Some(sub_span), Some(sup_span), _, Some(&sup_symbol)) => {
-                        PlaceholderRelationLfNotSatisfied::HasSup {
-                            span,
-                            sub_span,
-                            sup_span,
-                            sup_symbol,
-                            note: (),
-                        }
-                    }
-                    (Some(sub_span), Some(sup_span), Some(&sub_symbol), _) => {
-                        PlaceholderRelationLfNotSatisfied::HasSub {
-                            span,
-                            sub_span,
-                            sup_span,
-                            sub_symbol,
-                            note: (),
-                        }
-                    }
-                    (Some(sub_span), Some(sup_span), _, _) => {
-                        PlaceholderRelationLfNotSatisfied::HasNone {
-                            span,
-                            sub_span,
-                            sup_span,
-                            note: (),
-                        }
-                    }
-                    _ => PlaceholderRelationLfNotSatisfied::OnlyPrimarySpan { span, note: () },
-                };
-                Some(self.tcx().dcx().create_err(diag))
-            }
-            _ => None,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
deleted file mode 100644
index ce157ff3dc8..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ /dev/null
@@ -1,618 +0,0 @@
-//! Error Reporting for static impl Traits.
-
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{
-    ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted,
-    ReqIntroducedLocations,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic};
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::{
-    self as hir, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime,
-    LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
-};
-use rustc_middle::ty::{
-    self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
-};
-use rustc_span::symbol::Ident;
-use rustc_span::Span;
-
-use rustc_span::def_id::LocalDefId;
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// Print the error message for lifetime errors when the return type is a static `impl Trait`,
-    /// `dyn Trait` or if a method call on a trait object introduces a static requirement.
-    pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
-        debug!("try_report_static_impl_trait(error={:?})", self.error);
-        let tcx = self.tcx();
-        let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
-            RegionResolutionError::SubSupConflict(
-                _,
-                var_origin,
-                sub_origin,
-                sub_r,
-                sup_origin,
-                sup_r,
-                spans,
-            ) if sub_r.is_static() => (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans),
-            RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
-                sub_r,
-                sup_r,
-            ) if sub_r.is_static() => {
-                // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
-                if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
-                    // This may have a closure and it would cause ICE
-                    // through `find_param_with_region` (#78262).
-                    let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
-                    let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
-                    if fn_returns.is_empty() {
-                        return None;
-                    }
-
-                    let param = self.find_param_with_region(*sup_r, *sub_r)?;
-                    let simple_ident = param.param.pat.simple_ident();
-
-                    let (has_impl_path, impl_path) = match ctxt.assoc_item.container {
-                        AssocItemContainer::TraitContainer => {
-                            let id = ctxt.assoc_item.container_id(tcx);
-                            (true, tcx.def_path_str(id))
-                        }
-                        AssocItemContainer::ImplContainer => (false, String::new()),
-                    };
-
-                    let mut err = self.tcx().dcx().create_err(ButCallingIntroduces {
-                        param_ty_span: param.param_ty_span,
-                        cause_span: cause.span,
-                        has_param_name: simple_ident.is_some(),
-                        param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
-                        has_lifetime: sup_r.has_name(),
-                        lifetime: sup_r.to_string(),
-                        assoc_item: ctxt.assoc_item.name,
-                        has_impl_path,
-                        impl_path,
-                    });
-                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt) {
-                        let reported = err.emit();
-                        return Some(reported);
-                    } else {
-                        err.cancel()
-                    }
-                }
-                return None;
-            }
-            _ => return None,
-        };
-        debug!(
-            "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
-            var_origin, sub_origin, sub_r, sup_origin, sup_r
-        );
-        let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
-        debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
-        let sp = var_origin.span();
-        let return_sp = sub_origin.span();
-        let param = self.find_param_with_region(*sup_r, *sub_r)?;
-        let simple_ident = param.param.pat.simple_ident();
-        let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
-
-        let (mention_influencer, influencer_point) =
-            if sup_origin.span().overlaps(param.param_ty_span) {
-                // Account for `async fn` like in `async-await/issues/issue-62097.rs`.
-                // The desugaring of `async fn`s causes `sup_origin` and `param` to point at the same
-                // place (but with different `ctxt`, hence `overlaps` instead of `==` above).
-                //
-                // This avoids the following:
-                //
-                // LL |     pub async fn run_dummy_fn(&self) {
-                //    |                               ^^^^^
-                //    |                               |
-                //    |                               this data with an anonymous lifetime `'_`...
-                //    |                               ...is captured here...
-                (false, sup_origin.span())
-            } else {
-                (!sup_origin.span().overlaps(return_sp), param.param_ty_span)
-            };
-
-        debug!("try_report_static_impl_trait: param_info={:?}", param);
-
-        let mut spans = spans.clone();
-
-        if mention_influencer {
-            spans.push(sup_origin.span());
-        }
-        // We dedup the spans *ignoring* expansion context.
-        spans.sort();
-        spans.dedup_by_key(|span| (span.lo(), span.hi()));
-
-        // We try to make the output have fewer overlapping spans if possible.
-        let require_span =
-            if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
-
-        let spans_empty = spans.is_empty();
-        let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp);
-        let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
-            Some(*bound)
-        } else {
-            None
-        };
-
-        let mut subdiag = None;
-
-        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
-            if let ObligationCauseCode::ReturnValue(hir_id)
-            | ObligationCauseCode::BlockTailExpression(hir_id, ..) = cause.code()
-            {
-                let parent_id = tcx.hir().get_parent_item(*hir_id);
-                if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {
-                    let mut span: MultiSpan = fn_decl.output.span().into();
-                    let mut spans = Vec::new();
-                    let mut add_label = true;
-                    if let hir::FnRetTy::Return(ty) = fn_decl.output {
-                        let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
-                        v.visit_ty(ty);
-                        if !v.0.is_empty() {
-                            span = v.0.clone().into();
-                            spans = v.0;
-                            add_label = false;
-                        }
-                    }
-                    let fn_decl_span = fn_decl.output.span();
-
-                    subdiag = Some(ReqIntroducedLocations {
-                        span,
-                        spans,
-                        fn_decl_span,
-                        cause_span: cause.span,
-                        add_label,
-                    });
-                }
-            }
-        }
-
-        let diag = ButNeedsToSatisfy {
-            sp,
-            influencer_point,
-            spans: spans.clone(),
-            // If any of the "captured here" labels appears on the same line or after
-            // `require_span`, we put it on a note to ensure the text flows by appearing
-            // always at the end.
-            require_span_as_note: require_as_note.then_some(require_span),
-            // We don't need a note, it's already at the end, it can be shown as a `span_label`.
-            require_span_as_label: (!require_as_note).then_some(require_span),
-            req_introduces_loc: subdiag,
-
-            has_lifetime: sup_r.has_name(),
-            lifetime: lifetime_name.clone(),
-            has_param_name: simple_ident.is_some(),
-            param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
-            spans_empty,
-            bound,
-        };
-
-        let mut err = self.tcx().dcx().create_err(diag);
-
-        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
-
-        let mut override_error_code = None;
-        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin
-            && let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code()
-            // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
-            // `'static` lifetime when called as a method on a binding: `bar.qux()`.
-            && self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt)
-        {
-            override_error_code = Some(ctxt.assoc_item.name);
-        }
-
-        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin
-            && let code = match cause.code() {
-                ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
-                _ => cause.code(),
-            }
-            && let (
-                &ObligationCauseCode::WhereClause(item_def_id, _)
-                | &ObligationCauseCode::WhereClauseInExpr(item_def_id, ..),
-                None,
-            ) = (code, override_error_code)
-        {
-            // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
-            // lifetime as above, but called using a fully-qualified path to the method:
-            // `Foo::qux(bar)`.
-            let mut v = TraitObjectVisitor(FxIndexSet::default());
-            v.visit_ty(param.param_ty);
-            if let Some((ident, self_ty)) =
-                NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, item_def_id, &v.0)
-                && self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
-            {
-                override_error_code = Some(ident.name);
-            }
-        }
-        if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
-            // Provide a more targeted error code and description.
-            let retarget_subdiag = MoreTargeted { ident };
-            retarget_subdiag.add_to_diag(&mut err);
-        }
-
-        let arg = match param.param.pat.simple_ident() {
-            Some(simple_ident) => format!("argument `{simple_ident}`"),
-            None => "the argument".to_string(),
-        };
-        let captures = format!("captures data from {arg}");
-        suggest_new_region_bound(
-            tcx,
-            &mut err,
-            fn_returns,
-            lifetime_name,
-            Some(arg),
-            captures,
-            Some((param.param_ty_span, param.param_ty.to_string())),
-            Some(anon_reg_sup.def_id),
-        );
-
-        let reported = err.emit();
-        Some(reported)
-    }
-}
-
-pub fn suggest_new_region_bound(
-    tcx: TyCtxt<'_>,
-    err: &mut Diag<'_>,
-    fn_returns: Vec<&rustc_hir::Ty<'_>>,
-    lifetime_name: String,
-    arg: Option<String>,
-    captures: String,
-    param: Option<(Span, String)>,
-    scope_def_id: Option<LocalDefId>,
-) {
-    debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
-    // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-    let consider = "consider changing";
-    let declare = "to declare that";
-    let explicit = format!("you can add an explicit `{lifetime_name}` lifetime bound");
-    let explicit_static =
-        arg.map(|arg| format!("explicit `'static` bound to the lifetime of {arg}"));
-    let add_static_bound = "alternatively, add an explicit `'static` bound to this reference";
-    let plus_lt = format!(" + {lifetime_name}");
-    for fn_return in fn_returns {
-        if fn_return.span.desugaring_kind().is_some() {
-            // Skip `async` desugaring `impl Future`.
-            continue;
-        }
-        match fn_return.kind {
-            // FIXME(precise_captures): Suggest adding to `use<...>` list instead.
-            TyKind::OpaqueDef(item_id, _, _) => {
-                let item = tcx.hir().item(item_id);
-                let ItemKind::OpaqueTy(opaque) = &item.kind else {
-                    return;
-                };
-
-                // Get the identity type for this RPIT
-                let did = item_id.owner_id.to_def_id();
-                let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did));
-
-                if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
-                    GenericBound::Outlives(Lifetime {
-                        res: LifetimeName::Static, ident, ..
-                    }) => Some(ident.span),
-                    _ => None,
-                }) {
-                    if let Some(explicit_static) = &explicit_static {
-                        err.span_suggestion_verbose(
-                            span,
-                            format!("{consider} `{ty}`'s {explicit_static}"),
-                            &lifetime_name,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    if let Some((param_span, ref param_ty)) = param {
-                        err.span_suggestion_verbose(
-                            param_span,
-                            add_static_bound,
-                            param_ty,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                } else if opaque.bounds.iter().any(|arg| {
-                    matches!(arg,
-                        GenericBound::Outlives(Lifetime { ident, .. })
-                        if ident.name.to_string() == lifetime_name )
-                }) {
-                } else {
-                    // get a lifetime name of existing named lifetimes if any
-                    let existing_lt_name = if let Some(id) = scope_def_id
-                        && let Some(generics) = tcx.hir().get_generics(id)
-                        && let named_lifetimes = generics
-                            .params
-                            .iter()
-                            .filter(|p| {
-                                matches!(
-                                    p.kind,
-                                    GenericParamKind::Lifetime {
-                                        kind: hir::LifetimeParamKind::Explicit
-                                    }
-                                )
-                            })
-                            .map(|p| {
-                                if let hir::ParamName::Plain(name) = p.name {
-                                    Some(name.to_string())
-                                } else {
-                                    None
-                                }
-                            })
-                            .filter(|n| !matches!(n, None))
-                            .collect::<Vec<_>>()
-                        && named_lifetimes.len() > 0
-                    {
-                        named_lifetimes[0].clone()
-                    } else {
-                        None
-                    };
-                    let name = if let Some(name) = &existing_lt_name { name } else { "'a" };
-                    // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used.
-                    // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any
-                    if let Some(id) = scope_def_id
-                        && let Some(generics) = tcx.hir().get_generics(id)
-                        && let mut spans_suggs =
-                            make_elided_region_spans_suggs(name, generics.params.iter())
-                        && spans_suggs.len() > 1
-                    {
-                        let use_lt = if existing_lt_name == None {
-                            spans_suggs.push((generics.span.shrink_to_hi(), format!("<{name}>")));
-                            format!("you can introduce a named lifetime parameter `{name}`")
-                        } else {
-                            // make use the existing named lifetime
-                            format!("you can use the named lifetime parameter `{name}`")
-                        };
-                        spans_suggs.push((fn_return.span.shrink_to_hi(), format!(" + {name} ")));
-                        err.multipart_suggestion_verbose(
-                            format!("{declare} `{ty}` {captures}, {use_lt}",),
-                            spans_suggs,
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        err.span_suggestion_verbose(
-                            fn_return.span.shrink_to_hi(),
-                            format!("{declare} `{ty}` {captures}, {explicit}",),
-                            &plus_lt,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-            TyKind::TraitObject(_, lt, _) => {
-                if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
-                    err.span_suggestion_verbose(
-                        fn_return.span.shrink_to_hi(),
-                        format!("{declare} the trait object {captures}, {explicit}",),
-                        &plus_lt,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else if lt.ident.name.to_string() != lifetime_name {
-                    // With this check we avoid suggesting redundant bounds. This
-                    // would happen if there are nested impl/dyn traits and only
-                    // one of them has the bound we'd suggest already there, like
-                    // in `impl Foo<X = dyn Bar> + '_`.
-                    if let Some(explicit_static) = &explicit_static {
-                        err.span_suggestion_verbose(
-                            lt.ident.span,
-                            format!("{consider} the trait object's {explicit_static}"),
-                            &lifetime_name,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    if let Some((param_span, param_ty)) = param.clone() {
-                        err.span_suggestion_verbose(
-                            param_span,
-                            add_static_bound,
-                            param_ty,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
-}
-
-fn make_elided_region_spans_suggs<'a>(
-    name: &str,
-    generic_params: impl Iterator<Item = &'a GenericParam<'a>>,
-) -> Vec<(Span, String)> {
-    let mut spans_suggs = Vec::new();
-    let mut bracket_span = None;
-    let mut consecutive_brackets = 0;
-
-    let mut process_consecutive_brackets =
-        |span: Option<Span>, spans_suggs: &mut Vec<(Span, String)>| {
-            if span
-                .is_some_and(|span| bracket_span.map_or(true, |bracket_span| span == bracket_span))
-            {
-                consecutive_brackets += 1;
-            } else if let Some(bracket_span) = bracket_span.take() {
-                let sugg = std::iter::once("<")
-                    .chain(std::iter::repeat(name).take(consecutive_brackets).intersperse(", "))
-                    .chain([">"])
-                    .collect();
-                spans_suggs.push((bracket_span.shrink_to_hi(), sugg));
-                consecutive_brackets = 0;
-            }
-            bracket_span = span;
-        };
-
-    for p in generic_params {
-        if let GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(kind) } = p.kind {
-            match kind {
-                MissingLifetimeKind::Underscore => {
-                    process_consecutive_brackets(None, &mut spans_suggs);
-                    spans_suggs.push((p.span, name.to_string()))
-                }
-                MissingLifetimeKind::Ampersand => {
-                    process_consecutive_brackets(None, &mut spans_suggs);
-                    spans_suggs.push((p.span.shrink_to_hi(), format!("{name} ")));
-                }
-                MissingLifetimeKind::Comma => {
-                    process_consecutive_brackets(None, &mut spans_suggs);
-                    spans_suggs.push((p.span.shrink_to_hi(), format!("{name}, ")));
-                }
-                MissingLifetimeKind::Brackets => {
-                    process_consecutive_brackets(Some(p.span), &mut spans_suggs);
-                }
-            }
-        }
-    }
-    process_consecutive_brackets(None, &mut spans_suggs);
-
-    spans_suggs
-}
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    pub fn get_impl_ident_and_self_ty_from_trait(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        trait_objects: &FxIndexSet<DefId>,
-    ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
-        match tcx.hir().get_if_local(def_id)? {
-            Node::ImplItem(impl_item) => {
-                let impl_did = tcx.hir().get_parent_item(impl_item.hir_id());
-                if let hir::OwnerNode::Item(Item {
-                    kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
-                    ..
-                }) = tcx.hir_owner_node(impl_did)
-                {
-                    Some((impl_item.ident, self_ty))
-                } else {
-                    None
-                }
-            }
-            Node::TraitItem(trait_item) => {
-                let trait_id = tcx.hir().get_parent_item(trait_item.hir_id());
-                debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait);
-                // The method being called is defined in the `trait`, but the `'static`
-                // obligation comes from the `impl`. Find that `impl` so that we can point
-                // at it in the suggestion.
-                let trait_did = trait_id.to_def_id();
-                tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
-                    if let Node::Item(Item {
-                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
-                    }) = tcx.hir_node_by_def_id(impl_did)
-                        && trait_objects.iter().all(|did| {
-                            // FIXME: we should check `self_ty` against the receiver
-                            // type in the `UnifyReceiver` context, but for now, use
-                            // this imperfect proxy. This will fail if there are
-                            // multiple `impl`s for the same trait like
-                            // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
-                            // In that case, only the first one will get suggestions.
-                            let mut traits = vec![];
-                            let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
-                            hir_v.visit_ty(self_ty);
-                            !traits.is_empty()
-                        })
-                    {
-                        Some((trait_item.ident, *self_ty))
-                    } else {
-                        None
-                    }
-                })
-            }
-            _ => None,
-        }
-    }
-
-    /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
-    /// `'static` obligation. Suggest relaxing that implicit bound.
-    fn find_impl_on_dyn_trait(
-        &self,
-        err: &mut Diag<'_>,
-        ty: Ty<'_>,
-        ctxt: &UnifyReceiverContext<'tcx>,
-    ) -> bool {
-        let tcx = self.tcx();
-
-        // Find the method being called.
-        let Ok(Some(instance)) = ty::Instance::try_resolve(
-            tcx,
-            ctxt.param_env,
-            ctxt.assoc_item.def_id,
-            self.cx.resolve_vars_if_possible(ctxt.args),
-        ) else {
-            return false;
-        };
-
-        let mut v = TraitObjectVisitor(FxIndexSet::default());
-        v.visit_ty(ty);
-
-        // Get the `Ident` of the method being called and the corresponding `impl` (to point at
-        // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
-        let Some((ident, self_ty)) =
-            NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0)
-        else {
-            return false;
-        };
-
-        // Find the trait object types in the argument, so we point at *only* the trait object.
-        self.suggest_constrain_dyn_trait_in_impl(err, &v.0, ident, self_ty)
-    }
-
-    fn suggest_constrain_dyn_trait_in_impl(
-        &self,
-        err: &mut Diag<'_>,
-        found_dids: &FxIndexSet<DefId>,
-        ident: Ident,
-        self_ty: &hir::Ty<'_>,
-    ) -> bool {
-        let mut suggested = false;
-        for found_did in found_dids {
-            let mut traits = vec![];
-            let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
-            hir_v.visit_ty(self_ty);
-            for &span in &traits {
-                let subdiag = DynTraitConstraintSuggestion { span, ident };
-                subdiag.add_to_diag(err);
-                suggested = true;
-            }
-        }
-        suggested
-    }
-}
-
-/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
-pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
-
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
-    fn visit_ty(&mut self, t: Ty<'tcx>) {
-        match t.kind() {
-            ty::Dynamic(preds, re, _) if re.is_static() => {
-                if let Some(def_id) = preds.principal_def_id() {
-                    self.0.insert(def_id);
-                }
-            }
-            _ => t.super_visit_with(self),
-        }
-    }
-}
-
-/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
-pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
-
-impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
-    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
-        if let TyKind::TraitObject(
-            poly_trait_refs,
-            Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. },
-            _,
-        ) = t.kind
-        {
-            for ptr in poly_trait_refs {
-                if Some(self.1) == ptr.trait_ref.trait_def_id() {
-                    self.0.push(ptr.span);
-                }
-            }
-        }
-        walk_ty(self, t);
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
deleted file mode 100644
index c58c7e13551..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
-
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
-use crate::infer::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::Visitor;
-use rustc_middle::hir::nested_filter;
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::RegionHighlightMode;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
-use rustc_span::Span;
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
-    pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuaranteed> {
-        let error = self.error.as_ref()?;
-        debug!("try_report_impl_not_conforming_to_trait {:?}", error);
-        if let RegionResolutionError::SubSupConflict(
-            _,
-            var_origin,
-            sub_origin,
-            _sub,
-            sup_origin,
-            _sup,
-            _,
-        ) = error.clone()
-            && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
-            && let ObligationCauseCode::CompareImplItem { trait_item_def_id, .. } =
-                sub_trace.cause.code()
-            && sub_trace.values == sup_trace.values
-            && let ValuePairs::PolySigs(ExpectedFound { expected, found }) = sub_trace.values
-        {
-            // FIXME(compiler-errors): Don't like that this needs `Ty`s, but
-            // all of the region highlighting machinery only deals with those.
-            let guar = self.emit_err(
-                var_origin.span(),
-                Ty::new_fn_ptr(self.cx.tcx, expected),
-                Ty::new_fn_ptr(self.cx.tcx, found),
-                *trait_item_def_id,
-            );
-            return Some(guar);
-        }
-        None
-    }
-
-    fn emit_err(
-        &self,
-        sp: Span,
-        expected: Ty<'tcx>,
-        found: Ty<'tcx>,
-        trait_def_id: DefId,
-    ) -> ErrorGuaranteed {
-        let trait_sp = self.tcx().def_span(trait_def_id);
-
-        // Mark all unnamed regions in the type with a number.
-        // This diagnostic is called in response to lifetime errors, so be informative.
-        struct HighlightBuilder<'tcx> {
-            highlight: RegionHighlightMode<'tcx>,
-            counter: usize,
-        }
-
-        impl<'tcx> HighlightBuilder<'tcx> {
-            fn build(ty: Ty<'tcx>) -> RegionHighlightMode<'tcx> {
-                let mut builder =
-                    HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1 };
-                builder.visit_ty(ty);
-                builder.highlight
-            }
-        }
-
-        impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> {
-            fn visit_region(&mut self, r: ty::Region<'tcx>) {
-                if !r.has_name() && self.counter <= 3 {
-                    self.highlight.highlighting_region(r, self.counter);
-                    self.counter += 1;
-                }
-            }
-        }
-
-        let expected_highlight = HighlightBuilder::build(expected);
-        let expected = self
-            .cx
-            .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
-            .name;
-        let found_highlight = HighlightBuilder::build(found);
-        let found =
-            self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
-
-        // Get the span of all the used type parameters in the method.
-        let assoc_item = self.tcx().associated_item(trait_def_id);
-        let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
-        match assoc_item.kind {
-            ty::AssocKind::Fn => {
-                let hir = self.tcx().hir();
-                if let Some(hir_id) =
-                    assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id))
-                {
-                    if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
-                        visitor.visit_fn_decl(decl);
-                    }
-                }
-            }
-            _ => {}
-        }
-
-        let diag = TraitImplDiff {
-            sp,
-            trait_sp,
-            note: (),
-            param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() },
-            rel_help: visitor.types.is_empty().then_some(RelationshipHelp),
-            expected,
-            found,
-        };
-
-        self.tcx().dcx().emit_err(diag)
-    }
-}
-
-struct TypeParamSpanVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    types: Vec<Span>,
-}
-
-impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
-        match arg.kind {
-            hir::TyKind::Ref(_, ref mut_ty) => {
-                // We don't want to suggest looking into borrowing `&T` or `&Self`.
-                hir::intravisit::walk_ty(self, mut_ty.ty);
-                return;
-            }
-            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
-                [segment]
-                    if matches!(
-                        segment.res,
-                        Res::SelfTyParam { .. }
-                            | Res::SelfTyAlias { .. }
-                            | Res::Def(hir::def::DefKind::TyParam, _)
-                    ) =>
-                {
-                    self.types.push(path.span);
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-        hir::intravisit::walk_ty(self, arg);
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs
deleted file mode 100644
index 30fa98c5526..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-//! Helper functions corresponding to lifetime errors due to
-//! anonymous regions.
-
-use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
-use rustc_span::Span;
-
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-
-/// Information about the anonymous region we are searching for.
-#[derive(Debug)]
-pub struct AnonymousParamInfo<'tcx> {
-    /// The parameter corresponding to the anonymous region.
-    pub param: &'tcx hir::Param<'tcx>,
-    /// The type corresponding to the anonymous region parameter.
-    pub param_ty: Ty<'tcx>,
-    /// The ty::BoundRegionKind corresponding to the anonymous region.
-    pub bound_region: ty::BoundRegionKind,
-    /// The `Span` of the parameter type.
-    pub param_ty_span: Span,
-    /// Signals that the argument is the first parameter in the declaration.
-    pub is_first: bool,
-}
-
-// This method walks the Type of the function body parameters using
-// `fold_regions()` function and returns the
-// &hir::Param of the function parameter corresponding to the anonymous
-// region and the Ty corresponding to the named region.
-// Currently only the case where the function declaration consists of
-// one named region and one anonymous region is handled.
-// Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
-// Here, we would return the hir::Param for y, we return the type &'a
-// i32, which is the type of y but with the anonymous region replaced
-// with 'a, the corresponding bound region and is_first which is true if
-// the hir::Param is the first parameter in the function declaration.
-#[instrument(skip(tcx), level = "debug")]
-pub fn find_param_with_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    generic_param_scope: LocalDefId,
-    anon_region: Region<'tcx>,
-    replace_region: Region<'tcx>,
-) -> Option<AnonymousParamInfo<'tcx>> {
-    let (id, bound_region) = match *anon_region {
-        ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
-        ty::ReEarlyParam(ebr) => {
-            let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id;
-            (tcx.parent(region_def), ty::BoundRegionKind::BrNamed(region_def, ebr.name))
-        }
-        _ => return None, // not a free region
-    };
-
-    let hir = &tcx.hir();
-    let def_id = id.as_local()?;
-
-    // FIXME: use def_kind
-    // Don't perform this on closures
-    match tcx.hir_node_by_def_id(generic_param_scope) {
-        hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
-            return None;
-        }
-        _ => {}
-    }
-
-    let body = hir.maybe_body_owned_by(def_id)?;
-
-    let owner_id = hir.body_owner(body.id());
-    let fn_decl = hir.fn_decl_by_hir_id(owner_id)?;
-    let poly_fn_sig = tcx.fn_sig(id).instantiate_identity();
-
-    let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
-    body.params
-        .iter()
-        .take(if fn_sig.c_variadic {
-            fn_sig.inputs().len()
-        } else {
-            assert_eq!(fn_sig.inputs().len(), body.params.len());
-            body.params.len()
-        })
-        .enumerate()
-        .find_map(|(index, param)| {
-            // May return None; sometimes the tables are not yet populated.
-            let ty = fn_sig.inputs()[index];
-            let mut found_anon_region = false;
-            let new_param_ty = tcx.fold_regions(ty, |r, _| {
-                if r == anon_region {
-                    found_anon_region = true;
-                    replace_region
-                } else {
-                    r
-                }
-            });
-            found_anon_region.then(|| {
-                let ty_hir_id = fn_decl.inputs[index].hir_id;
-                let param_ty_span = hir.span(ty_hir_id);
-                let is_first = index == 0;
-                AnonymousParamInfo {
-                    param,
-                    param_ty: new_param_ty,
-                    param_ty_span,
-                    bound_region,
-                    is_first,
-                }
-            })
-        })
-}
-
-impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    pub(super) fn find_param_with_region(
-        &self,
-        anon_region: Region<'tcx>,
-        replace_region: Region<'tcx>,
-    ) -> Option<AnonymousParamInfo<'tcx>> {
-        find_param_with_region(self.tcx(), self.generic_param_scope, anon_region, replace_region)
-    }
-
-    // Here, we check for the case where the anonymous region
-    // is in the return type as written by the user.
-    // FIXME(#42703) - Need to handle certain cases here.
-    pub(super) fn is_return_type_anon(
-        &self,
-        scope_def_id: LocalDefId,
-        br: ty::BoundRegionKind,
-        hir_sig: &hir::FnSig<'_>,
-    ) -> Option<Span> {
-        let fn_ty = self.tcx().type_of(scope_def_id).instantiate_identity();
-        if let ty::FnDef(_, _) = fn_ty.kind() {
-            let ret_ty = fn_ty.fn_sig(self.tcx()).output();
-            let span = hir_sig.decl.output.span();
-            let future_output = if hir_sig.header.is_async() {
-                ret_ty.map_bound(|ty| self.cx.get_impl_future_output_ty(ty)).transpose()
-            } else {
-                None
-            };
-            return match future_output {
-                Some(output) if self.includes_region(output, br) => Some(span),
-                None if self.includes_region(ret_ty, br) => Some(span),
-                _ => None,
-            };
-        }
-        None
-    }
-
-    fn includes_region(
-        &self,
-        ty: Binder<'tcx, impl TypeFoldable<TyCtxt<'tcx>>>,
-        region: ty::BoundRegionKind,
-    ) -> bool {
-        let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(ty);
-        // We are only checking is any region meets the condition so order doesn't matter
-        #[allow(rustc::potential_query_instability)]
-        late_bound_regions.iter().any(|r| *r == region)
-    }
-
-    // Here we check for the case where anonymous region
-    // corresponds to self and if yes, we display E0312.
-    // FIXME(#42700) - Need to format self properly to
-    // enable E0621 for it.
-    pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: LocalDefId) -> bool {
-        is_first
-            && self
-                .tcx()
-                .opt_associated_item(scope_def_id.to_def_id())
-                .is_some_and(|i| i.fn_has_self_parameter)
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/note.rs b/compiler/rustc_infer/src/error_reporting/infer/note.rs
deleted file mode 100644
index aeb3049c2ae..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/note.rs
+++ /dev/null
@@ -1,421 +0,0 @@
-use crate::error_reporting::infer::{note_and_explain_region, TypeErrCtxt};
-use crate::errors::{
-    note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
-    RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
-};
-use crate::fluent_generated as fluent;
-use crate::infer::{self, SubregionOrigin};
-use rustc_errors::{Diag, Subdiagnostic};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, IsSuggestable, Region, Ty};
-use rustc_span::symbol::kw;
-
-use super::ObligationCauseAsDiagArg;
-
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
-        match *origin {
-            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
-                span: trace.cause.span,
-                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
-            }
-            .add_to_diag(err),
-            infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
-            }
-            infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
-                    .add_to_diag(err);
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reference_outlives_referent,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diag(err);
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_relate_param_bound,
-                    name: &self.ty_to_string(ty),
-                    continues: opt_span.is_some(),
-                }
-                .add_to_diag(err);
-                if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diag(err);
-                }
-            }
-            infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diag(err);
-            }
-            infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diag(err);
-            }
-            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
-                self.note_region_origin(err, parent);
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                RegionOriginNote::Plain {
-                    span,
-                    msg: fluent::infer_ascribe_user_type_prove_predicate,
-                }
-                .add_to_diag(err);
-            }
-        }
-    }
-
-    pub(super) fn report_concrete_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> Diag<'a> {
-        let mut err = match origin {
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
-                let mut err = self.report_and_explain_type_error(trace, terr);
-                match (*sub, *sup) {
-                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
-                    (ty::RePlaceholder(_), _) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "",
-                            sup,
-                            " doesn't meet the lifetime requirements",
-                            None,
-                        );
-                    }
-                    (_, ty::RePlaceholder(_)) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "the required lifetime does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                    _ => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "",
-                            sup,
-                            "...",
-                            None,
-                        );
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "...does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                }
-                err
-            }
-            infer::Reborrow(span) => {
-                let reference_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::RefValidFor,
-                    note_and_explain::SuffixKind::Continues,
-                );
-                let content_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::ContentValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(OutlivesContent {
-                    span,
-                    notes: reference_valid.into_iter().chain(content_valid).collect(),
-                })
-            }
-            infer::RelateObjectBound(span) => {
-                let object_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::TypeObjValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let pointer_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::SourcePointerValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(OutlivesBound {
-                    span,
-                    notes: object_valid.into_iter().chain(pointer_valid).collect(),
-                })
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                let prefix = match *sub {
-                    ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
-                    _ => note_and_explain::PrefixKind::TypeOutlive,
-                };
-                let suffix = if opt_span.is_some() {
-                    note_and_explain::SuffixKind::ReqByBinding
-                } else {
-                    note_and_explain::SuffixKind::Empty
-                };
-                let note = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    opt_span,
-                    prefix,
-                    suffix,
-                );
-                self.dcx().create_err(FulfillReqLifetime {
-                    span,
-                    ty: self.resolve_vars_if_possible(ty),
-                    note,
-                })
-            }
-            infer::RelateRegionParamBound(span) => {
-                let param_instantiated = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::LfParamInstantiatedWith,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let param_must_outlive = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::LfParamMustOutlive,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(LfBoundNotSatisfied {
-                    span,
-                    notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
-                })
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                let pointer_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::PointerValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let data_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::DataValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(RefLongerThanData {
-                    span,
-                    ty: self.resolve_vars_if_possible(ty),
-                    notes: pointer_valid.into_iter().chain(data_valid).collect(),
-                })
-            }
-            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
-                let mut err = self.infcx.report_extra_impl_obligation(
-                    span,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    &format!("`{sup}: {sub}`"),
-                );
-                // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
-                if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
-                    && generics.where_clause_span.contains(span)
-                {
-                    self.suggest_copy_trait_method_bounds(
-                        trait_item_def_id,
-                        impl_item_def_id,
-                        &mut err,
-                    );
-                }
-                err
-            }
-            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
-                let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup);
-
-                // Don't mention the item name if it's an RPITIT, since that'll just confuse
-                // folks.
-                if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) {
-                    let trait_item_span = self.tcx.def_span(trait_item_def_id);
-                    let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                    err.span_label(
-                        trait_item_span,
-                        format!("definition of `{item_name}` from trait"),
-                    );
-                }
-
-                self.suggest_copy_trait_method_bounds(
-                    trait_item_def_id,
-                    impl_item_def_id,
-                    &mut err,
-                );
-                err
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                let instantiated = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::LfInstantiatedWith,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let must_outlive = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::LfMustOutlive,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(LfBoundNotSatisfied {
-                    span,
-                    notes: instantiated.into_iter().chain(must_outlive).collect(),
-                })
-            }
-        };
-        if sub.is_error() || sup.is_error() {
-            err.downgrade_to_delayed_bug();
-        }
-        err
-    }
-
-    pub fn suggest_copy_trait_method_bounds(
-        &self,
-        trait_item_def_id: DefId,
-        impl_item_def_id: LocalDefId,
-        err: &mut Diag<'_>,
-    ) {
-        // FIXME(compiler-errors): Right now this is only being used for region
-        // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
-        // but right now it's not really very smart when it comes to implicit `Sized`
-        // predicates and bounds on the trait itself.
-
-        let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
-        else {
-            return;
-        };
-        let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
-            return;
-        };
-        let trait_args = trait_ref
-            .instantiate_identity()
-            // Replace the explicit self type with `Self` for better suggestion rendering
-            .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
-            .args;
-        let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
-            .rebase_onto(self.tcx, impl_def_id, trait_args);
-
-        let Ok(trait_predicates) =
-            self.tcx
-                .explicit_predicates_of(trait_item_def_id)
-                .instantiate_own(self.tcx, trait_item_args)
-                .map(|(pred, _)| {
-                    if pred.is_suggestable(self.tcx, false) {
-                        Ok(pred.to_string())
-                    } else {
-                        Err(())
-                    }
-                })
-                .collect::<Result<Vec<_>, ()>>()
-        else {
-            return;
-        };
-
-        let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
-            return;
-        };
-
-        let suggestion = if trait_predicates.is_empty() {
-            WhereClauseSuggestions::Remove { span: generics.where_clause_span }
-        } else {
-            let space = if generics.where_clause_span.is_empty() { " " } else { "" };
-            WhereClauseSuggestions::CopyPredicates {
-                span: generics.where_clause_span,
-                space,
-                trait_predicates: trait_predicates.join(", "),
-            }
-        };
-        err.subdiagnostic(suggestion);
-    }
-
-    pub(super) fn report_placeholder_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        placeholder_origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> Diag<'a> {
-        // I can't think how to do better than this right now. -nikomatsakis
-        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
-        match placeholder_origin {
-            infer::Subtype(box ref trace)
-                if matches!(
-                    &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::WhereClause(..)
-                        | ObligationCauseCode::WhereClauseInExpr(..)
-                ) =>
-            {
-                // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::WhereClause(_, span)
-                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
-                    &trace.cause.code().peel_derives()
-                    && !span.is_dummy()
-                {
-                    let span = *span;
-                    self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
-                        .with_span_note(span, "the lifetime requirement is introduced here")
-                } else {
-                    unreachable!(
-                        "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
-                    )
-                }
-            }
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsPlaceholderMismatch;
-                return self.report_and_explain_type_error(trace, terr);
-            }
-            _ => {
-                return self.report_concrete_failure(
-                    generic_param_scope,
-                    placeholder_origin,
-                    sub,
-                    sup,
-                );
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs
deleted file mode 100644
index d5e7de897d0..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs
+++ /dev/null
@@ -1,940 +0,0 @@
-use super::TypeErrCtxt;
-use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
-use rustc_errors::{pluralize, Diag, MultiSpan};
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::Printer;
-use rustc_middle::{
-    traits::ObligationCause,
-    ty::{self, error::TypeError, print::FmtPrinter, suggest_constraining_type_param, Ty},
-};
-use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    pub fn note_and_explain_type_err(
-        &self,
-        diag: &mut Diag<'_>,
-        err: TypeError<'tcx>,
-        cause: &ObligationCause<'tcx>,
-        sp: Span,
-        body_owner_def_id: DefId,
-    ) {
-        debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
-
-        let tcx = self.tcx;
-
-        match err {
-            TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
-                match (*values.expected.kind(), *values.found.kind()) {
-                    (ty::Closure(..), ty::Closure(..)) => {
-                        diag.note("no two closures, even if identical, have the same type");
-                        diag.help("consider boxing your closure and/or using it as a trait object");
-                    }
-                    (ty::Coroutine(def_id1, ..), ty::Coroutine(def_id2, ..))
-                        if self.tcx.coroutine_is_async(def_id1)
-                            && self.tcx.coroutine_is_async(def_id2) =>
-                    {
-                        diag.note("no two async blocks, even if identical, have the same type");
-                        diag.help(
-                            "consider pinning your async block and casting it to a trait object",
-                        );
-                    }
-                    (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
-                        // Issue #63167
-                        diag.note("distinct uses of `impl Trait` result in different opaque types");
-                    }
-                    (ty::Float(_), ty::Infer(ty::IntVar(_)))
-                        if let Ok(
-                            // Issue #53280
-                            snippet,
-                        ) = tcx.sess.source_map().span_to_snippet(sp) =>
-                    {
-                        if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
-                            diag.span_suggestion_verbose(
-                                sp.shrink_to_hi(),
-                                "use a float literal",
-                                ".0",
-                                MachineApplicable,
-                            );
-                        }
-                    }
-                    (ty::Param(expected), ty::Param(found)) => {
-                        let generics = tcx.generics_of(body_owner_def_id);
-                        let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
-                        if !sp.contains(e_span) {
-                            diag.span_label(e_span, "expected type parameter");
-                        }
-                        let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
-                        if !sp.contains(f_span) {
-                            diag.span_label(f_span, "found type parameter");
-                        }
-                        diag.note(
-                            "a type parameter was expected, but a different one was found; \
-                             you might be missing a type parameter or trait bound",
-                        );
-                        diag.note(
-                            "for more information, visit \
-                             https://doc.rust-lang.org/book/ch10-02-traits.html\
-                             #traits-as-parameters",
-                        );
-                    }
-                    (
-                        ty::Alias(ty::Projection | ty::Inherent, _),
-                        ty::Alias(ty::Projection | ty::Inherent, _),
-                    ) => {
-                        diag.note("an associated type was expected, but a different one was found");
-                    }
-                    // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
-                    (ty::Param(p), ty::Alias(ty::Projection, proj))
-                    | (ty::Alias(ty::Projection, proj), ty::Param(p))
-                        if !tcx.is_impl_trait_in_trait(proj.def_id) =>
-                    {
-                        let param = tcx.generics_of(body_owner_def_id).type_param(p, tcx);
-                        let p_def_id = param.def_id;
-                        let p_span = tcx.def_span(p_def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
-                        }
-                        let parent = p_def_id.as_local().and_then(|id| {
-                            let local_id = tcx.local_def_id_to_hir_id(id);
-                            let generics = tcx.parent_hir_node(local_id).generics()?;
-                            Some((id, generics))
-                        });
-                        let mut note = true;
-                        if let Some((local_id, generics)) = parent {
-                            // Synthesize the associated type restriction `Add<Output = Expected>`.
-                            // FIXME: extract this logic for use in other diagnostics.
-                            let (trait_ref, assoc_args) = proj.trait_ref_and_own_args(tcx);
-                            let item_name = tcx.item_name(proj.def_id);
-                            let item_args = self.format_generic_args(assoc_args);
-
-                            // Here, we try to see if there's an existing
-                            // trait implementation that matches the one that
-                            // we're suggesting to restrict. If so, find the
-                            // "end", whether it be at the end of the trait
-                            // or the end of the generic arguments.
-                            let mut matching_span = None;
-                            let mut matched_end_of_args = false;
-                            for bound in generics.bounds_for_param(local_id) {
-                                let potential_spans = bound.bounds.iter().find_map(|bound| {
-                                    let bound_trait_path = bound.trait_ref()?.path;
-                                    let def_id = bound_trait_path.res.opt_def_id()?;
-                                    let generic_args = bound_trait_path
-                                        .segments
-                                        .iter()
-                                        .last()
-                                        .map(|path| path.args());
-                                    (def_id == trait_ref.def_id)
-                                        .then_some((bound_trait_path.span, generic_args))
-                                });
-
-                                if let Some((end_of_trait, end_of_args)) = potential_spans {
-                                    let args_span = end_of_args.and_then(|args| args.span());
-                                    matched_end_of_args = args_span.is_some();
-                                    matching_span = args_span
-                                        .or_else(|| Some(end_of_trait))
-                                        .map(|span| span.shrink_to_hi());
-                                    break;
-                                }
-                            }
-
-                            if matched_end_of_args {
-                                // Append suggestion to the end of our args
-                                let path = format!(", {item_name}{item_args} = {p}");
-                                note = !suggest_constraining_type_param(
-                                    tcx,
-                                    generics,
-                                    diag,
-                                    &proj.self_ty().to_string(),
-                                    &path,
-                                    None,
-                                    matching_span,
-                                );
-                            } else {
-                                // Suggest adding a bound to an existing trait
-                                // or if the trait doesn't exist, add the trait
-                                // and the suggested bounds.
-                                let path = format!("<{item_name}{item_args} = {p}>");
-                                note = !suggest_constraining_type_param(
-                                    tcx,
-                                    generics,
-                                    diag,
-                                    &proj.self_ty().to_string(),
-                                    &path,
-                                    None,
-                                    matching_span,
-                                );
-                            }
-                        }
-                        if note {
-                            diag.note("you might be missing a type parameter or trait bound");
-                        }
-                    }
-                    (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
-                    | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
-                        let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
-                        }
-                        diag.help("type parameters must be constrained to match other types");
-                        if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
-                            diag.help(
-                                "given a type parameter `T` and a method `foo`:
-```
-trait Trait<T> { fn foo(&self) -> T; }
-```
-the only ways to implement method `foo` are:
-- constrain `T` with an explicit type:
-```
-impl Trait<String> for X {
-    fn foo(&self) -> String { String::new() }
-}
-```
-- add a trait bound to `T` and call a method on that trait that returns `Self`:
-```
-impl<T: std::default::Default> Trait<T> for X {
-    fn foo(&self) -> T { <T as std::default::Default>::default() }
-}
-```
-- change `foo` to return an argument of type `T`:
-```
-impl<T> Trait<T> for X {
-    fn foo(&self, x: T) -> T { x }
-}
-```",
-                            );
-                        }
-                        diag.note(
-                            "for more information, visit \
-                             https://doc.rust-lang.org/book/ch10-02-traits.html\
-                             #traits-as-parameters",
-                        );
-                    }
-                    (
-                        ty::Param(p),
-                        ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..),
-                    ) => {
-                        let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, "expected this type parameter");
-                        }
-                        diag.help(format!(
-                            "every closure has a distinct type and so could not always match the \
-                             caller-chosen type of parameter `{p}`"
-                        ));
-                    }
-                    (ty::Param(p), _) | (_, ty::Param(p)) => {
-                        let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
-                        }
-                    }
-                    (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _)
-                        if !tcx.is_impl_trait_in_trait(proj_ty.def_id) =>
-                    {
-                        self.expected_projection(
-                            diag,
-                            proj_ty,
-                            values,
-                            body_owner_def_id,
-                            cause.code(),
-                        );
-                    }
-                    (_, ty::Alias(ty::Projection | ty::Inherent, proj_ty))
-                        if !tcx.is_impl_trait_in_trait(proj_ty.def_id) =>
-                    {
-                        let msg = || {
-                            format!(
-                                "consider constraining the associated type `{}` to `{}`",
-                                values.found, values.expected,
-                            )
-                        };
-                        if !(self.suggest_constraining_opaque_associated_type(
-                            diag,
-                            msg,
-                            proj_ty,
-                            values.expected,
-                        ) || self.suggest_constraint(
-                            diag,
-                            &msg,
-                            body_owner_def_id,
-                            proj_ty,
-                            values.expected,
-                        )) {
-                            diag.help(msg());
-                            diag.note(
-                                "for more information, visit \
-                                https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
-                            );
-                        }
-                    }
-                    (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias))
-                        if let Some(def_id) = t.principal_def_id()
-                            && tcx
-                                .explicit_item_super_predicates(alias.def_id)
-                                .skip_binder()
-                                .iter()
-                                .any(|(pred, _span)| match pred.kind().skip_binder() {
-                                    ty::ClauseKind::Trait(trait_predicate)
-                                        if trait_predicate.polarity
-                                            == ty::PredicatePolarity::Positive =>
-                                    {
-                                        trait_predicate.def_id() == def_id
-                                    }
-                                    _ => false,
-                                }) =>
-                    {
-                        diag.help(format!(
-                            "you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \
-                             change the expected type as well",
-                            values.found, values.expected,
-                        ));
-                    }
-                    (ty::Dynamic(t, _, ty::DynKind::Dyn), _)
-                        if let Some(def_id) = t.principal_def_id() =>
-                    {
-                        let mut impl_def_ids = vec![];
-                        tcx.for_each_relevant_impl(def_id, values.found, |did| {
-                            impl_def_ids.push(did)
-                        });
-                        if let [_] = &impl_def_ids[..] {
-                            let trait_name = tcx.item_name(def_id);
-                            diag.help(format!(
-                                "`{}` implements `{trait_name}` so you could box the found value \
-                                 and coerce it to the trait object `Box<dyn {trait_name}>`, you \
-                                 will have to change the expected type as well",
-                                values.found,
-                            ));
-                        }
-                    }
-                    (_, ty::Dynamic(t, _, ty::DynKind::Dyn))
-                        if let Some(def_id) = t.principal_def_id() =>
-                    {
-                        let mut impl_def_ids = vec![];
-                        tcx.for_each_relevant_impl(def_id, values.expected, |did| {
-                            impl_def_ids.push(did)
-                        });
-                        if let [_] = &impl_def_ids[..] {
-                            let trait_name = tcx.item_name(def_id);
-                            diag.help(format!(
-                                "`{}` implements `{trait_name}` so you could change the expected \
-                                 type to `Box<dyn {trait_name}>`",
-                                values.expected,
-                            ));
-                        }
-                    }
-                    (ty::Dynamic(t, _, ty::DynKind::DynStar), _)
-                        if let Some(def_id) = t.principal_def_id() =>
-                    {
-                        let mut impl_def_ids = vec![];
-                        tcx.for_each_relevant_impl(def_id, values.found, |did| {
-                            impl_def_ids.push(did)
-                        });
-                        if let [_] = &impl_def_ids[..] {
-                            let trait_name = tcx.item_name(def_id);
-                            diag.help(format!(
-                                "`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \
-                                 not enabled; that feature it is currently incomplete",
-                                values.found,
-                            ));
-                        }
-                    }
-                    (_, ty::Alias(ty::Opaque, opaque_ty))
-                    | (ty::Alias(ty::Opaque, opaque_ty), _) => {
-                        if opaque_ty.def_id.is_local()
-                            && matches!(
-                                tcx.def_kind(body_owner_def_id),
-                                DefKind::Fn
-                                    | DefKind::Static { .. }
-                                    | DefKind::Const
-                                    | DefKind::AssocFn
-                                    | DefKind::AssocConst
-                            )
-                            && tcx.is_type_alias_impl_trait(opaque_ty.def_id)
-                            && !tcx
-                                .opaque_types_defined_by(body_owner_def_id.expect_local())
-                                .contains(&opaque_ty.def_id.expect_local())
-                        {
-                            let sp = tcx
-                                .def_ident_span(body_owner_def_id)
-                                .unwrap_or_else(|| tcx.def_span(body_owner_def_id));
-                            diag.span_note(
-                                sp,
-                                "this item must have the opaque type in its signature in order to \
-                                 be able to register hidden types",
-                            );
-                        }
-                        // If two if arms can be coerced to a trait object, provide a structured
-                        // suggestion.
-                        let ObligationCauseCode::IfExpression(cause) = cause.code() else {
-                            return;
-                        };
-                        let hir::Node::Block(blk) = self.tcx.hir_node(cause.then_id) else {
-                            return;
-                        };
-                        let Some(then) = blk.expr else {
-                            return;
-                        };
-                        let hir::Node::Block(blk) = self.tcx.hir_node(cause.else_id) else {
-                            return;
-                        };
-                        let Some(else_) = blk.expr else {
-                            return;
-                        };
-                        let expected = match values.found.kind() {
-                            ty::Alias(..) => values.expected,
-                            _ => values.found,
-                        };
-                        let preds = tcx.explicit_item_super_predicates(opaque_ty.def_id);
-                        for (pred, _span) in preds.skip_binder() {
-                            let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder()
-                            else {
-                                continue;
-                            };
-                            if trait_predicate.polarity != ty::PredicatePolarity::Positive {
-                                continue;
-                            }
-                            let def_id = trait_predicate.def_id();
-                            let mut impl_def_ids = vec![];
-                            tcx.for_each_relevant_impl(def_id, expected, |did| {
-                                impl_def_ids.push(did)
-                            });
-                            if let [_] = &impl_def_ids[..] {
-                                let trait_name = tcx.item_name(def_id);
-                                diag.multipart_suggestion(
-                                    format!(
-                                        "`{expected}` implements `{trait_name}` so you can box \
-                                         both arms and coerce to the trait object \
-                                         `Box<dyn {trait_name}>`",
-                                    ),
-                                    vec![
-                                        (then.span.shrink_to_lo(), "Box::new(".to_string()),
-                                        (
-                                            then.span.shrink_to_hi(),
-                                            format!(") as Box<dyn {}>", tcx.def_path_str(def_id)),
-                                        ),
-                                        (else_.span.shrink_to_lo(), "Box::new(".to_string()),
-                                        (else_.span.shrink_to_hi(), ")".to_string()),
-                                    ],
-                                    MachineApplicable,
-                                );
-                            }
-                        }
-                    }
-                    (ty::FnPtr(sig), ty::FnDef(def_id, _))
-                    | (ty::FnDef(def_id, _), ty::FnPtr(sig)) => {
-                        if tcx.fn_sig(def_id).skip_binder().safety() < sig.safety() {
-                            diag.note(
-                                "unsafe functions cannot be coerced into safe function pointers",
-                            );
-                        }
-                    }
-                    (ty::Adt(_, _), ty::Adt(def, args))
-                        if let ObligationCauseCode::IfExpression(cause) = cause.code()
-                            && let hir::Node::Block(blk) = self.tcx.hir_node(cause.then_id)
-                            && let Some(then) = blk.expr
-                            && def.is_box()
-                            && let boxed_ty = args.type_at(0)
-                            && let ty::Dynamic(t, _, _) = boxed_ty.kind()
-                            && let Some(def_id) = t.principal_def_id()
-                            && let mut impl_def_ids = vec![]
-                            && let _ =
-                                tcx.for_each_relevant_impl(def_id, values.expected, |did| {
-                                    impl_def_ids.push(did)
-                                })
-                            && let [_] = &impl_def_ids[..] =>
-                    {
-                        // We have divergent if/else arms where the expected value is a type that
-                        // implements the trait of the found boxed trait object.
-                        diag.multipart_suggestion(
-                            format!(
-                                "`{}` implements `{}` so you can box it to coerce to the trait \
-                                 object `{}`",
-                                values.expected,
-                                tcx.item_name(def_id),
-                                values.found,
-                            ),
-                            vec![
-                                (then.span.shrink_to_lo(), "Box::new(".to_string()),
-                                (then.span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            MachineApplicable,
-                        );
-                    }
-                    _ => {}
-                }
-                debug!(
-                    "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
-                    values.expected,
-                    values.expected.kind(),
-                    values.found,
-                    values.found.kind(),
-                );
-            }
-            TypeError::CyclicTy(ty) => {
-                // Watch out for various cases of cyclic types and try to explain.
-                if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
-                    diag.note(
-                        "closures cannot capture themselves or take themselves as argument;\n\
-                         this error may be the result of a recent compiler bug-fix,\n\
-                         see issue #46062 <https://github.com/rust-lang/rust/issues/46062>\n\
-                         for more information",
-                    );
-                }
-            }
-            TypeError::TargetFeatureCast(def_id) => {
-                let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
-                diag.note(
-                    "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
-                );
-                diag.span_labels(target_spans, "`#[target_feature]` added here");
-            }
-            _ => {}
-        }
-    }
-
-    fn suggest_constraint(
-        &self,
-        diag: &mut Diag<'_>,
-        msg: impl Fn() -> String,
-        body_owner_def_id: DefId,
-        proj_ty: ty::AliasTy<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> bool {
-        let tcx = self.tcx;
-        let assoc = tcx.associated_item(proj_ty.def_id);
-        let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
-        let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else {
-            return false;
-        };
-        let Some(hir_generics) = item.generics() else {
-            return false;
-        };
-        // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
-        // This will also work for `impl Trait`.
-        let ty::Param(param_ty) = *proj_ty.self_ty().kind() else {
-            return false;
-        };
-        let generics = tcx.generics_of(body_owner_def_id);
-        let def_id = generics.type_param(param_ty, tcx).def_id;
-        let Some(def_id) = def_id.as_local() else {
-            return false;
-        };
-
-        // First look in the `where` clause, as this might be
-        // `fn foo<T>(x: T) where T: Trait`.
-        for pred in hir_generics.bounds_for_param(def_id) {
-            if self.constrain_generic_bound_associated_type_structured_suggestion(
-                diag,
-                trait_ref,
-                pred.bounds,
-                assoc,
-                assoc_args,
-                ty,
-                &msg,
-                false,
-            ) {
-                return true;
-            }
-        }
-        if (param_ty.index as usize) >= generics.parent_count {
-            // The param comes from the current item, do not look at the parent. (#117209)
-            return false;
-        }
-        // If associated item, look to constrain the params of the trait/impl.
-        let hir_id = match item {
-            hir::Node::ImplItem(item) => item.hir_id(),
-            hir::Node::TraitItem(item) => item.hir_id(),
-            _ => return false,
-        };
-        let parent = tcx.hir().get_parent_item(hir_id).def_id;
-        self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
-    }
-
-    /// An associated type was expected and a different type was found.
-    ///
-    /// We perform a few different checks to see what we can suggest:
-    ///
-    ///  - In the current item, look for associated functions that return the expected type and
-    ///    suggest calling them. (Not a structured suggestion.)
-    ///  - If any of the item's generic bounds can be constrained, we suggest constraining the
-    ///    associated type to the found type.
-    ///  - If the associated type has a default type and was expected inside of a `trait`, we
-    ///    mention that this is disallowed.
-    ///  - If all other things fail, and the error is not because of a mismatch between the `trait`
-    ///    and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
-    ///    fn that returns the type.
-    fn expected_projection(
-        &self,
-        diag: &mut Diag<'_>,
-        proj_ty: ty::AliasTy<'tcx>,
-        values: ExpectedFound<Ty<'tcx>>,
-        body_owner_def_id: DefId,
-        cause_code: &ObligationCauseCode<'_>,
-    ) {
-        let tcx = self.tcx;
-
-        // Don't suggest constraining a projection to something containing itself
-        if self.tcx.erase_regions(values.found).contains(self.tcx.erase_regions(values.expected)) {
-            return;
-        }
-
-        let msg = || {
-            format!(
-                "consider constraining the associated type `{}` to `{}`",
-                values.expected, values.found
-            )
-        };
-
-        let body_owner = tcx.hir().get_if_local(body_owner_def_id);
-        let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
-
-        // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
-        let callable_scope = matches!(
-            body_owner,
-            Some(
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
-                    | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
-                    | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
-            )
-        );
-        let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItem { .. });
-        let assoc = tcx.associated_item(proj_ty.def_id);
-        if impl_comparison {
-            // We do not want to suggest calling functions when the reason of the
-            // type error is a comparison of an `impl` with its `trait`.
-        } else {
-            let point_at_assoc_fn = if callable_scope
-                && self.point_at_methods_that_satisfy_associated_type(
-                    diag,
-                    assoc.container_id(tcx),
-                    current_method_ident,
-                    proj_ty.def_id,
-                    values.expected,
-                ) {
-                // If we find a suitable associated function that returns the expected type, we
-                // don't want the more general suggestion later in this method about "consider
-                // constraining the associated type or calling a method that returns the associated
-                // type".
-                true
-            } else {
-                false
-            };
-            // Possibly suggest constraining the associated type to conform to the
-            // found type.
-            if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
-                || point_at_assoc_fn
-            {
-                return;
-            }
-        }
-
-        self.suggest_constraining_opaque_associated_type(diag, &msg, proj_ty, values.found);
-
-        if self.point_at_associated_type(diag, body_owner_def_id, values.found) {
-            return;
-        }
-
-        if !impl_comparison {
-            // Generic suggestion when we can't be more specific.
-            if callable_scope {
-                diag.help(format!(
-                    "{} or calling a method that returns `{}`",
-                    msg(),
-                    values.expected
-                ));
-            } else {
-                diag.help(msg());
-            }
-            diag.note(
-                "for more information, visit \
-                 https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
-            );
-        }
-        if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
-            diag.help(
-                "given an associated type `T` and a method `foo`:
-```
-trait Trait {
-type T;
-fn foo(&self) -> Self::T;
-}
-```
-the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
-```
-impl Trait for X {
-type T = String;
-fn foo(&self) -> Self::T { String::new() }
-}
-```",
-            );
-        }
-    }
-
-    /// When the expected `impl Trait` is not defined in the current item, it will come from
-    /// a return type. This can occur when dealing with `TryStream` (#71035).
-    fn suggest_constraining_opaque_associated_type(
-        &self,
-        diag: &mut Diag<'_>,
-        msg: impl Fn() -> String,
-        proj_ty: ty::AliasTy<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> bool {
-        let tcx = self.tcx;
-
-        let assoc = tcx.associated_item(proj_ty.def_id);
-        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
-            let opaque_local_def_id = def_id.as_local();
-            let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
-            } else {
-                return false;
-            };
-
-            let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
-
-            self.constrain_generic_bound_associated_type_structured_suggestion(
-                diag,
-                trait_ref,
-                opaque_hir_ty.bounds,
-                assoc,
-                assoc_args,
-                ty,
-                msg,
-                true,
-            )
-        } else {
-            false
-        }
-    }
-
-    fn point_at_methods_that_satisfy_associated_type(
-        &self,
-        diag: &mut Diag<'_>,
-        assoc_container_id: DefId,
-        current_method_ident: Option<Symbol>,
-        proj_ty_item_def_id: DefId,
-        expected: Ty<'tcx>,
-    ) -> bool {
-        let tcx = self.tcx;
-
-        let items = tcx.associated_items(assoc_container_id);
-        // Find all the methods in the trait that could be called to construct the
-        // expected associated type.
-        // FIXME: consider suggesting the use of associated `const`s.
-        let methods: Vec<(Span, String)> = items
-            .in_definition_order()
-            .filter(|item| {
-                ty::AssocKind::Fn == item.kind
-                    && Some(item.name) != current_method_ident
-                    && !tcx.is_doc_hidden(item.def_id)
-            })
-            .filter_map(|item| {
-                let method = tcx.fn_sig(item.def_id).instantiate_identity();
-                match *method.output().skip_binder().kind() {
-                    ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
-                        if item_def_id == proj_ty_item_def_id =>
-                    {
-                        Some((
-                            tcx.def_span(item.def_id),
-                            format!("consider calling `{}`", tcx.def_path_str(item.def_id)),
-                        ))
-                    }
-                    _ => None,
-                }
-            })
-            .collect();
-        if !methods.is_empty() {
-            // Use a single `help:` to show all the methods in the trait that can
-            // be used to construct the expected associated type.
-            let mut span: MultiSpan =
-                methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
-            let msg = format!(
-                "{some} method{s} {are} available that return{r} `{ty}`",
-                some = if methods.len() == 1 { "a" } else { "some" },
-                s = pluralize!(methods.len()),
-                are = pluralize!("is", methods.len()),
-                r = if methods.len() == 1 { "s" } else { "" },
-                ty = expected
-            );
-            for (sp, label) in methods.into_iter() {
-                span.push_span_label(sp, label);
-            }
-            diag.span_help(span, msg);
-            return true;
-        }
-        false
-    }
-
-    fn point_at_associated_type(
-        &self,
-        diag: &mut Diag<'_>,
-        body_owner_def_id: DefId,
-        found: Ty<'tcx>,
-    ) -> bool {
-        let tcx = self.tcx;
-
-        let Some(def_id) = body_owner_def_id.as_local() else {
-            return false;
-        };
-
-        // When `body_owner` is an `impl` or `trait` item, look in its associated types for
-        // `expected` and point at it.
-        let hir_id = tcx.local_def_id_to_hir_id(def_id);
-        let parent_id = tcx.hir().get_parent_item(hir_id);
-        let item = tcx.hir_node_by_def_id(parent_id.def_id);
-
-        debug!("expected_projection parent item {:?}", item);
-
-        let param_env = tcx.param_env(body_owner_def_id);
-
-        match item {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. }) => {
-                // FIXME: account for `#![feature(specialization)]`
-                for item in &items[..] {
-                    match item.kind {
-                        hir::AssocItemKind::Type => {
-                            // FIXME: account for returning some type in a trait fn impl that has
-                            // an assoc type as a return type (#72076).
-                            if let hir::Defaultness::Default { has_value: true } =
-                                tcx.defaultness(item.id.owner_id)
-                            {
-                                let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
-                                if self.infcx.can_eq_shallow(param_env, assoc_ty, found) {
-                                    diag.span_label(
-                                        item.span,
-                                        "associated type defaults can't be assumed inside the \
-                                            trait defining them",
-                                    );
-                                    return true;
-                                }
-                            }
-                        }
-                        _ => {}
-                    }
-                }
-            }
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
-                ..
-            }) => {
-                for item in &items[..] {
-                    if let hir::AssocItemKind::Type = item.kind {
-                        let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
-                        if let hir::Defaultness::Default { has_value: true } =
-                            tcx.defaultness(item.id.owner_id)
-                            && self.infcx.can_eq_shallow(param_env, assoc_ty, found)
-                        {
-                            diag.span_label(
-                                item.span,
-                                "associated type is `default` and may be overridden",
-                            );
-                            return true;
-                        }
-                    }
-                }
-            }
-            _ => {}
-        }
-        false
-    }
-
-    /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
-    /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
-    ///
-    /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
-    /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
-    /// trait bound as the one we're looking for. This can help in cases where the associated
-    /// type is defined on a supertrait of the one present in the bounds.
-    fn constrain_generic_bound_associated_type_structured_suggestion(
-        &self,
-        diag: &mut Diag<'_>,
-        trait_ref: ty::TraitRef<'tcx>,
-        bounds: hir::GenericBounds<'_>,
-        assoc: ty::AssocItem,
-        assoc_args: &[ty::GenericArg<'tcx>],
-        ty: Ty<'tcx>,
-        msg: impl Fn() -> String,
-        is_bound_surely_present: bool,
-    ) -> bool {
-        // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
-
-        let trait_bounds = bounds.iter().filter_map(|bound| match bound {
-            hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
-            _ => None,
-        });
-
-        let matching_trait_bounds = trait_bounds
-            .clone()
-            .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
-            .collect::<Vec<_>>();
-
-        let span = match &matching_trait_bounds[..] {
-            &[ptr] => ptr.span,
-            &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
-                &[ptr] => ptr.span,
-                _ => return false,
-            },
-            _ => return false,
-        };
-
-        self.constrain_associated_type_structured_suggestion(diag, span, assoc, assoc_args, ty, msg)
-    }
-
-    /// Given a span corresponding to a bound, provide a structured suggestion to set an
-    /// associated type to a given type `ty`.
-    fn constrain_associated_type_structured_suggestion(
-        &self,
-        diag: &mut Diag<'_>,
-        span: Span,
-        assoc: ty::AssocItem,
-        assoc_args: &[ty::GenericArg<'tcx>],
-        ty: Ty<'tcx>,
-        msg: impl Fn() -> String,
-    ) -> bool {
-        let tcx = self.tcx;
-
-        if let Ok(has_params) =
-            tcx.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>'))
-        {
-            let (span, sugg) = if has_params {
-                let pos = span.hi() - BytePos(1);
-                let span = Span::new(pos, pos, span.ctxt(), span.parent());
-                (span, format!(", {} = {}", assoc.ident(tcx), ty))
-            } else {
-                let item_args = self.format_generic_args(assoc_args);
-                (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
-            };
-            diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
-            return true;
-        }
-        false
-    }
-
-    pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
-        FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |cx| {
-            cx.path_generic_args(|_| Ok(()), args)
-        })
-        .expect("could not write to `String`.")
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/region.rs b/compiler/rustc_infer/src/error_reporting/infer/region.rs
deleted file mode 100644
index 5d41bb5d271..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/region.rs
+++ /dev/null
@@ -1,1428 +0,0 @@
-use std::iter;
-
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{
-    struct_span_code_err, Applicability, Diag, Subdiagnostic, E0309, E0310, E0311, E0495,
-};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{self as hir, ParamName};
-use rustc_middle::bug;
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _};
-use rustc_span::symbol::kw;
-use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol};
-use rustc_type_ir::Upcast as _;
-
-use super::nice_region_error::find_anon_type;
-use super::{nice_region_error, ObligationCauseAsDiagArg};
-use crate::error_reporting::infer::{ObligationCauseExt as _, TypeErrCtxt};
-use crate::errors::{
-    self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound,
-    OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
-};
-use crate::fluent_generated as fluent;
-use crate::infer::region_constraints::GenericKind;
-use crate::infer::{self, InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin};
-
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    pub fn report_region_errors(
-        &self,
-        generic_param_scope: LocalDefId,
-        errors: &[RegionResolutionError<'tcx>],
-    ) -> ErrorGuaranteed {
-        assert!(!errors.is_empty());
-
-        if let Some(guaranteed) = self.infcx.tainted_by_errors() {
-            return guaranteed;
-        }
-
-        debug!("report_region_errors(): {} errors to start", errors.len());
-
-        // try to pre-process the errors, which will group some of them
-        // together into a `ProcessedErrors` group:
-        let errors = self.process_errors(errors);
-
-        debug!("report_region_errors: {} errors after preprocessing", errors.len());
-
-        let mut guar = None;
-        for error in errors {
-            debug!("report_region_errors: error = {:?}", error);
-
-            let e = if let Some(guar) =
-                self.try_report_nice_region_error(generic_param_scope, &error)
-            {
-                guar
-            } else {
-                match error.clone() {
-                    // These errors could indicate all manner of different
-                    // problems with many different solutions. Rather
-                    // than generate a "one size fits all" error, what we
-                    // attempt to do is go through a number of specific
-                    // scenarios and try to find the best way to present
-                    // the error. If all of these fails, we fall back to a rather
-                    // general bit of code that displays the error information
-                    RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
-                        if sub.is_placeholder() || sup.is_placeholder() {
-                            self.report_placeholder_failure(generic_param_scope, origin, sub, sup)
-                                .emit()
-                        } else {
-                            self.report_concrete_failure(generic_param_scope, origin, sub, sup)
-                                .emit()
-                        }
-                    }
-
-                    RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => self
-                        .report_generic_bound_failure(
-                            generic_param_scope,
-                            origin.span(),
-                            Some(origin),
-                            param_ty,
-                            sub,
-                        ),
-
-                    RegionResolutionError::SubSupConflict(
-                        _,
-                        var_origin,
-                        sub_origin,
-                        sub_r,
-                        sup_origin,
-                        sup_r,
-                        _,
-                    ) => {
-                        if sub_r.is_placeholder() {
-                            self.report_placeholder_failure(
-                                generic_param_scope,
-                                sub_origin,
-                                sub_r,
-                                sup_r,
-                            )
-                            .emit()
-                        } else if sup_r.is_placeholder() {
-                            self.report_placeholder_failure(
-                                generic_param_scope,
-                                sup_origin,
-                                sub_r,
-                                sup_r,
-                            )
-                            .emit()
-                        } else {
-                            self.report_sub_sup_conflict(
-                                generic_param_scope,
-                                var_origin,
-                                sub_origin,
-                                sub_r,
-                                sup_origin,
-                                sup_r,
-                            )
-                        }
-                    }
-
-                    RegionResolutionError::UpperBoundUniverseConflict(
-                        _,
-                        _,
-                        _,
-                        sup_origin,
-                        sup_r,
-                    ) => {
-                        assert!(sup_r.is_placeholder());
-
-                        // Make a dummy value for the "sub region" --
-                        // this is the initial value of the
-                        // placeholder. In practice, we expect more
-                        // tailored errors that don't really use this
-                        // value.
-                        let sub_r = self.tcx.lifetimes.re_erased;
-
-                        self.report_placeholder_failure(
-                            generic_param_scope,
-                            sup_origin,
-                            sub_r,
-                            sup_r,
-                        )
-                        .emit()
-                    }
-
-                    RegionResolutionError::CannotNormalize(clause, origin) => {
-                        let clause: ty::Clause<'tcx> =
-                            clause.map_bound(ty::ClauseKind::TypeOutlives).upcast(self.tcx);
-                        self.tcx
-                            .dcx()
-                            .struct_span_err(origin.span(), format!("cannot normalize `{clause}`"))
-                            .emit()
-                    }
-                }
-            };
-
-            guar = Some(e)
-        }
-
-        guar.unwrap()
-    }
-
-    // This method goes through all the errors and try to group certain types
-    // of error together, for the purpose of suggesting explicit lifetime
-    // parameters to the user. This is done so that we can have a more
-    // complete view of what lifetimes should be the same.
-    // If the return value is an empty vector, it means that processing
-    // failed (so the return value of this method should not be used).
-    //
-    // The method also attempts to weed out messages that seem like
-    // duplicates that will be unhelpful to the end-user. But
-    // obviously it never weeds out ALL errors.
-    fn process_errors(
-        &self,
-        errors: &[RegionResolutionError<'tcx>],
-    ) -> Vec<RegionResolutionError<'tcx>> {
-        debug!("process_errors()");
-
-        // We want to avoid reporting generic-bound failures if we can
-        // avoid it: these have a very high rate of being unhelpful in
-        // practice. This is because they are basically secondary
-        // checks that test the state of the region graph after the
-        // rest of inference is done, and the other kinds of errors
-        // indicate that the region constraint graph is internally
-        // inconsistent, so these test results are likely to be
-        // meaningless.
-        //
-        // Therefore, we filter them out of the list unless they are
-        // the only thing in the list.
-
-        let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
-            RegionResolutionError::GenericBoundFailure(..) => true,
-            RegionResolutionError::ConcreteFailure(..)
-            | RegionResolutionError::SubSupConflict(..)
-            | RegionResolutionError::UpperBoundUniverseConflict(..)
-            | RegionResolutionError::CannotNormalize(..) => false,
-        };
-
-        let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
-            errors.to_owned()
-        } else {
-            errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
-        };
-
-        // sort the errors by span, for better error message stability.
-        errors.sort_by_key(|u| match *u {
-            RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
-            RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
-            RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
-            RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
-            RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(),
-        });
-        errors
-    }
-
-    pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
-        match *origin {
-            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
-                span: trace.cause.span,
-                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
-            }
-            .add_to_diag(err),
-            infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
-            }
-            infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
-                    .add_to_diag(err);
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reference_outlives_referent,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diag(err);
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_relate_param_bound,
-                    name: &self.ty_to_string(ty),
-                    continues: opt_span.is_some(),
-                }
-                .add_to_diag(err);
-                if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diag(err);
-                }
-            }
-            infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diag(err);
-            }
-            infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diag(err);
-            }
-            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
-                self.note_region_origin(err, parent);
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                RegionOriginNote::Plain {
-                    span,
-                    msg: fluent::infer_ascribe_user_type_prove_predicate,
-                }
-                .add_to_diag(err);
-            }
-        }
-    }
-
-    pub(super) fn report_concrete_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> Diag<'a> {
-        let mut err = match origin {
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
-                let mut err = self.report_and_explain_type_error(trace, terr);
-                match (*sub, *sup) {
-                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
-                    (ty::RePlaceholder(_), _) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "",
-                            sup,
-                            " doesn't meet the lifetime requirements",
-                            None,
-                        );
-                    }
-                    (_, ty::RePlaceholder(_)) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "the required lifetime does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                    _ => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "",
-                            sup,
-                            "...",
-                            None,
-                        );
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            generic_param_scope,
-                            "...does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                }
-                err
-            }
-            infer::Reborrow(span) => {
-                let reference_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::RefValidFor,
-                    note_and_explain::SuffixKind::Continues,
-                );
-                let content_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::ContentValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(OutlivesContent {
-                    span,
-                    notes: reference_valid.into_iter().chain(content_valid).collect(),
-                })
-            }
-            infer::RelateObjectBound(span) => {
-                let object_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::TypeObjValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let pointer_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::SourcePointerValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(OutlivesBound {
-                    span,
-                    notes: object_valid.into_iter().chain(pointer_valid).collect(),
-                })
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                let prefix = match *sub {
-                    ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
-                    _ => note_and_explain::PrefixKind::TypeOutlive,
-                };
-                let suffix = if opt_span.is_some() {
-                    note_and_explain::SuffixKind::ReqByBinding
-                } else {
-                    note_and_explain::SuffixKind::Empty
-                };
-                let note = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    opt_span,
-                    prefix,
-                    suffix,
-                );
-                self.dcx().create_err(FulfillReqLifetime {
-                    span,
-                    ty: self.resolve_vars_if_possible(ty),
-                    note,
-                })
-            }
-            infer::RelateRegionParamBound(span) => {
-                let param_instantiated = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::LfParamInstantiatedWith,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let param_must_outlive = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::LfParamMustOutlive,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(LfBoundNotSatisfied {
-                    span,
-                    notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
-                })
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                let pointer_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::PointerValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let data_valid = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::DataValidFor,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(RefLongerThanData {
-                    span,
-                    ty: self.resolve_vars_if_possible(ty),
-                    notes: pointer_valid.into_iter().chain(data_valid).collect(),
-                })
-            }
-            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
-                let mut err = self.infcx.report_extra_impl_obligation(
-                    span,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    &format!("`{sup}: {sub}`"),
-                );
-                // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
-                if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
-                    && generics.where_clause_span.contains(span)
-                {
-                    self.suggest_copy_trait_method_bounds(
-                        trait_item_def_id,
-                        impl_item_def_id,
-                        &mut err,
-                    );
-                }
-                err
-            }
-            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
-                let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup);
-
-                // Don't mention the item name if it's an RPITIT, since that'll just confuse
-                // folks.
-                if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) {
-                    let trait_item_span = self.tcx.def_span(trait_item_def_id);
-                    let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                    err.span_label(
-                        trait_item_span,
-                        format!("definition of `{item_name}` from trait"),
-                    );
-                }
-
-                self.suggest_copy_trait_method_bounds(
-                    trait_item_def_id,
-                    impl_item_def_id,
-                    &mut err,
-                );
-                err
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                let instantiated = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sup,
-                    None,
-                    note_and_explain::PrefixKind::LfInstantiatedWith,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                let must_outlive = note_and_explain::RegionExplanation::new(
-                    self.tcx,
-                    generic_param_scope,
-                    sub,
-                    None,
-                    note_and_explain::PrefixKind::LfMustOutlive,
-                    note_and_explain::SuffixKind::Empty,
-                );
-                self.dcx().create_err(LfBoundNotSatisfied {
-                    span,
-                    notes: instantiated.into_iter().chain(must_outlive).collect(),
-                })
-            }
-        };
-        if sub.is_error() || sup.is_error() {
-            err.downgrade_to_delayed_bug();
-        }
-        err
-    }
-
-    pub fn suggest_copy_trait_method_bounds(
-        &self,
-        trait_item_def_id: DefId,
-        impl_item_def_id: LocalDefId,
-        err: &mut Diag<'_>,
-    ) {
-        // FIXME(compiler-errors): Right now this is only being used for region
-        // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
-        // but right now it's not really very smart when it comes to implicit `Sized`
-        // predicates and bounds on the trait itself.
-
-        let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
-        else {
-            return;
-        };
-        let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
-            return;
-        };
-        let trait_args = trait_ref
-            .instantiate_identity()
-            // Replace the explicit self type with `Self` for better suggestion rendering
-            .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
-            .args;
-        let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
-            .rebase_onto(self.tcx, impl_def_id, trait_args);
-
-        let Ok(trait_predicates) =
-            self.tcx
-                .explicit_predicates_of(trait_item_def_id)
-                .instantiate_own(self.tcx, trait_item_args)
-                .map(|(pred, _)| {
-                    if pred.is_suggestable(self.tcx, false) {
-                        Ok(pred.to_string())
-                    } else {
-                        Err(())
-                    }
-                })
-                .collect::<Result<Vec<_>, ()>>()
-        else {
-            return;
-        };
-
-        let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
-            return;
-        };
-
-        let suggestion = if trait_predicates.is_empty() {
-            WhereClauseSuggestions::Remove { span: generics.where_clause_span }
-        } else {
-            let space = if generics.where_clause_span.is_empty() { " " } else { "" };
-            WhereClauseSuggestions::CopyPredicates {
-                span: generics.where_clause_span,
-                space,
-                trait_predicates: trait_predicates.join(", "),
-            }
-        };
-        err.subdiagnostic(suggestion);
-    }
-
-    pub(super) fn report_placeholder_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        placeholder_origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> Diag<'a> {
-        // I can't think how to do better than this right now. -nikomatsakis
-        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
-        match placeholder_origin {
-            infer::Subtype(box ref trace)
-                if matches!(
-                    &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::WhereClause(..)
-                        | ObligationCauseCode::WhereClauseInExpr(..)
-                ) =>
-            {
-                // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::WhereClause(_, span)
-                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
-                    &trace.cause.code().peel_derives()
-                    && !span.is_dummy()
-                {
-                    let span = *span;
-                    self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
-                        .with_span_note(span, "the lifetime requirement is introduced here")
-                } else {
-                    unreachable!(
-                        "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
-                    )
-                }
-            }
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsPlaceholderMismatch;
-                return self.report_and_explain_type_error(trace, terr);
-            }
-            _ => {
-                return self.report_concrete_failure(
-                    generic_param_scope,
-                    placeholder_origin,
-                    sub,
-                    sup,
-                );
-            }
-        }
-    }
-
-    pub fn report_generic_bound_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        span: Span,
-        origin: Option<SubregionOrigin<'tcx>>,
-        bound_kind: GenericKind<'tcx>,
-        sub: Region<'tcx>,
-    ) -> ErrorGuaranteed {
-        self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub)
-            .emit()
-    }
-
-    pub fn construct_generic_bound_failure(
-        &self,
-        generic_param_scope: LocalDefId,
-        span: Span,
-        origin: Option<SubregionOrigin<'tcx>>,
-        bound_kind: GenericKind<'tcx>,
-        sub: Region<'tcx>,
-    ) -> Diag<'a> {
-        if let Some(SubregionOrigin::CompareImplItemObligation {
-            span,
-            impl_item_def_id,
-            trait_item_def_id,
-        }) = origin
-        {
-            return self.infcx.report_extra_impl_obligation(
-                span,
-                impl_item_def_id,
-                trait_item_def_id,
-                &format!("`{bound_kind}: {sub}`"),
-            );
-        }
-
-        let labeled_user_string = match bound_kind {
-            GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
-            GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"),
-            GenericKind::Alias(ref p) => match p.kind(self.tcx) {
-                ty::Projection | ty::Inherent => {
-                    format!("the associated type `{p}`")
-                }
-                ty::Weak => format!("the type alias `{p}`"),
-                ty::Opaque => format!("the opaque type `{p}`"),
-            },
-        };
-
-        let mut err = self
-            .tcx
-            .dcx()
-            .struct_span_err(span, format!("{labeled_user_string} may not live long enough"));
-        err.code(match sub.kind() {
-            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => E0309,
-            ty::ReStatic => E0310,
-            _ => E0311,
-        });
-
-        '_explain: {
-            let (description, span) = match sub.kind() {
-                ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
-                    msg_span_from_named_region(self.tcx, generic_param_scope, sub, Some(span))
-                }
-                _ => (format!("lifetime `{sub}`"), Some(span)),
-            };
-            let prefix = format!("{labeled_user_string} must be valid for ");
-            label_msg_span(&mut err, &prefix, description, span, "...");
-            if let Some(origin) = origin {
-                self.note_region_origin(&mut err, &origin);
-            }
-        }
-
-        'suggestion: {
-            let msg = "consider adding an explicit lifetime bound";
-
-            if (bound_kind, sub).has_infer_regions()
-                || (bound_kind, sub).has_placeholders()
-                || !bound_kind.is_suggestable(self.tcx, false)
-            {
-                let lt_name = sub.get_name_or_anon().to_string();
-                err.help(format!("{msg} `{bound_kind}: {lt_name}`..."));
-                break 'suggestion;
-            }
-
-            let mut generic_param_scope = generic_param_scope;
-            while self.tcx.def_kind(generic_param_scope) == DefKind::OpaqueTy {
-                generic_param_scope = self.tcx.local_parent(generic_param_scope);
-            }
-
-            // type_param_sugg_span is (span, has_bounds, needs_parentheses)
-            let (type_scope, type_param_sugg_span) = match bound_kind {
-                GenericKind::Param(param) => {
-                    let generics = self.tcx.generics_of(generic_param_scope);
-                    let type_param = generics.type_param(param, self.tcx);
-                    let def_id = type_param.def_id.expect_local();
-                    let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
-                    // Get the `hir::Param` to verify whether it already has any bounds.
-                    // We do this to avoid suggesting code that ends up as `T: 'a'b`,
-                    // instead we suggest `T: 'a + 'b` in that case.
-                    let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
-                    let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
-                        Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
-                        // If `param` corresponds to `Self`, no usable suggestion span.
-                        None if generics.has_self && param.index == 0 => None,
-                        None => {
-                            let span = if let Some(param) =
-                                hir_generics.params.iter().find(|param| param.def_id == def_id)
-                                && let ParamName::Plain(ident) = param.name
-                            {
-                                ident.span.shrink_to_hi()
-                            } else {
-                                let span = self.tcx.def_span(def_id);
-                                span.shrink_to_hi()
-                            };
-                            Some((span, false, None))
-                        }
-                    };
-                    (scope, sugg_span)
-                }
-                _ => (generic_param_scope, None),
-            };
-            let suggestion_scope = {
-                let lifetime_scope = match sub.kind() {
-                    ty::ReStatic => hir::def_id::CRATE_DEF_ID,
-                    _ => match self.tcx.is_suitable_region(generic_param_scope, sub) {
-                        Some(info) => info.def_id,
-                        None => generic_param_scope,
-                    },
-                };
-                match self.tcx.is_descendant_of(type_scope.into(), lifetime_scope.into()) {
-                    true => type_scope,
-                    false => lifetime_scope,
-                }
-            };
-
-            let mut suggs = vec![];
-            let lt_name = self.suggest_name_region(generic_param_scope, sub, &mut suggs);
-
-            if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
-                && suggestion_scope == type_scope
-            {
-                let suggestion =
-                    if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
-
-                if let Some(open_paren_sp) = open_paren_sp {
-                    suggs.push((open_paren_sp, "(".to_string()));
-                    suggs.push((sp, format!("){suggestion}")));
-                } else {
-                    suggs.push((sp, suggestion))
-                }
-            } else if let GenericKind::Alias(ref p) = bound_kind
-                && let ty::Projection = p.kind(self.tcx)
-                && let DefKind::AssocTy = self.tcx.def_kind(p.def_id)
-                && let Some(ty::ImplTraitInTraitData::Trait { .. }) =
-                    self.tcx.opt_rpitit_info(p.def_id)
-            {
-                // The lifetime found in the `impl` is longer than the one on the RPITIT.
-                // Do not suggest `<Type as Trait>::{opaque}: 'static`.
-            } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) {
-                let pred = format!("{bound_kind}: {lt_name}");
-                let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred);
-                suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
-            } else {
-                let consider = format!("{msg} `{bound_kind}: {sub}`...");
-                err.help(consider);
-            }
-
-            if !suggs.is_empty() {
-                err.multipart_suggestion_verbose(
-                    msg,
-                    suggs,
-                    Applicability::MaybeIncorrect, // Issue #41966
-                );
-            }
-        }
-
-        err
-    }
-
-    pub fn suggest_name_region(
-        &self,
-        generic_param_scope: LocalDefId,
-        lifetime: Region<'tcx>,
-        add_lt_suggs: &mut Vec<(Span, String)>,
-    ) -> String {
-        struct LifetimeReplaceVisitor<'tcx, 'a> {
-            tcx: TyCtxt<'tcx>,
-            needle: hir::LifetimeName,
-            new_lt: &'a str,
-            add_lt_suggs: &'a mut Vec<(Span, String)>,
-        }
-
-        impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> {
-            fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
-                if lt.res == self.needle {
-                    let (pos, span) = lt.suggestion_position();
-                    let new_lt = &self.new_lt;
-                    let sugg = match pos {
-                        hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"),
-                        hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "),
-                        hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"),
-                        hir::LifetimeSuggestionPosition::ElidedPathArgument => {
-                            format!("{new_lt}, ")
-                        }
-                        hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"),
-                    };
-                    self.add_lt_suggs.push((span, sugg));
-                }
-            }
-
-            fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) {
-                let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind else {
-                    return hir::intravisit::walk_ty(self, ty);
-                };
-                let opaque_ty = self.tcx.hir().item(item_id).expect_opaque_ty();
-                if let Some(&(_, b)) =
-                    opaque_ty.lifetime_mapping.iter().find(|&(a, _)| a.res == self.needle)
-                {
-                    let prev_needle =
-                        std::mem::replace(&mut self.needle, hir::LifetimeName::Param(b));
-                    for bound in opaque_ty.bounds {
-                        self.visit_param_bound(bound);
-                    }
-                    self.needle = prev_needle;
-                }
-            }
-        }
-
-        let (lifetime_def_id, lifetime_scope) =
-            match self.tcx.is_suitable_region(generic_param_scope, lifetime) {
-                Some(info) if !lifetime.has_name() => {
-                    (info.bound_region.get_id().unwrap().expect_local(), info.def_id)
-                }
-                _ => return lifetime.get_name_or_anon().to_string(),
-            };
-
-        let new_lt = {
-            let generics = self.tcx.generics_of(lifetime_scope);
-            let mut used_names =
-                iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
-                    .flat_map(|g| &g.own_params)
-                    .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
-                    .map(|p| p.name)
-                    .collect::<Vec<_>>();
-            let hir_id = self.tcx.local_def_id_to_hir_id(lifetime_scope);
-            // consider late-bound lifetimes ...
-            used_names.extend(self.tcx.late_bound_vars(hir_id).into_iter().filter_map(
-                |p| match p {
-                    ty::BoundVariableKind::Region(lt) => lt.get_name(),
-                    _ => None,
-                },
-            ));
-            (b'a'..=b'z')
-                .map(|c| format!("'{}", c as char))
-                .find(|candidate| !used_names.iter().any(|e| e.as_str() == candidate))
-                .unwrap_or("'lt".to_string())
-        };
-
-        let mut visitor = LifetimeReplaceVisitor {
-            tcx: self.tcx,
-            needle: hir::LifetimeName::Param(lifetime_def_id),
-            add_lt_suggs,
-            new_lt: &new_lt,
-        };
-        match self.tcx.expect_hir_owner_node(lifetime_scope) {
-            hir::OwnerNode::Item(i) => visitor.visit_item(i),
-            hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i),
-            hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i),
-            hir::OwnerNode::TraitItem(i) => visitor.visit_trait_item(i),
-            hir::OwnerNode::Crate(_) => bug!("OwnerNode::Crate doesn't not have generics"),
-            hir::OwnerNode::Synthetic => unreachable!(),
-        }
-
-        let ast_generics = self.tcx.hir().get_generics(lifetime_scope).unwrap();
-        let sugg = ast_generics
-            .span_for_lifetime_suggestion()
-            .map(|span| (span, format!("{new_lt}, ")))
-            .unwrap_or_else(|| (ast_generics.span, format!("<{new_lt}>")));
-        add_lt_suggs.push(sugg);
-
-        new_lt
-    }
-
-    fn report_sub_sup_conflict(
-        &self,
-        generic_param_scope: LocalDefId,
-        var_origin: RegionVariableOrigin,
-        sub_origin: SubregionOrigin<'tcx>,
-        sub_region: Region<'tcx>,
-        sup_origin: SubregionOrigin<'tcx>,
-        sup_region: Region<'tcx>,
-    ) -> ErrorGuaranteed {
-        let mut err = self.report_inference_failure(var_origin);
-
-        note_and_explain_region(
-            self.tcx,
-            &mut err,
-            generic_param_scope,
-            "first, the lifetime cannot outlive ",
-            sup_region,
-            "...",
-            None,
-        );
-
-        debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
-        debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
-        debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
-        debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
-        debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
-
-        if let infer::Subtype(ref sup_trace) = sup_origin
-            && let infer::Subtype(ref sub_trace) = sub_origin
-            && let Some((sup_expected, sup_found, _)) = self.values_str(sup_trace.values)
-            && let Some((sub_expected, sub_found, _)) = self.values_str(sub_trace.values)
-            && sub_expected == sup_expected
-            && sub_found == sup_found
-        {
-            note_and_explain_region(
-                self.tcx,
-                &mut err,
-                generic_param_scope,
-                "...but the lifetime must also be valid for ",
-                sub_region,
-                "...",
-                None,
-            );
-            err.span_note(
-                sup_trace.cause.span,
-                format!("...so that the {}", sup_trace.cause.as_requirement_str()),
-            );
-
-            err.note_expected_found(&"", sup_expected, &"", sup_found);
-            return if sub_region.is_error() | sup_region.is_error() {
-                err.delay_as_bug()
-            } else {
-                err.emit()
-            };
-        }
-
-        self.note_region_origin(&mut err, &sup_origin);
-
-        note_and_explain_region(
-            self.tcx,
-            &mut err,
-            generic_param_scope,
-            "but, the lifetime must be valid for ",
-            sub_region,
-            "...",
-            None,
-        );
-
-        self.note_region_origin(&mut err, &sub_origin);
-        if sub_region.is_error() | sup_region.is_error() { err.delay_as_bug() } else { err.emit() }
-    }
-
-    fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_> {
-        let br_string = |br: ty::BoundRegionKind| {
-            let mut s = match br {
-                ty::BrNamed(_, name) => name.to_string(),
-                _ => String::new(),
-            };
-            if !s.is_empty() {
-                s.push(' ');
-            }
-            s
-        };
-        let var_description = match var_origin {
-            infer::MiscVariable(_) => String::new(),
-            infer::PatternRegion(_) => " for pattern".to_string(),
-            infer::AddrOfRegion(_) => " for borrow expression".to_string(),
-            infer::Autoref(_) => " for autoref".to_string(),
-            infer::Coercion(_) => " for automatic coercion".to_string(),
-            infer::BoundRegion(_, br, infer::FnCall) => {
-                format!(" for lifetime parameter {}in function call", br_string(br))
-            }
-            infer::BoundRegion(_, br, infer::HigherRankedType) => {
-                format!(" for lifetime parameter {}in generic type", br_string(br))
-            }
-            infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
-                " for lifetime parameter {}in trait containing associated type `{}`",
-                br_string(br),
-                self.tcx.associated_item(def_id).name
-            ),
-            infer::RegionParameterDefinition(_, name) => {
-                format!(" for lifetime parameter `{name}`")
-            }
-            infer::UpvarRegion(ref upvar_id, _) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                format!(" for capture of `{var_name}` by closure")
-            }
-            infer::Nll(..) => bug!("NLL variable found in lexical phase"),
-        };
-
-        struct_span_code_err!(
-            self.dcx(),
-            var_origin.span(),
-            E0495,
-            "cannot infer an appropriate lifetime{} due to conflicting requirements",
-            var_description
-        )
-    }
-}
-
-pub(super) fn note_and_explain_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    err: &mut Diag<'_>,
-    generic_param_scope: LocalDefId,
-    prefix: &str,
-    region: ty::Region<'tcx>,
-    suffix: &str,
-    alt_span: Option<Span>,
-) {
-    let (description, span) = match *region {
-        ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
-            msg_span_from_named_region(tcx, generic_param_scope, region, alt_span)
-        }
-
-        ty::ReError(_) => return,
-
-        // FIXME(#125431): `ReVar` shouldn't reach here.
-        ty::ReVar(_) => (format!("lifetime `{region}`"), alt_span),
-
-        ty::ReBound(..) | ty::ReErased => {
-            bug!("unexpected region for note_and_explain_region: {:?}", region);
-        }
-    };
-
-    emit_msg_span(err, prefix, description, span, suffix);
-}
-
-fn explain_free_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    err: &mut Diag<'_>,
-    generic_param_scope: LocalDefId,
-    prefix: &str,
-    region: ty::Region<'tcx>,
-    suffix: &str,
-) {
-    let (description, span) = msg_span_from_named_region(tcx, generic_param_scope, region, None);
-
-    label_msg_span(err, prefix, description, span, suffix);
-}
-
-fn msg_span_from_named_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    generic_param_scope: LocalDefId,
-    region: ty::Region<'tcx>,
-    alt_span: Option<Span>,
-) -> (String, Option<Span>) {
-    match *region {
-        ty::ReEarlyParam(br) => {
-            let scope = tcx
-                .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
-                .expect_local();
-            let span = if let Some(param) =
-                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
-            {
-                param.span
-            } else {
-                tcx.def_span(scope)
-            };
-            let text = if br.has_name() {
-                format!("the lifetime `{}` as defined here", br.name)
-            } else {
-                "the anonymous lifetime as defined here".to_string()
-            };
-            (text, Some(span))
-        }
-        ty::ReLateParam(ref fr) => {
-            if !fr.bound_region.is_named()
-                && let Some((ty, _)) =
-                    find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
-            {
-                ("the anonymous lifetime defined here".to_string(), Some(ty.span))
-            } else {
-                match fr.bound_region {
-                    ty::BoundRegionKind::BrNamed(_, name) => {
-                        let span = if let Some(param) = tcx
-                            .hir()
-                            .get_generics(generic_param_scope)
-                            .and_then(|generics| generics.get_named(name))
-                        {
-                            param.span
-                        } else {
-                            tcx.def_span(generic_param_scope)
-                        };
-                        let text = if name == kw::UnderscoreLifetime {
-                            "the anonymous lifetime as defined here".to_string()
-                        } else {
-                            format!("the lifetime `{name}` as defined here")
-                        };
-                        (text, Some(span))
-                    }
-                    ty::BrAnon => (
-                        "the anonymous lifetime as defined here".to_string(),
-                        Some(tcx.def_span(generic_param_scope)),
-                    ),
-                    _ => (
-                        format!("the lifetime `{region}` as defined here"),
-                        Some(tcx.def_span(generic_param_scope)),
-                    ),
-                }
-            }
-        }
-        ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
-        ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
-            ..
-        }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
-        ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon, .. },
-            ..
-        }) => ("an anonymous lifetime".to_owned(), None),
-        _ => bug!("{:?}", region),
-    }
-}
-
-fn emit_msg_span(
-    err: &mut Diag<'_>,
-    prefix: &str,
-    description: String,
-    span: Option<Span>,
-    suffix: &str,
-) {
-    let message = format!("{prefix}{description}{suffix}");
-
-    if let Some(span) = span {
-        err.span_note(span, message);
-    } else {
-        err.note(message);
-    }
-}
-
-fn label_msg_span(
-    err: &mut Diag<'_>,
-    prefix: &str,
-    description: String,
-    span: Option<Span>,
-    suffix: &str,
-) {
-    let message = format!("{prefix}{description}{suffix}");
-
-    if let Some(span) = span {
-        err.span_label(span, message);
-    } else {
-        err.note(message);
-    }
-}
-
-#[instrument(level = "trace", skip(infcx))]
-pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>(
-    infcx: &'a InferCtxt<'tcx>,
-    generic_param_scope: LocalDefId,
-    span: Span,
-    hidden_ty: Ty<'tcx>,
-    hidden_region: ty::Region<'tcx>,
-    opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
-) -> Diag<'a> {
-    let tcx = infcx.tcx;
-    let mut err = infcx.dcx().create_err(errors::OpaqueCapturesLifetime {
-        span,
-        opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args),
-        opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
-    });
-
-    // Explain the region we are capturing.
-    match *hidden_region {
-        ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
-            // Assuming regionck succeeded (*), we ought to always be
-            // capturing *some* region from the fn header, and hence it
-            // ought to be free. So under normal circumstances, we will go
-            // down this path which gives a decent human readable
-            // explanation.
-            //
-            // (*) if not, the `tainted_by_errors` field would be set to
-            // `Some(ErrorGuaranteed)` in any case, so we wouldn't be here at all.
-            explain_free_region(
-                tcx,
-                &mut err,
-                generic_param_scope,
-                &format!("hidden type `{hidden_ty}` captures "),
-                hidden_region,
-                "",
-            );
-            if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) {
-                if infcx.tcx.features().precise_capturing {
-                    suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err);
-                } else {
-                    let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id);
-                    nice_region_error::suggest_new_region_bound(
-                        tcx,
-                        &mut err,
-                        fn_returns,
-                        hidden_region.to_string(),
-                        None,
-                        format!("captures `{hidden_region}`"),
-                        None,
-                        Some(reg_info.def_id),
-                    )
-                }
-            }
-        }
-        ty::RePlaceholder(_) => {
-            explain_free_region(
-                tcx,
-                &mut err,
-                generic_param_scope,
-                &format!("hidden type `{}` captures ", hidden_ty),
-                hidden_region,
-                "",
-            );
-        }
-        ty::ReError(_) => {
-            err.downgrade_to_delayed_bug();
-        }
-        _ => {
-            // Ugh. This is a painful case: the hidden region is not one
-            // that we can easily summarize or explain. This can happen
-            // in a case like
-            // `tests/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
-            //
-            // ```
-            // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
-            //   if condition() { a } else { b }
-            // }
-            // ```
-            //
-            // Here the captured lifetime is the intersection of `'a` and
-            // `'b`, which we can't quite express.
-
-            // We can at least report a really cryptic error for now.
-            note_and_explain_region(
-                tcx,
-                &mut err,
-                generic_param_scope,
-                &format!("hidden type `{hidden_ty}` captures "),
-                hidden_region,
-                "",
-                None,
-            );
-        }
-    }
-
-    err
-}
-
-fn suggest_precise_capturing<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    opaque_def_id: LocalDefId,
-    captured_lifetime: ty::Region<'tcx>,
-    diag: &mut Diag<'_>,
-) {
-    let hir::OpaqueTy { bounds, origin, .. } =
-        tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
-
-    let hir::OpaqueTyOrigin::FnReturn(fn_def_id) = *origin else {
-        return;
-    };
-
-    let new_lifetime = Symbol::intern(&captured_lifetime.to_string());
-
-    if let Some((args, span)) = bounds.iter().find_map(|bound| match bound {
-        hir::GenericBound::Use(args, span) => Some((args, span)),
-        _ => None,
-    }) {
-        let last_lifetime_span = args.iter().rev().find_map(|arg| match arg {
-            hir::PreciseCapturingArg::Lifetime(lt) => Some(lt.ident.span),
-            _ => None,
-        });
-
-        let first_param_span = args.iter().find_map(|arg| match arg {
-            hir::PreciseCapturingArg::Param(p) => Some(p.ident.span),
-            _ => None,
-        });
-
-        let (span, pre, post) = if let Some(last_lifetime_span) = last_lifetime_span {
-            (last_lifetime_span.shrink_to_hi(), ", ", "")
-        } else if let Some(first_param_span) = first_param_span {
-            (first_param_span.shrink_to_lo(), "", ", ")
-        } else {
-            // If we have no args, then have `use<>` and need to fall back to using
-            // span math. This sucks, but should be reliable due to the construction
-            // of the `use<>` span.
-            (span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), "", "")
-        };
-
-        diag.subdiagnostic(errors::AddPreciseCapturing::Existing { span, new_lifetime, pre, post });
-    } else {
-        let mut captured_lifetimes = FxIndexSet::default();
-        let mut captured_non_lifetimes = FxIndexSet::default();
-
-        let variances = tcx.variances_of(opaque_def_id);
-        let mut generics = tcx.generics_of(opaque_def_id);
-        let mut synthetics = vec![];
-        loop {
-            for param in &generics.own_params {
-                if variances[param.index as usize] == ty::Bivariant {
-                    continue;
-                }
-
-                match param.kind {
-                    ty::GenericParamDefKind::Lifetime => {
-                        captured_lifetimes.insert(param.name);
-                    }
-                    ty::GenericParamDefKind::Type { synthetic: true, .. } => {
-                        synthetics.push((tcx.def_span(param.def_id), param.name));
-                    }
-                    ty::GenericParamDefKind::Type { .. }
-                    | ty::GenericParamDefKind::Const { .. } => {
-                        captured_non_lifetimes.insert(param.name);
-                    }
-                }
-            }
-
-            if let Some(parent) = generics.parent {
-                generics = tcx.generics_of(parent);
-            } else {
-                break;
-            }
-        }
-
-        if !captured_lifetimes.insert(new_lifetime) {
-            // Uh, strange. This lifetime appears to already be captured...
-            return;
-        }
-
-        if synthetics.is_empty() {
-            let concatenated_bounds = captured_lifetimes
-                .into_iter()
-                .chain(captured_non_lifetimes)
-                .map(|sym| sym.to_string())
-                .collect::<Vec<_>>()
-                .join(", ");
-
-            diag.subdiagnostic(errors::AddPreciseCapturing::New {
-                span: tcx.def_span(opaque_def_id).shrink_to_hi(),
-                new_lifetime,
-                concatenated_bounds,
-            });
-        } else {
-            let mut next_fresh_param = || {
-                ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
-                    .into_iter()
-                    .map(Symbol::intern)
-                    .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
-                    .find(|s| captured_non_lifetimes.insert(*s))
-                    .unwrap()
-            };
-
-            let mut new_params = String::new();
-            let mut suggs = vec![];
-            let mut apit_spans = vec![];
-
-            for (i, (span, name)) in synthetics.into_iter().enumerate() {
-                apit_spans.push(span);
-
-                let fresh_param = next_fresh_param();
-
-                // Suggest renaming.
-                suggs.push((span, fresh_param.to_string()));
-
-                // Super jank. Turn `impl Trait` into `T: Trait`.
-                //
-                // This currently involves stripping the `impl` from the name of
-                // the parameter, since APITs are always named after how they are
-                // rendered in the AST. This sucks! But to recreate the bound list
-                // from the APIT itself would be miserable, so we're stuck with
-                // this for now!
-                if i > 0 {
-                    new_params += ", ";
-                }
-                let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
-                new_params += fresh_param.as_str();
-                new_params += ": ";
-                new_params += name_as_bounds;
-            }
-
-            let Some(generics) = tcx.hir().get_generics(fn_def_id) else {
-                // This shouldn't happen, but don't ICE.
-                return;
-            };
-
-            // Add generics or concatenate to the end of the list.
-            suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
-                (params_span, format!(", {new_params}"))
-            } else {
-                (generics.span, format!("<{new_params}>"))
-            });
-
-            let concatenated_bounds = captured_lifetimes
-                .into_iter()
-                .chain(captured_non_lifetimes)
-                .map(|sym| sym.to_string())
-                .collect::<Vec<_>>()
-                .join(", ");
-
-            suggs.push((
-                tcx.def_span(opaque_def_id).shrink_to_hi(),
-                format!(" + use<{concatenated_bounds}>"),
-            ));
-
-            diag.subdiagnostic(errors::AddPreciseCapturingAndParams {
-                suggs,
-                new_lifetime,
-                apit_spans,
-            });
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs b/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs
deleted file mode 100644
index ef26a8ff7b8..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::undo_log::NoUndo;
-use rustc_data_structures::unify as ut;
-use rustc_middle::ty;
-
-use crate::infer::InferCtxt;
-
-#[derive(Debug, Copy, Clone, PartialEq)]
-struct SubId(u32);
-impl ut::UnifyKey for SubId {
-    type Value = ();
-    #[inline]
-    fn index(&self) -> u32 {
-        self.0
-    }
-    #[inline]
-    fn from_index(i: u32) -> SubId {
-        SubId(i)
-    }
-    fn tag() -> &'static str {
-        "SubId"
-    }
-}
-
-/// When reporting ambiguity errors, we sometimes want to
-/// treat all inference vars which are subtypes of each
-/// others as if they are equal. For this case we compute
-/// the transitive closure of our subtype obligations here.
-///
-/// E.g. when encountering ambiguity errors, we want to suggest
-/// specifying some method argument or to add a type annotation
-/// to a local variable. Because subtyping cannot change the
-/// shape of a type, it's fine if the cause of the ambiguity error
-/// is only related to the suggested variable via subtyping.
-///
-/// Even for something like `let x = returns_arg(); x.method();` the
-/// type of `x` is only a supertype of the argument of `returns_arg`. We
-/// still want to suggest specifying the type of the argument.
-#[derive(Default)]
-pub struct SubRelations {
-    map: FxHashMap<ty::TyVid, SubId>,
-    table: ut::UnificationTableStorage<SubId>,
-}
-
-impl SubRelations {
-    fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId {
-        let root_vid = infcx.root_var(vid);
-        *self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(()))
-    }
-
-    pub fn add_constraints<'tcx>(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-        obls: impl IntoIterator<Item = ty::Predicate<'tcx>>,
-    ) {
-        for p in obls {
-            let (a, b) = match p.kind().skip_binder() {
-                ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
-                    (a, b)
-                }
-                ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
-                _ => continue,
-            };
-
-            match (a.kind(), b.kind()) {
-                (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
-                    let a = self.get_id(infcx, a_vid);
-                    let b = self.get_id(infcx, b_vid);
-                    self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap();
-                }
-                _ => continue,
-            }
-        }
-    }
-
-    pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool {
-        let a = self.get_id(infcx, a);
-        let b = self.get_id(infcx, b);
-        self.table.with_log(&mut NoUndo).unioned(a, b)
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/suggest.rs b/compiler/rustc_infer/src/error_reporting/infer/suggest.rs
deleted file mode 100644
index 4d11ab9fac6..00000000000
--- a/compiler/rustc_infer/src/error_reporting/infer/suggest.rs
+++ /dev/null
@@ -1,899 +0,0 @@
-use crate::error_reporting::infer::hir::Path;
-use core::ops::ControlFlow;
-use hir::def::CtorKind;
-use hir::intravisit::{walk_expr, walk_stmt, Visitor};
-use hir::{LetStmt, QPath};
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{Applicability, Diag};
-use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::MatchSource;
-use rustc_hir::Node;
-use rustc_middle::traits::{
-    IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
-    StatementAsExpression,
-};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
-use rustc_span::{sym, Span};
-
-use crate::errors::{
-    ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
-    FunctionPointerSuggestion, SuggestAccessingField, SuggestRemoveSemiOrReturnBinding,
-    SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
-};
-
-use super::TypeErrCtxt;
-
-#[derive(Clone, Copy)]
-pub enum SuggestAsRefKind {
-    Option,
-    Result,
-}
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    pub(super) fn suggest_remove_semi_or_return_binding(
-        &self,
-        first_id: Option<hir::HirId>,
-        first_ty: Ty<'tcx>,
-        first_span: Span,
-        second_id: Option<hir::HirId>,
-        second_ty: Ty<'tcx>,
-        second_span: Span,
-    ) -> Option<SuggestRemoveSemiOrReturnBinding> {
-        let remove_semicolon = [
-            (first_id, self.resolve_vars_if_possible(second_ty)),
-            (second_id, self.resolve_vars_if_possible(first_ty)),
-        ]
-        .into_iter()
-        .find_map(|(id, ty)| {
-            let hir::Node::Block(blk) = self.tcx.hir_node(id?) else { return None };
-            self.could_remove_semicolon(blk, ty)
-        });
-        match remove_semicolon {
-            Some((sp, StatementAsExpression::NeedsBoxing)) => {
-                Some(SuggestRemoveSemiOrReturnBinding::RemoveAndBox {
-                    first_lo: first_span.shrink_to_lo(),
-                    first_hi: first_span.shrink_to_hi(),
-                    second_lo: second_span.shrink_to_lo(),
-                    second_hi: second_span.shrink_to_hi(),
-                    sp,
-                })
-            }
-            Some((sp, StatementAsExpression::CorrectType)) => {
-                Some(SuggestRemoveSemiOrReturnBinding::Remove { sp })
-            }
-            None => {
-                let mut ret = None;
-                for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
-                    if let Some(id) = id
-                        && let hir::Node::Block(blk) = self.tcx.hir_node(id)
-                        && let Some(diag) = self.consider_returning_binding_diag(blk, ty)
-                    {
-                        ret = Some(diag);
-                        break;
-                    }
-                }
-                ret
-            }
-        }
-    }
-
-    pub(super) fn suggest_tuple_pattern(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
-        // some modifications due to that being in typeck and this being in infer.
-        if let ObligationCauseCode::Pattern { .. } = cause.code() {
-            if let ty::Adt(expected_adt, args) = exp_found.expected.kind() {
-                let compatible_variants: Vec<_> = expected_adt
-                    .variants()
-                    .iter()
-                    .filter(|variant| {
-                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
-                    })
-                    .filter_map(|variant| {
-                        let sole_field = &variant.single_field();
-                        let sole_field_ty = sole_field.ty(self.tcx, args);
-                        if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
-                            let variant_path =
-                                with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
-                            // FIXME #56861: DRYer prelude filtering
-                            if let Some(path) = variant_path.strip_prefix("std::prelude::") {
-                                if let Some((_, path)) = path.split_once("::") {
-                                    return Some(path.to_string());
-                                }
-                            }
-                            Some(variant_path)
-                        } else {
-                            None
-                        }
-                    })
-                    .collect();
-                match &compatible_variants[..] {
-                    [] => {}
-                    [variant] => {
-                        let sugg = SuggestTuplePatternOne {
-                            variant: variant.to_owned(),
-                            span_low: cause.span.shrink_to_lo(),
-                            span_high: cause.span.shrink_to_hi(),
-                        };
-                        diag.subdiagnostic(sugg);
-                    }
-                    _ => {
-                        // More than one matching variant.
-                        let sugg = SuggestTuplePatternMany {
-                            path: self.tcx.def_path_str(expected_adt.did()),
-                            cause_span: cause.span,
-                            compatible_variants,
-                        };
-                        diag.subdiagnostic(sugg);
-                    }
-                }
-            }
-        }
-    }
-
-    /// A possible error is to forget to add `.await` when using futures:
-    ///
-    /// ```compile_fail,E0308
-    /// async fn make_u32() -> u32 {
-    ///     22
-    /// }
-    ///
-    /// fn take_u32(x: u32) {}
-    ///
-    /// async fn foo() {
-    ///     let x = make_u32();
-    ///     take_u32(x);
-    /// }
-    /// ```
-    ///
-    /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
-    /// expected type. If this is the case, and we are inside of an async body, it suggests adding
-    /// `.await` to the tail of the expression.
-    pub(super) fn suggest_await_on_expect_found(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        debug!(
-            "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
-            exp_span, exp_found.expected, exp_found.found,
-        );
-
-        if let ObligationCauseCode::CompareImplItem { .. } = cause.code() {
-            return;
-        }
-
-        let subdiag = match (
-            self.get_impl_future_output_ty(exp_found.expected),
-            self.get_impl_future_output_ty(exp_found.found),
-        ) {
-            (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
-                .code()
-            {
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    Some(ConsiderAddingAwait::BothFuturesSugg {
-                        first: then_span.shrink_to_hi(),
-                        second: exp_span.shrink_to_hi(),
-                    })
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    prior_non_diverging_arms,
-                    ..
-                }) => {
-                    if let [.., arm_span] = &prior_non_diverging_arms[..] {
-                        Some(ConsiderAddingAwait::BothFuturesSugg {
-                            first: arm_span.shrink_to_hi(),
-                            second: exp_span.shrink_to_hi(),
-                        })
-                    } else {
-                        Some(ConsiderAddingAwait::BothFuturesHelp)
-                    }
-                }
-                _ => Some(ConsiderAddingAwait::BothFuturesHelp),
-            },
-            (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
-                // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
-                diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
-                    span: exp_span.shrink_to_hi(),
-                });
-                Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
-            }
-            (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
-            {
-                ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => {
-                    origin_expr.then_some(ConsiderAddingAwait::FutureSugg {
-                        span: then_span.shrink_to_hi(),
-                    })
-                }
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    ref prior_non_diverging_arms,
-                    ..
-                }) => Some({
-                    ConsiderAddingAwait::FutureSuggMultiple {
-                        spans: prior_non_diverging_arms
-                            .iter()
-                            .map(|arm| arm.shrink_to_hi())
-                            .collect(),
-                    }
-                }),
-                _ => None,
-            },
-            _ => None,
-        };
-        if let Some(subdiag) = subdiag {
-            diag.subdiagnostic(subdiag);
-        }
-    }
-
-    pub(super) fn suggest_accessing_field_where_appropriate(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        debug!(
-            "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
-            cause, exp_found
-        );
-        if let ty::Adt(expected_def, expected_args) = exp_found.expected.kind() {
-            if expected_def.is_enum() {
-                return;
-            }
-
-            if let Some((name, ty)) = expected_def
-                .non_enum_variant()
-                .fields
-                .iter()
-                .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
-                .map(|field| (field.name, field.ty(self.tcx, expected_args)))
-                .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
-            {
-                if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        let suggestion = if expected_def.is_struct() {
-                            SuggestAccessingField::Safe { span, snippet, name, ty }
-                        } else if expected_def.is_union() {
-                            SuggestAccessingField::Unsafe { span, snippet, name, ty }
-                        } else {
-                            return;
-                        };
-                        diag.subdiagnostic(suggestion);
-                    }
-                }
-            }
-        }
-    }
-
-    pub(super) fn suggest_turning_stmt_into_expr(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        let ty::error::ExpectedFound { expected, found } = exp_found;
-        if !found.peel_refs().is_unit() {
-            return;
-        }
-
-        let ObligationCauseCode::BlockTailExpression(hir_id, MatchSource::Normal) = cause.code()
-        else {
-            return;
-        };
-
-        let node = self.tcx.hir_node(*hir_id);
-        let mut blocks = vec![];
-        if let hir::Node::Block(block) = node
-            && let Some(expr) = block.expr
-            && let hir::ExprKind::Path(QPath::Resolved(_, Path { res, .. })) = expr.kind
-            && let Res::Local(local) = res
-            && let Node::LetStmt(LetStmt { init: Some(init), .. }) =
-                self.tcx.parent_hir_node(*local)
-        {
-            fn collect_blocks<'hir>(expr: &hir::Expr<'hir>, blocks: &mut Vec<&hir::Block<'hir>>) {
-                match expr.kind {
-                    // `blk1` and `blk2` must be have the same types, it will be reported before reaching here
-                    hir::ExprKind::If(_, blk1, Some(blk2)) => {
-                        collect_blocks(blk1, blocks);
-                        collect_blocks(blk2, blocks);
-                    }
-                    hir::ExprKind::Match(_, arms, _) => {
-                        // all arms must have same types
-                        for arm in arms.iter() {
-                            collect_blocks(arm.body, blocks);
-                        }
-                    }
-                    hir::ExprKind::Block(blk, _) => {
-                        blocks.push(blk);
-                    }
-                    _ => {}
-                }
-            }
-            collect_blocks(init, &mut blocks);
-        }
-
-        let expected_inner: Ty<'_> = expected.peel_refs();
-        for block in blocks.iter() {
-            self.consider_removing_semicolon(block, expected_inner, diag);
-        }
-    }
-
-    /// A common error is to add an extra semicolon:
-    ///
-    /// ```compile_fail,E0308
-    /// fn foo() -> usize {
-    ///     22;
-    /// }
-    /// ```
-    ///
-    /// This routine checks if the final statement in a block is an
-    /// expression with an explicit semicolon whose type is compatible
-    /// with `expected_ty`. If so, it suggests removing the semicolon.
-    pub fn consider_removing_semicolon(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-        diag: &mut Diag<'_>,
-    ) -> bool {
-        if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
-            if let StatementAsExpression::NeedsBoxing = boxed {
-                diag.span_suggestion_verbose(
-                    span_semi,
-                    "consider removing this semicolon and boxing the expression",
-                    "",
-                    Applicability::HasPlaceholders,
-                );
-            } else {
-                diag.span_suggestion_short(
-                    span_semi,
-                    "remove this semicolon to return this value",
-                    "",
-                    Applicability::MachineApplicable,
-                );
-            }
-            true
-        } else {
-            false
-        }
-    }
-
-    pub(super) fn suggest_function_pointers(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        debug!("suggest_function_pointers(cause={:?}, exp_found={:?})", cause, exp_found);
-        let ty::error::ExpectedFound { expected, found } = exp_found;
-        let expected_inner = expected.peel_refs();
-        let found_inner = found.peel_refs();
-        if !expected_inner.is_fn() || !found_inner.is_fn() {
-            return;
-        }
-        match (&expected_inner.kind(), &found_inner.kind()) {
-            (ty::FnPtr(sig), ty::FnDef(did, args)) => {
-                let expected_sig = &(self.normalize_fn_sig)(*sig);
-                let found_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
-
-                let fn_name = self.tcx.def_path_str_with_args(*did, args);
-
-                if !self.same_type_modulo_infer(*found_sig, *expected_sig)
-                    || !sig.is_suggestable(self.tcx, true)
-                    || self.tcx.intrinsic(*did).is_some()
-                {
-                    return;
-                }
-
-                let sugg = match (expected.is_ref(), found.is_ref()) {
-                    (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
-                    (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
-                    (true, true) => {
-                        diag.subdiagnostic(FnItemsAreDistinct);
-                        FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
-                    }
-                    (false, false) => {
-                        diag.subdiagnostic(FnItemsAreDistinct);
-                        FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
-                    }
-                };
-                diag.subdiagnostic(sugg);
-            }
-            (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
-                let expected_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did1).instantiate(self.tcx, args1));
-                let found_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2));
-
-                if self.same_type_modulo_infer(*expected_sig, *found_sig) {
-                    diag.subdiagnostic(FnUniqTypes);
-                }
-
-                if !self.same_type_modulo_infer(*found_sig, *expected_sig)
-                    || !found_sig.is_suggestable(self.tcx, true)
-                    || !expected_sig.is_suggestable(self.tcx, true)
-                    || self.tcx.intrinsic(*did1).is_some()
-                    || self.tcx.intrinsic(*did2).is_some()
-                {
-                    return;
-                }
-
-                let fn_name = self.tcx.def_path_str_with_args(*did2, args2);
-                let sug = if found.is_ref() {
-                    FunctionPointerSuggestion::CastBothRef {
-                        span,
-                        fn_name,
-                        found_sig: *found_sig,
-                        expected_sig: *expected_sig,
-                    }
-                } else {
-                    FunctionPointerSuggestion::CastBoth {
-                        span,
-                        fn_name,
-                        found_sig: *found_sig,
-                        expected_sig: *expected_sig,
-                    }
-                };
-
-                diag.subdiagnostic(sug);
-            }
-            (ty::FnDef(did, args), ty::FnPtr(sig)) => {
-                let expected_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
-                let found_sig = &(self.normalize_fn_sig)(*sig);
-
-                if !self.same_type_modulo_infer(*found_sig, *expected_sig) {
-                    return;
-                }
-
-                let fn_name = self.tcx.def_path_str_with_args(*did, args);
-
-                let casting = if expected.is_ref() {
-                    format!("&({fn_name} as {found_sig})")
-                } else {
-                    format!("{fn_name} as {found_sig}")
-                };
-
-                diag.subdiagnostic(FnConsiderCasting { casting });
-            }
-            _ => {
-                return;
-            }
-        };
-    }
-
-    pub fn should_suggest_as_ref_kind(
-        &self,
-        expected: Ty<'tcx>,
-        found: Ty<'tcx>,
-    ) -> Option<SuggestAsRefKind> {
-        if let (ty::Adt(exp_def, exp_args), ty::Ref(_, found_ty, _)) =
-            (expected.kind(), found.kind())
-        {
-            if let ty::Adt(found_def, found_args) = *found_ty.kind() {
-                if exp_def == &found_def {
-                    let have_as_ref = &[
-                        (sym::Option, SuggestAsRefKind::Option),
-                        (sym::Result, SuggestAsRefKind::Result),
-                    ];
-                    if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
-                        self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
-                    }) {
-                        let mut show_suggestion = true;
-                        for (exp_ty, found_ty) in
-                            std::iter::zip(exp_args.types(), found_args.types())
-                        {
-                            match *exp_ty.kind() {
-                                ty::Ref(_, exp_ty, _) => {
-                                    match (exp_ty.kind(), found_ty.kind()) {
-                                        (_, ty::Param(_))
-                                        | (_, ty::Infer(_))
-                                        | (ty::Param(_), _)
-                                        | (ty::Infer(_), _) => {}
-                                        _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
-                                        _ => show_suggestion = false,
-                                    };
-                                }
-                                ty::Param(_) | ty::Infer(_) => {}
-                                _ => show_suggestion = false,
-                            }
-                        }
-                        if show_suggestion {
-                            return Some(*msg);
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
-
-    // FIXME: Remove once `rustc_hir_typeck` is migrated to diagnostic structs
-    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
-        match self.should_suggest_as_ref_kind(expected, found) {
-            Some(SuggestAsRefKind::Option) => Some(
-                "you can convert from `&Option<T>` to `Option<&T>` using \
-            `.as_ref()`",
-            ),
-            Some(SuggestAsRefKind::Result) => Some(
-                "you can convert from `&Result<T, E>` to \
-            `Result<&T, &E>` using `.as_ref()`",
-            ),
-            None => None,
-        }
-    }
-    /// Try to find code with pattern `if Some(..) = expr`
-    /// use a `visitor` to mark the `if` which its span contains given error span,
-    /// and then try to find a assignment in the `cond` part, which span is equal with error span
-    pub(super) fn suggest_let_for_letchains(
-        &self,
-        cause: &ObligationCause<'_>,
-        span: Span,
-    ) -> Option<TypeErrorAdditionalDiags> {
-        /// Find the if expression with given span
-        struct IfVisitor {
-            pub found_if: bool,
-            pub err_span: Span,
-        }
-
-        impl<'v> Visitor<'v> for IfVisitor {
-            type Result = ControlFlow<()>;
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
-                match ex.kind {
-                    hir::ExprKind::If(cond, _, _) => {
-                        self.found_if = true;
-                        walk_expr(self, cond)?;
-                        self.found_if = false;
-                        ControlFlow::Continue(())
-                    }
-                    _ => walk_expr(self, ex),
-                }
-            }
-
-            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
-                if let hir::StmtKind::Let(LetStmt {
-                    span,
-                    pat: hir::Pat { .. },
-                    ty: None,
-                    init: Some(_),
-                    ..
-                }) = &ex.kind
-                    && self.found_if
-                    && span.eq(&self.err_span)
-                {
-                    ControlFlow::Break(())
-                } else {
-                    walk_stmt(self, ex)
-                }
-            }
-        }
-
-        self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body| {
-            IfVisitor { err_span: span, found_if: false }
-                .visit_body(&body)
-                .is_break()
-                .then(|| TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo() })
-        })
-    }
-
-    /// For "one type is more general than the other" errors on closures, suggest changing the lifetime
-    /// of the parameters to accept all lifetimes.
-    pub(super) fn suggest_for_all_lifetime_closure(
-        &self,
-        span: Span,
-        hir: hir::Node<'_>,
-        exp_found: &ty::error::ExpectedFound<ty::TraitRef<'tcx>>,
-        diag: &mut Diag<'_>,
-    ) {
-        // 0. Extract fn_decl from hir
-        let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }),
-            ..
-        }) = hir
-        else {
-            return;
-        };
-        let hir::Body { params, .. } = self.tcx.hir().body(*body);
-
-        // 1. Get the args of the closure.
-        // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
-        let Some(expected) = exp_found.expected.args.get(1) else {
-            return;
-        };
-        let Some(found) = exp_found.found.args.get(1) else {
-            return;
-        };
-        let expected = expected.unpack();
-        let found = found.unpack();
-        // 3. Extract the tuple type from Fn trait and suggest the change.
-        if let GenericArgKind::Type(expected) = expected
-            && let GenericArgKind::Type(found) = found
-            && let ty::Tuple(expected) = expected.kind()
-            && let ty::Tuple(found) = found.kind()
-            && expected.len() == found.len()
-        {
-            let mut suggestion = "|".to_string();
-            let mut is_first = true;
-            let mut has_suggestion = false;
-
-            for (((expected, found), param_hir), arg_hir) in
-                expected.iter().zip(found.iter()).zip(params.iter()).zip(fn_decl.inputs.iter())
-            {
-                if is_first {
-                    is_first = false;
-                } else {
-                    suggestion += ", ";
-                }
-
-                if let ty::Ref(expected_region, _, _) = expected.kind()
-                    && let ty::Ref(found_region, _, _) = found.kind()
-                    && expected_region.is_bound()
-                    && !found_region.is_bound()
-                    && let hir::TyKind::Infer = arg_hir.kind
-                {
-                    // If the expected region is late bound, the found region is not, and users are asking compiler
-                    // to infer the type, we can suggest adding `: &_`.
-                    if param_hir.pat.span == param_hir.ty_span {
-                        // for `|x|`, `|_|`, `|x: impl Foo|`
-                        let Ok(pat) =
-                            self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span)
-                        else {
-                            return;
-                        };
-                        suggestion += &format!("{pat}: &_");
-                    } else {
-                        // for `|x: ty|`, `|_: ty|`
-                        let Ok(pat) =
-                            self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span)
-                        else {
-                            return;
-                        };
-                        let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span)
-                        else {
-                            return;
-                        };
-                        suggestion += &format!("{pat}: &{ty}");
-                    }
-                    has_suggestion = true;
-                } else {
-                    let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else {
-                        return;
-                    };
-                    // Otherwise, keep it as-is.
-                    suggestion += &arg;
-                }
-            }
-            suggestion += "|";
-
-            if has_suggestion {
-                diag.span_suggestion_verbose(
-                    span,
-                    "consider specifying the type of the closure parameters",
-                    suggestion,
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        }
-    }
-}
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
-    /// is enough to fix the error.
-    pub fn could_remove_semicolon(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-    ) -> Option<(Span, StatementAsExpression)> {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return None;
-        }
-        let last_stmt = blk.stmts.last()?;
-        let hir::StmtKind::Semi(last_expr) = last_stmt.kind else {
-            return None;
-        };
-        let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(last_expr)?;
-        let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
-            _ if last_expr_ty.references_error() => return None,
-            _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
-                StatementAsExpression::CorrectType
-            }
-            (
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, .. }),
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
-            ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
-            (
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, args: last_bounds, .. }),
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, args: exp_bounds, .. }),
-            ) => {
-                debug!(
-                    "both opaque, likely future {:?} {:?} {:?} {:?}",
-                    last_def_id, last_bounds, exp_def_id, exp_bounds
-                );
-
-                let last_local_id = last_def_id.as_local()?;
-                let exp_local_id = exp_def_id.as_local()?;
-
-                match (
-                    &self.tcx.hir().expect_item(last_local_id).kind,
-                    &self.tcx.hir().expect_item(exp_local_id).kind,
-                ) {
-                    (
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
-                    ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| match (
-                        left, right,
-                    ) {
-                        (hir::GenericBound::Trait(tl, ml), hir::GenericBound::Trait(tr, mr))
-                            if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
-                                && ml == mr =>
-                        {
-                            true
-                        }
-                        _ => false,
-                    }) =>
-                    {
-                        StatementAsExpression::NeedsBoxing
-                    }
-                    _ => StatementAsExpression::CorrectType,
-                }
-            }
-            _ => return None,
-        };
-        let span = if last_stmt.span.from_expansion() {
-            let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
-            self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
-        } else {
-            self.tcx
-                .sess
-                .source_map()
-                .span_extend_while_whitespace(last_expr.span)
-                .shrink_to_hi()
-                .with_hi(last_stmt.span.hi())
-        };
-
-        Some((span, needs_box))
-    }
-
-    /// Suggest returning a local binding with a compatible type if the block
-    /// has no return expression.
-    pub fn consider_returning_binding_diag(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-    ) -> Option<SuggestRemoveSemiOrReturnBinding> {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return None;
-        }
-        let mut shadowed = FxIndexSet::default();
-        let mut candidate_idents = vec![];
-        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
-            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
-                && let Some(pat_ty) = self
-                    .typeck_results
-                    .as_ref()
-                    .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
-            {
-                let pat_ty = self.resolve_vars_if_possible(pat_ty);
-                if self.same_type_modulo_infer(pat_ty, expected_ty)
-                    && !(pat_ty, expected_ty).references_error()
-                    && shadowed.insert(ident.name)
-                {
-                    candidate_idents.push((*ident, pat_ty));
-                }
-            }
-            true
-        };
-
-        let hir = self.tcx.hir();
-        for stmt in blk.stmts.iter().rev() {
-            let hir::StmtKind::Let(local) = &stmt.kind else {
-                continue;
-            };
-            local.pat.walk(&mut find_compatible_candidates);
-        }
-        match self.tcx.parent_hir_node(blk.hir_id) {
-            hir::Node::Expr(hir::Expr { hir_id, .. }) => match self.tcx.parent_hir_node(*hir_id) {
-                hir::Node::Arm(hir::Arm { pat, .. }) => {
-                    pat.walk(&mut find_compatible_candidates);
-                }
-
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Fn(_, body), ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
-                    ..
-                })
-                | hir::Node::Expr(hir::Expr {
-                    kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
-                    ..
-                }) => {
-                    for param in hir.body(*body).params {
-                        param.pat.walk(&mut find_compatible_candidates);
-                    }
-                }
-                hir::Node::Expr(hir::Expr {
-                    kind:
-                        hir::ExprKind::If(
-                            hir::Expr { kind: hir::ExprKind::Let(let_), .. },
-                            then_block,
-                            _,
-                        ),
-                    ..
-                }) if then_block.hir_id == *hir_id => {
-                    let_.pat.walk(&mut find_compatible_candidates);
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-
-        match &candidate_idents[..] {
-            [(ident, _ty)] => {
-                let sm = self.tcx.sess.source_map();
-                let (span, sugg) = if let Some(stmt) = blk.stmts.last() {
-                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(stmt_span)
-                    {
-                        format!("\n{spacing}{ident}")
-                    } else {
-                        format!(" {ident}")
-                    };
-                    (stmt_span.shrink_to_hi(), sugg)
-                } else {
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
-                    {
-                        format!("\n{spacing}    {ident}\n{spacing}")
-                    } else {
-                        format!(" {ident} ")
-                    };
-                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
-                    (sm.span_extend_while_whitespace(left_span), sugg)
-                };
-                Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
-            }
-            values if (1..3).contains(&values.len()) => {
-                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
-                Some(SuggestRemoveSemiOrReturnBinding::AddOne { spans: spans.into() })
-            }
-            _ => None,
-        }
-    }
-
-    pub fn consider_returning_binding(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-        err: &mut Diag<'_>,
-    ) -> bool {
-        let diag = self.consider_returning_binding_diag(blk, expected_ty);
-        match diag {
-            Some(diag) => {
-                err.subdiagnostic(diag);
-                true
-            }
-            None => false,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/error_reporting/mod.rs b/compiler/rustc_infer/src/error_reporting/mod.rs
deleted file mode 100644
index 132485ec661..00000000000
--- a/compiler/rustc_infer/src/error_reporting/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod infer;
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 2ce712e0bff..1a5c0137219 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,28 +1,5 @@
-use hir::GenericParamKind;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{
-    codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, IntoDiagArg,
-    MultiSpan, SubdiagMessageOp, Subdiagnostic,
-};
-use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::FnRetTy;
-use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
-use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
-use rustc_span::symbol::kw;
-use rustc_span::Symbol;
-use rustc_span::{symbol::Ident, BytePos, Span};
-
-use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
-use crate::error_reporting::infer::ObligationCauseAsDiagArg;
-use crate::fluent_generated as fluent;
-use crate::infer::need_type_info::UnderspecifiedArgKind;
-
-use std::path::PathBuf;
-
-pub mod note_and_explain;
+use rustc_macros::Diagnostic;
+use rustc_span::Span;
 
 #[derive(Diagnostic)]
 #[diag(infer_opaque_hidden_type)]
@@ -35,1599 +12,3 @@ pub struct OpaqueHiddenTypeDiag {
     #[note(infer_hidden_type)]
     pub hidden_type: Span,
 }
-
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0282)]
-pub struct AnnotationRequired<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Copy of `AnnotationRequired` for E0283
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0283)]
-pub struct AmbiguousImpl<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Copy of `AnnotationRequired` for E0284
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0284)]
-pub struct AmbiguousReturn<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Used when a better one isn't available
-#[derive(Subdiagnostic)]
-#[label(infer_label_bad)]
-pub struct InferenceBadError<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub bad_kind: &'static str,
-    pub prefix_kind: UnderspecifiedArgKind,
-    pub has_parent: bool,
-    pub prefix: &'a str,
-    pub parent_prefix: &'a str,
-    pub parent_name: String,
-    pub name: String,
-}
-
-#[derive(Subdiagnostic)]
-pub enum SourceKindSubdiag<'a> {
-    #[suggestion(
-        infer_source_kind_subdiag_let,
-        style = "verbose",
-        code = ": {type_name}",
-        applicability = "has-placeholders"
-    )]
-    LetLike {
-        #[primary_span]
-        span: Span,
-        name: String,
-        type_name: String,
-        kind: &'static str,
-        x_kind: &'static str,
-        prefix_kind: UnderspecifiedArgKind,
-        prefix: &'a str,
-        arg_name: String,
-    },
-    #[label(infer_source_kind_subdiag_generic_label)]
-    GenericLabel {
-        #[primary_span]
-        span: Span,
-        is_type: bool,
-        param_name: String,
-        parent_exists: bool,
-        parent_prefix: String,
-        parent_name: String,
-    },
-    #[suggestion(
-        infer_source_kind_subdiag_generic_suggestion,
-        style = "verbose",
-        code = "::<{args}>",
-        applicability = "has-placeholders"
-    )]
-    GenericSuggestion {
-        #[primary_span]
-        span: Span,
-        arg_count: usize,
-        args: String,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum SourceKindMultiSuggestion<'a> {
-    #[multipart_suggestion(
-        infer_source_kind_fully_qualified,
-        style = "verbose",
-        applicability = "has-placeholders"
-    )]
-    FullyQualified {
-        #[suggestion_part(code = "{def_path}({adjustment}")]
-        span_lo: Span,
-        #[suggestion_part(code = "{successor_pos}")]
-        span_hi: Span,
-        def_path: String,
-        adjustment: &'a str,
-        successor_pos: &'a str,
-    },
-    #[multipart_suggestion(
-        infer_source_kind_closure_return,
-        style = "verbose",
-        applicability = "has-placeholders"
-    )]
-    ClosureReturn {
-        #[suggestion_part(code = "{start_span_code}")]
-        start_span: Span,
-        start_span_code: String,
-        #[suggestion_part(code = " }}")]
-        end_span: Option<Span>,
-    },
-}
-
-impl<'a> SourceKindMultiSuggestion<'a> {
-    pub fn new_fully_qualified(
-        span: Span,
-        def_path: String,
-        adjustment: &'a str,
-        successor: (&'a str, BytePos),
-    ) -> Self {
-        Self::FullyQualified {
-            span_lo: span.shrink_to_lo(),
-            span_hi: span.shrink_to_hi().with_hi(successor.1),
-            def_path,
-            adjustment,
-            successor_pos: successor.0,
-        }
-    }
-
-    pub fn new_closure_return(
-        ty_info: String,
-        data: &'a FnRetTy<'a>,
-        should_wrap_expr: Option<Span>,
-    ) -> Self {
-        let arrow = match data {
-            FnRetTy::DefaultReturn(_) => " -> ",
-            _ => "",
-        };
-        let (start_span, start_span_code, end_span) = match should_wrap_expr {
-            Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
-            None => (data.span(), format!("{arrow}{ty_info}"), None),
-        };
-        Self::ClosureReturn { start_span, start_span_code, end_span }
-    }
-}
-
-pub enum RegionOriginNote<'a> {
-    Plain {
-        span: Span,
-        msg: DiagMessage,
-    },
-    WithName {
-        span: Span,
-        msg: DiagMessage,
-        name: &'a str,
-        continues: bool,
-    },
-    WithRequirement {
-        span: Span,
-        requirement: ObligationCauseAsDiagArg<'a>,
-        expected_found: Option<(DiagStyledString, DiagStyledString)>,
-    },
-}
-
-impl Subdiagnostic for RegionOriginNote<'_> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        let mut label_or_note = |span, msg: DiagMessage| {
-            let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
-            let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
-            let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
-            if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
-                diag.span_label(span, msg);
-            } else if span_is_primary && expanded_sub_count == 0 {
-                diag.note(msg);
-            } else {
-                diag.span_note(span, msg);
-            }
-        };
-        match self {
-            RegionOriginNote::Plain { span, msg } => {
-                label_or_note(span, msg);
-            }
-            RegionOriginNote::WithName { span, msg, name, continues } => {
-                label_or_note(span, msg);
-                diag.arg("name", name);
-                diag.arg("continues", continues);
-            }
-            RegionOriginNote::WithRequirement {
-                span,
-                requirement,
-                expected_found: Some((expected, found)),
-            } => {
-                label_or_note(span, fluent::infer_subtype);
-                diag.arg("requirement", requirement);
-
-                diag.note_expected_found(&"", expected, &"", found);
-            }
-            RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
-                // FIXME: this really should be handled at some earlier stage. Our
-                // handling of region checking when type errors are present is
-                // *terrible*.
-                label_or_note(span, fluent::infer_subtype_2);
-                diag.arg("requirement", requirement);
-            }
-        };
-    }
-}
-
-pub enum LifetimeMismatchLabels {
-    InRet {
-        param_span: Span,
-        ret_span: Span,
-        span: Span,
-        label_var1: Option<Ident>,
-    },
-    Normal {
-        hir_equal: bool,
-        ty_sup: Span,
-        ty_sub: Span,
-        span: Span,
-        sup: Option<Ident>,
-        sub: Option<Ident>,
-    },
-}
-
-impl Subdiagnostic for LifetimeMismatchLabels {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        match self {
-            LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
-                diag.span_label(param_span, fluent::infer_declared_different);
-                diag.span_label(ret_span, fluent::infer_nothing);
-                diag.span_label(span, fluent::infer_data_returned);
-                diag.arg("label_var1_exists", label_var1.is_some());
-                diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
-            }
-            LifetimeMismatchLabels::Normal {
-                hir_equal,
-                ty_sup,
-                ty_sub,
-                span,
-                sup: label_var1,
-                sub: label_var2,
-            } => {
-                if hir_equal {
-                    diag.span_label(ty_sup, fluent::infer_declared_multiple);
-                    diag.span_label(ty_sub, fluent::infer_nothing);
-                    diag.span_label(span, fluent::infer_data_lifetime_flow);
-                } else {
-                    diag.span_label(ty_sup, fluent::infer_types_declared_different);
-                    diag.span_label(ty_sub, fluent::infer_nothing);
-                    diag.span_label(span, fluent::infer_data_flows);
-                    diag.arg("label_var1_exists", label_var1.is_some());
-                    diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
-                    diag.arg("label_var2_exists", label_var2.is_some());
-                    diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
-                }
-            }
-        }
-    }
-}
-
-pub struct AddLifetimeParamsSuggestion<'a> {
-    pub tcx: TyCtxt<'a>,
-    pub generic_param_scope: LocalDefId,
-    pub sub: Region<'a>,
-    pub ty_sup: &'a hir::Ty<'a>,
-    pub ty_sub: &'a hir::Ty<'a>,
-    pub add_note: bool,
-}
-
-impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        let mut mk_suggestion = || {
-            let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
-            else {
-                return false;
-            };
-
-            let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
-            let is_impl = matches!(&node, hir::Node::ImplItem(_));
-            let (generics, parent_generics) = match node {
-                hir::Node::Item(&hir::Item {
-                    kind: hir::ItemKind::Fn(_, ref generics, ..),
-                    ..
-                })
-                | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
-                | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
-                    generics,
-                    match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id))
-                    {
-                        hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::Trait(_, _, ref generics, ..),
-                            ..
-                        })
-                        | hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }),
-                            ..
-                        }) => Some(generics),
-                        _ => None,
-                    },
-                ),
-                _ => return false,
-            };
-
-            let suggestion_param_name = generics
-                .params
-                .iter()
-                .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                .map(|p| p.name.ident().name)
-                .find(|i| *i != kw::UnderscoreLifetime);
-            let introduce_new = suggestion_param_name.is_none();
-
-            let mut default = "'a".to_string();
-            if let Some(parent_generics) = parent_generics {
-                let used: FxHashSet<_> = parent_generics
-                    .params
-                    .iter()
-                    .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                    .map(|p| p.name.ident().name)
-                    .filter(|i| *i != kw::UnderscoreLifetime)
-                    .map(|l| l.to_string())
-                    .collect();
-                if let Some(lt) =
-                    ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
-                {
-                    // We want a lifetime that *isn't* present in the `trait` or `impl` that assoc
-                    // `fn` belongs to. We could suggest reusing one of their lifetimes, but it is
-                    // likely to be an over-constraining lifetime requirement, so we always add a
-                    // lifetime to the `fn`.
-                    default = lt;
-                }
-            }
-            let suggestion_param_name =
-                suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
-
-            struct ImplicitLifetimeFinder {
-                suggestions: Vec<(Span, String)>,
-                suggestion_param_name: String,
-            }
-
-            impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
-                fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                    let make_suggestion = |ident: Ident| {
-                        if ident.name == kw::Empty && ident.span.is_empty() {
-                            format!("{}, ", self.suggestion_param_name)
-                        } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
-                            format!("{} ", self.suggestion_param_name)
-                        } else {
-                            self.suggestion_param_name.clone()
-                        }
-                    };
-                    match ty.kind {
-                        hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
-                            for segment in path.segments {
-                                if let Some(args) = segment.args {
-                                    if args.args.iter().all(|arg| {
-                                        matches!(
-                                            arg,
-                                            hir::GenericArg::Lifetime(lifetime)
-                                            if lifetime.ident.name == kw::Empty
-                                        )
-                                    }) {
-                                        self.suggestions.push((
-                                            segment.ident.span.shrink_to_hi(),
-                                            format!(
-                                                "<{}>",
-                                                args.args
-                                                    .iter()
-                                                    .map(|_| self.suggestion_param_name.clone())
-                                                    .collect::<Vec<_>>()
-                                                    .join(", ")
-                                            ),
-                                        ));
-                                    } else {
-                                        for arg in args.args {
-                                            if let hir::GenericArg::Lifetime(lifetime) = arg
-                                                && lifetime.is_anonymous()
-                                            {
-                                                self.suggestions.push((
-                                                    lifetime.ident.span,
-                                                    make_suggestion(lifetime.ident),
-                                                ));
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
-                            self.suggestions
-                                .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
-                        }
-                        _ => {}
-                    }
-                    walk_ty(self, ty);
-                }
-            }
-            let mut visitor = ImplicitLifetimeFinder {
-                suggestions: vec![],
-                suggestion_param_name: suggestion_param_name.clone(),
-            };
-            if let Some(fn_decl) = node.fn_decl()
-                && let hir::FnRetTy::Return(ty) = fn_decl.output
-            {
-                visitor.visit_ty(ty);
-            }
-            if visitor.suggestions.is_empty() {
-                // Do not suggest constraining the `&self` param, but rather the return type.
-                // If that is wrong (because it is not sufficient), a follow up error will tell the
-                // user to fix it. This way we lower the chances of *over* constraining, but still
-                // get the cake of "correctly" contrained in two steps.
-                visitor.visit_ty(self.ty_sup);
-            }
-            visitor.visit_ty(self.ty_sub);
-            if visitor.suggestions.is_empty() {
-                return false;
-            }
-            if introduce_new {
-                let new_param_suggestion = if let Some(first) =
-                    generics.params.iter().find(|p| !p.name.ident().span.is_empty())
-                {
-                    (first.span.shrink_to_lo(), format!("{suggestion_param_name}, "))
-                } else {
-                    (generics.span, format!("<{suggestion_param_name}>"))
-                };
-
-                visitor.suggestions.push(new_param_suggestion);
-            }
-            diag.multipart_suggestion_verbose(
-                fluent::infer_lifetime_param_suggestion,
-                visitor.suggestions,
-                Applicability::MaybeIncorrect,
-            );
-            diag.arg("is_impl", is_impl);
-            diag.arg("is_reuse", !introduce_new);
-
-            true
-        };
-        if mk_suggestion() && self.add_note {
-            diag.note(fluent::infer_lifetime_param_suggestion_elided);
-        }
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_lifetime_mismatch, code = E0623)]
-pub struct LifetimeMismatch<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub labels: LifetimeMismatchLabels,
-    #[subdiagnostic]
-    pub suggestion: AddLifetimeParamsSuggestion<'a>,
-}
-
-pub struct IntroducesStaticBecauseUnmetLifetimeReq {
-    pub unmet_requirements: MultiSpan,
-    pub binding_span: Span,
-}
-
-impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        mut self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        self.unmet_requirements
-            .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
-        diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
-    }
-}
-
-// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
-#[derive(Subdiagnostic)]
-pub enum DoesNotOutliveStaticFromImpl {
-    #[note(infer_does_not_outlive_static_from_impl)]
-    Spanned {
-        #[primary_span]
-        span: Span,
-    },
-    #[note(infer_does_not_outlive_static_from_impl)]
-    Unspanned,
-}
-
-#[derive(Subdiagnostic)]
-pub enum ImplicitStaticLifetimeSubdiag {
-    #[note(infer_implicit_static_lifetime_note)]
-    Note {
-        #[primary_span]
-        span: Span,
-    },
-    #[suggestion(
-        infer_implicit_static_lifetime_suggestion,
-        style = "verbose",
-        code = " + '_",
-        applicability = "maybe-incorrect"
-    )]
-    Sugg {
-        #[primary_span]
-        span: Span,
-    },
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_mismatched_static_lifetime)]
-pub struct MismatchedStaticLifetime<'a> {
-    #[primary_span]
-    pub cause_span: Span,
-    #[subdiagnostic]
-    pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
-    #[subdiagnostic]
-    pub expl: Option<note_and_explain::RegionExplanation<'a>>,
-    #[subdiagnostic]
-    pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
-    #[subdiagnostic]
-    pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
-}
-
-#[derive(Diagnostic)]
-pub enum ExplicitLifetimeRequired<'a> {
-    #[diag(infer_explicit_lifetime_required_with_ident, code = E0621)]
-    WithIdent {
-        #[primary_span]
-        #[label]
-        span: Span,
-        simple_ident: Ident,
-        named: String,
-        #[suggestion(
-            infer_explicit_lifetime_required_sugg_with_ident,
-            code = "{new_ty}",
-            applicability = "unspecified"
-        )]
-        new_ty_span: Span,
-        #[skip_arg]
-        new_ty: Ty<'a>,
-    },
-    #[diag(infer_explicit_lifetime_required_with_param_type, code = E0621)]
-    WithParamType {
-        #[primary_span]
-        #[label]
-        span: Span,
-        named: String,
-        #[suggestion(
-            infer_explicit_lifetime_required_sugg_with_param_type,
-            code = "{new_ty}",
-            applicability = "unspecified"
-        )]
-        new_ty_span: Span,
-        #[skip_arg]
-        new_ty: Ty<'a>,
-    },
-}
-
-pub enum TyOrSig<'tcx> {
-    Ty(Highlighted<'tcx, Ty<'tcx>>),
-    ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
-}
-
-impl IntoDiagArg for TyOrSig<'_> {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        match self {
-            TyOrSig::Ty(ty) => ty.into_diag_arg(),
-            TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
-        }
-    }
-}
-
-#[derive(Subdiagnostic)]
-pub enum ActualImplExplNotes<'tcx> {
-    #[note(infer_actual_impl_expl_expected_signature_two)]
-    ExpectedSignatureTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_any)]
-    ExpectedSignatureAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_some)]
-    ExpectedSignatureSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_nothing)]
-    ExpectedSignatureNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_two)]
-    ExpectedPassiveTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_any)]
-    ExpectedPassiveAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_some)]
-    ExpectedPassiveSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_nothing)]
-    ExpectedPassiveNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_expected_other_two)]
-    ExpectedOtherTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_any)]
-    ExpectedOtherAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_some)]
-    ExpectedOtherSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_nothing)]
-    ExpectedOtherNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_but_actually_implements_trait)]
-    ButActuallyImplementsTrait {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-    },
-    #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
-    ButActuallyImplementedForTy {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-        ty: String,
-    },
-    #[note(infer_actual_impl_expl_but_actually_ty_implements)]
-    ButActuallyTyImplements {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-        ty: String,
-    },
-}
-
-pub enum ActualImplExpectedKind {
-    Signature,
-    Passive,
-    Other,
-}
-
-pub enum ActualImplExpectedLifetimeKind {
-    Two,
-    Any,
-    Some,
-    Nothing,
-}
-
-impl<'tcx> ActualImplExplNotes<'tcx> {
-    pub fn new_expected(
-        kind: ActualImplExpectedKind,
-        lt_kind: ActualImplExpectedLifetimeKind,
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    ) -> Self {
-        match (kind, lt_kind) {
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedSignatureTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedPassiveTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedOtherTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-        }
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_trait_placeholder_mismatch)]
-pub struct TraitPlaceholderMismatch<'tcx> {
-    #[primary_span]
-    pub span: Span,
-    #[label(infer_label_satisfy)]
-    pub satisfy_span: Option<Span>,
-    #[label(infer_label_where)]
-    pub where_span: Option<Span>,
-    #[label(infer_label_dup)]
-    pub dup_span: Option<Span>,
-    pub def_id: String,
-    pub trait_def_id: String,
-
-    #[subdiagnostic]
-    pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
-}
-
-pub struct ConsiderBorrowingParamHelp {
-    pub spans: Vec<Span>,
-}
-
-impl Subdiagnostic for ConsiderBorrowingParamHelp {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        let mut type_param_span: MultiSpan = self.spans.clone().into();
-        for &span in &self.spans {
-            // Seems like we can't call f() here as Into<DiagMessage> is required
-            type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
-        }
-        let msg = f(diag, fluent::infer_tid_param_help.into());
-        diag.span_help(type_param_span, msg);
-    }
-}
-
-#[derive(Subdiagnostic)]
-#[help(infer_tid_rel_help)]
-pub struct RelationshipHelp;
-
-#[derive(Diagnostic)]
-#[diag(infer_trait_impl_diff)]
-pub struct TraitImplDiff {
-    #[primary_span]
-    #[label(infer_found)]
-    pub sp: Span,
-    #[label(infer_expected)]
-    pub trait_sp: Span,
-    #[note(infer_expected_found)]
-    pub note: (),
-    #[subdiagnostic]
-    pub param_help: ConsiderBorrowingParamHelp,
-    #[subdiagnostic]
-    // Seems like subdiagnostics are always pushed to the end, so this one
-    // also has to be a subdiagnostic to maintain order.
-    pub rel_help: Option<RelationshipHelp>,
-    pub expected: String,
-    pub found: String,
-}
-
-pub struct DynTraitConstraintSuggestion {
-    pub span: Span,
-    pub ident: Ident,
-}
-
-impl Subdiagnostic for DynTraitConstraintSuggestion {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        let mut multi_span: MultiSpan = vec![self.span].into();
-        multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
-        multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
-        let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
-        diag.span_note(multi_span, msg);
-        let msg = f(diag, fluent::infer_dtcs_suggestion.into());
-        diag.span_suggestion_verbose(
-            self.span.shrink_to_hi(),
-            msg,
-            " + '_",
-            Applicability::MaybeIncorrect,
-        );
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_but_calling_introduces, code = E0772)]
-pub struct ButCallingIntroduces {
-    #[label(infer_label1)]
-    pub param_ty_span: Span,
-    #[primary_span]
-    #[label(infer_label2)]
-    pub cause_span: Span,
-
-    pub has_param_name: bool,
-    pub param_name: String,
-    pub has_lifetime: bool,
-    pub lifetime: String,
-    pub assoc_item: Symbol,
-    pub has_impl_path: bool,
-    pub impl_path: String,
-}
-
-pub struct ReqIntroducedLocations {
-    pub span: MultiSpan,
-    pub spans: Vec<Span>,
-    pub fn_decl_span: Span,
-    pub cause_span: Span,
-    pub add_label: bool,
-}
-
-impl Subdiagnostic for ReqIntroducedLocations {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        mut self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        for sp in self.spans {
-            self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
-        }
-
-        if self.add_label {
-            self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
-        }
-        self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
-        let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
-        diag.span_note(self.span, msg);
-    }
-}
-
-pub struct MoreTargeted {
-    pub ident: Symbol,
-}
-
-impl Subdiagnostic for MoreTargeted {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        diag.code(E0772);
-        diag.primary_message(fluent::infer_more_targeted);
-        diag.arg("ident", self.ident);
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_but_needs_to_satisfy, code = E0759)]
-pub struct ButNeedsToSatisfy {
-    #[primary_span]
-    pub sp: Span,
-    #[label(infer_influencer)]
-    pub influencer_point: Span,
-    #[label(infer_used_here)]
-    pub spans: Vec<Span>,
-    #[label(infer_require)]
-    pub require_span_as_label: Option<Span>,
-    #[note(infer_require)]
-    pub require_span_as_note: Option<Span>,
-    #[note(infer_introduced_by_bound)]
-    pub bound: Option<Span>,
-
-    #[subdiagnostic]
-    pub req_introduces_loc: Option<ReqIntroducedLocations>,
-
-    pub has_param_name: bool,
-    pub param_name: String,
-    pub spans_empty: bool,
-    pub has_lifetime: bool,
-    pub lifetime: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_outlives_content, code = E0312)]
-pub struct OutlivesContent<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_outlives_bound, code = E0476)]
-pub struct OutlivesBound<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_fulfill_req_lifetime, code = E0477)]
-pub struct FulfillReqLifetime<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub ty: Ty<'a>,
-    #[subdiagnostic]
-    pub note: Option<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_lf_bound_not_satisfied, code = E0478)]
-pub struct LfBoundNotSatisfied<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_ref_longer_than_data, code = E0491)]
-pub struct RefLongerThanData<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub ty: Ty<'a>,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Subdiagnostic)]
-pub enum WhereClauseSuggestions {
-    #[suggestion(
-        infer_where_remove,
-        code = "",
-        applicability = "machine-applicable",
-        style = "verbose"
-    )]
-    Remove {
-        #[primary_span]
-        span: Span,
-    },
-    #[suggestion(
-        infer_where_copy_predicates,
-        code = "{space}where {trait_predicates}",
-        applicability = "machine-applicable",
-        style = "verbose"
-    )]
-    CopyPredicates {
-        #[primary_span]
-        span: Span,
-        space: &'static str,
-        trait_predicates: String,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum SuggestRemoveSemiOrReturnBinding {
-    #[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
-    RemoveAndBox {
-        #[suggestion_part(code = "Box::new(")]
-        first_lo: Span,
-        #[suggestion_part(code = ")")]
-        first_hi: Span,
-        #[suggestion_part(code = "Box::new(")]
-        second_lo: Span,
-        #[suggestion_part(code = ")")]
-        second_hi: Span,
-        #[suggestion_part(code = "")]
-        sp: Span,
-    },
-    #[suggestion(
-        infer_srs_remove,
-        style = "short",
-        code = "",
-        applicability = "machine-applicable"
-    )]
-    Remove {
-        #[primary_span]
-        sp: Span,
-    },
-    #[suggestion(
-        infer_srs_add,
-        style = "verbose",
-        code = "{code}",
-        applicability = "maybe-incorrect"
-    )]
-    Add {
-        #[primary_span]
-        sp: Span,
-        code: String,
-        ident: Ident,
-    },
-    #[note(infer_srs_add_one)]
-    AddOne {
-        #[primary_span]
-        spans: MultiSpan,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum ConsiderAddingAwait {
-    #[help(infer_await_both_futures)]
-    BothFuturesHelp,
-    #[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
-    BothFuturesSugg {
-        #[suggestion_part(code = ".await")]
-        first: Span,
-        #[suggestion_part(code = ".await")]
-        second: Span,
-    },
-    #[suggestion(
-        infer_await_future,
-        code = ".await",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    FutureSugg {
-        #[primary_span]
-        span: Span,
-    },
-    #[note(infer_await_note)]
-    FutureSuggNote {
-        #[primary_span]
-        span: Span,
-    },
-    #[multipart_suggestion(
-        infer_await_future,
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    FutureSuggMultiple {
-        #[suggestion_part(code = ".await")]
-        spans: Vec<Span>,
-    },
-}
-
-#[derive(Diagnostic)]
-pub enum PlaceholderRelationLfNotSatisfied {
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasBoth {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_with_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_with_sup)]
-        sup_span: Span,
-        sub_symbol: Symbol,
-        sup_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasSub {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_with_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_without_sup)]
-        sup_span: Span,
-        sub_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasSup {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_without_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_with_sup)]
-        sup_span: Span,
-        sup_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasNone {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_without_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_without_sup)]
-        sup_span: Span,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    OnlyPrimarySpan {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_opaque_captures_lifetime, code = E0700)]
-pub struct OpaqueCapturesLifetime<'tcx> {
-    #[primary_span]
-    pub span: Span,
-    #[label]
-    pub opaque_ty_span: Span,
-    pub opaque_ty: Ty<'tcx>,
-}
-
-#[derive(Subdiagnostic)]
-pub enum FunctionPointerSuggestion<'a> {
-    #[suggestion(
-        infer_fps_use_ref,
-        code = "&{fn_name}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    UseRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-    },
-    #[suggestion(
-        infer_fps_remove_ref,
-        code = "{fn_name}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    RemoveRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-    },
-    #[suggestion(
-        infer_fps_cast,
-        code = "&({fn_name} as {sig})",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    CastRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast,
-        code = "{fn_name} as {sig}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    Cast {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast_both,
-        code = "{fn_name} as {found_sig}",
-        style = "hidden",
-        applicability = "maybe-incorrect"
-    )]
-    CastBoth {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        found_sig: Binder<'a, FnSig<'a>>,
-        expected_sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast_both,
-        code = "&({fn_name} as {found_sig})",
-        style = "hidden",
-        applicability = "maybe-incorrect"
-    )]
-    CastBothRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        found_sig: Binder<'a, FnSig<'a>>,
-        expected_sig: Binder<'a, FnSig<'a>>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-#[note(infer_fps_items_are_distinct)]
-pub struct FnItemsAreDistinct;
-
-#[derive(Subdiagnostic)]
-#[note(infer_fn_uniq_types)]
-pub struct FnUniqTypes;
-
-#[derive(Subdiagnostic)]
-#[help(infer_fn_consider_casting)]
-pub struct FnConsiderCasting {
-    pub casting: String,
-}
-
-#[derive(Subdiagnostic)]
-pub enum SuggestAccessingField<'a> {
-    #[suggestion(
-        infer_suggest_accessing_field,
-        code = "{snippet}.{name}",
-        applicability = "maybe-incorrect"
-    )]
-    Safe {
-        #[primary_span]
-        span: Span,
-        snippet: String,
-        name: Symbol,
-        ty: Ty<'a>,
-    },
-    #[suggestion(
-        infer_suggest_accessing_field,
-        code = "unsafe {{ {snippet}.{name} }}",
-        applicability = "maybe-incorrect"
-    )]
-    Unsafe {
-        #[primary_span]
-        span: Span,
-        snippet: String,
-        name: Symbol,
-        ty: Ty<'a>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-#[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
-pub struct SuggestTuplePatternOne {
-    pub variant: String,
-    #[suggestion_part(code = "{variant}(")]
-    pub span_low: Span,
-    #[suggestion_part(code = ")")]
-    pub span_high: Span,
-}
-
-pub struct SuggestTuplePatternMany {
-    pub path: String,
-    pub cause_span: Span,
-    pub compatible_variants: Vec<String>,
-}
-
-impl Subdiagnostic for SuggestTuplePatternMany {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        diag.arg("path", self.path);
-        let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
-        diag.multipart_suggestions(
-            message,
-            self.compatible_variants.into_iter().map(|variant| {
-                vec![
-                    (self.cause_span.shrink_to_lo(), format!("{variant}(")),
-                    (self.cause_span.shrink_to_hi(), ")".to_string()),
-                ]
-            }),
-            rustc_errors::Applicability::MaybeIncorrect,
-        );
-    }
-}
-
-#[derive(Subdiagnostic)]
-pub enum TypeErrorAdditionalDiags {
-    #[suggestion(
-        infer_meant_byte_literal,
-        code = "b'{code}'",
-        applicability = "machine-applicable"
-    )]
-    MeantByteLiteral {
-        #[primary_span]
-        span: Span,
-        code: String,
-    },
-    #[suggestion(
-        infer_meant_char_literal,
-        code = "'{code}'",
-        applicability = "machine-applicable"
-    )]
-    MeantCharLiteral {
-        #[primary_span]
-        span: Span,
-        code: String,
-    },
-    #[multipart_suggestion(infer_meant_str_literal, applicability = "machine-applicable")]
-    MeantStrLiteral {
-        #[suggestion_part(code = "\"")]
-        start: Span,
-        #[suggestion_part(code = "\"")]
-        end: Span,
-    },
-    #[suggestion(
-        infer_consider_specifying_length,
-        code = "{length}",
-        applicability = "maybe-incorrect"
-    )]
-    ConsiderSpecifyingLength {
-        #[primary_span]
-        span: Span,
-        length: u64,
-    },
-    #[note(infer_try_cannot_convert)]
-    TryCannotConvert { found: String, expected: String },
-    #[suggestion(infer_tuple_trailing_comma, code = ",", applicability = "machine-applicable")]
-    TupleOnlyComma {
-        #[primary_span]
-        span: Span,
-    },
-    #[multipart_suggestion(infer_tuple_trailing_comma, applicability = "machine-applicable")]
-    TupleAlsoParentheses {
-        #[suggestion_part(code = "(")]
-        span_low: Span,
-        #[suggestion_part(code = ",)")]
-        span_high: Span,
-    },
-    #[suggestion(
-        infer_suggest_add_let_for_letchains,
-        style = "verbose",
-        applicability = "machine-applicable",
-        code = "let "
-    )]
-    AddLetForLetChains {
-        #[primary_span]
-        span: Span,
-    },
-}
-
-#[derive(Diagnostic)]
-pub enum ObligationCauseFailureCode {
-    #[diag(infer_oc_method_compat, code = E0308)]
-    MethodCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_type_compat, code = E0308)]
-    TypeCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_const_compat, code = E0308)]
-    ConstCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_try_compat, code = E0308)]
-    TryCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_match_compat, code = E0308)]
-    MatchCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_if_else_different, code = E0308)]
-    IfElseDifferent {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_no_else, code = E0317)]
-    NoElse {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_no_diverge, code = E0308)]
-    NoDiverge {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_fn_main_correct_type, code = E0580)]
-    FnMainCorrectType {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_fn_start_correct_type, code = E0308)]
-    FnStartCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_fn_lang_correct_type, code = E0308)]
-    FnLangCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-        lang_item_name: Symbol,
-    },
-    #[diag(infer_oc_intrinsic_correct_type, code = E0308)]
-    IntrinsicCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_method_correct_type, code = E0308)]
-    MethodCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_closure_selfref, code = E0644)]
-    ClosureSelfref {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_cant_coerce, code = E0308)]
-    CantCoerce {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_generic, code = E0308)]
-    Generic {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum AddPreciseCapturing {
-    #[suggestion(
-        infer_precise_capturing_new,
-        style = "verbose",
-        code = " + use<{concatenated_bounds}>",
-        applicability = "machine-applicable"
-    )]
-    New {
-        #[primary_span]
-        span: Span,
-        new_lifetime: Symbol,
-        concatenated_bounds: String,
-    },
-    #[suggestion(
-        infer_precise_capturing_existing,
-        style = "verbose",
-        code = "{pre}{new_lifetime}{post}",
-        applicability = "machine-applicable"
-    )]
-    Existing {
-        #[primary_span]
-        span: Span,
-        new_lifetime: Symbol,
-        pre: &'static str,
-        post: &'static str,
-    },
-}
-
-pub struct AddPreciseCapturingAndParams {
-    pub suggs: Vec<(Span, String)>,
-    pub new_lifetime: Symbol,
-    pub apit_spans: Vec<Span>,
-}
-
-impl Subdiagnostic for AddPreciseCapturingAndParams {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        diag.arg("new_lifetime", self.new_lifetime);
-        diag.multipart_suggestion_verbose(
-            fluent::infer_precise_capturing_new_but_apit,
-            self.suggs,
-            Applicability::MaybeIncorrect,
-        );
-        diag.span_note(self.apit_spans, fluent::infer_warn_removing_apit_params);
-    }
-}
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
deleted file mode 100644
index d71b7f3c264..00000000000
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ /dev/null
@@ -1,183 +0,0 @@
-use crate::error_reporting::infer::nice_region_error::find_anon_type;
-use crate::fluent_generated as fluent;
-use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
-use rustc_hir::def_id::LocalDefId;
-use rustc_middle::bug;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::{symbol::kw, Span};
-
-struct DescriptionCtx<'a> {
-    span: Option<Span>,
-    kind: &'a str,
-    arg: String,
-}
-
-impl<'a> DescriptionCtx<'a> {
-    fn new<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        generic_param_scope: LocalDefId,
-        region: ty::Region<'tcx>,
-        alt_span: Option<Span>,
-    ) -> Option<Self> {
-        let (span, kind, arg) = match *region {
-            ty::ReEarlyParam(br) => {
-                let scope = tcx
-                    .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
-                    .expect_local();
-                let span = if let Some(param) =
-                    tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
-                {
-                    param.span
-                } else {
-                    tcx.def_span(scope)
-                };
-                if br.has_name() {
-                    (Some(span), "as_defined", br.name.to_string())
-                } else {
-                    (Some(span), "as_defined_anon", String::new())
-                }
-            }
-            ty::ReLateParam(ref fr) => {
-                if !fr.bound_region.is_named()
-                    && let Some((ty, _)) =
-                        find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
-                {
-                    (Some(ty.span), "defined_here", String::new())
-                } else {
-                    let scope = fr.scope.expect_local();
-                    match fr.bound_region {
-                        ty::BoundRegionKind::BrNamed(_, name) => {
-                            let span = if let Some(param) = tcx
-                                .hir()
-                                .get_generics(scope)
-                                .and_then(|generics| generics.get_named(name))
-                            {
-                                param.span
-                            } else {
-                                tcx.def_span(scope)
-                            };
-                            if name == kw::UnderscoreLifetime {
-                                (Some(span), "as_defined_anon", String::new())
-                            } else {
-                                (Some(span), "as_defined", name.to_string())
-                            }
-                        }
-                        ty::BrAnon => {
-                            let span = Some(tcx.def_span(scope));
-                            (span, "defined_here", String::new())
-                        }
-                        _ => (Some(tcx.def_span(scope)), "defined_here_reg", region.to_string()),
-                    }
-                }
-            }
-
-            ty::ReStatic => (alt_span, "restatic", String::new()),
-
-            ty::RePlaceholder(_) | ty::ReError(_) => return None,
-
-            ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
-                bug!("unexpected region for DescriptionCtx: {:?}", region);
-            }
-        };
-        Some(DescriptionCtx { span, kind, arg })
-    }
-}
-
-pub enum PrefixKind {
-    Empty,
-    RefValidFor,
-    ContentValidFor,
-    TypeObjValidFor,
-    SourcePointerValidFor,
-    TypeSatisfy,
-    TypeOutlive,
-    LfParamInstantiatedWith,
-    LfParamMustOutlive,
-    LfInstantiatedWith,
-    LfMustOutlive,
-    PointerValidFor,
-    DataValidFor,
-}
-
-pub enum SuffixKind {
-    Empty,
-    Continues,
-    ReqByBinding,
-}
-
-impl IntoDiagArg for PrefixKind {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        let kind = match self {
-            Self::Empty => "empty",
-            Self::RefValidFor => "ref_valid_for",
-            Self::ContentValidFor => "content_valid_for",
-            Self::TypeObjValidFor => "type_obj_valid_for",
-            Self::SourcePointerValidFor => "source_pointer_valid_for",
-            Self::TypeSatisfy => "type_satisfy",
-            Self::TypeOutlive => "type_outlive",
-            Self::LfParamInstantiatedWith => "lf_param_instantiated_with",
-            Self::LfParamMustOutlive => "lf_param_must_outlive",
-            Self::LfInstantiatedWith => "lf_instantiated_with",
-            Self::LfMustOutlive => "lf_must_outlive",
-            Self::PointerValidFor => "pointer_valid_for",
-            Self::DataValidFor => "data_valid_for",
-        }
-        .into();
-        rustc_errors::DiagArgValue::Str(kind)
-    }
-}
-
-impl IntoDiagArg for SuffixKind {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        let kind = match self {
-            Self::Empty => "empty",
-            Self::Continues => "continues",
-            Self::ReqByBinding => "req_by_binding",
-        }
-        .into();
-        rustc_errors::DiagArgValue::Str(kind)
-    }
-}
-
-pub struct RegionExplanation<'a> {
-    desc: DescriptionCtx<'a>,
-    prefix: PrefixKind,
-    suffix: SuffixKind,
-}
-
-impl RegionExplanation<'_> {
-    pub fn new<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        generic_param_scope: LocalDefId,
-        region: ty::Region<'tcx>,
-        alt_span: Option<Span>,
-        prefix: PrefixKind,
-        suffix: SuffixKind,
-    ) -> Option<Self> {
-        Some(Self {
-            desc: DescriptionCtx::new(tcx, generic_param_scope, region, alt_span)?,
-            prefix,
-            suffix,
-        })
-    }
-}
-
-impl Subdiagnostic for RegionExplanation<'_> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        diag.arg("pref_kind", self.prefix);
-        diag.arg("suff_kind", self.suffix);
-        diag.arg("desc_kind", self.desc.kind);
-        diag.arg("desc_arg", self.desc.arg);
-
-        let msg = f(diag, fluent::infer_region_explanation.into());
-        if let Some(span) = self.desc.span {
-            diag.span_note(span, msg);
-        } else {
-            diag.note(msg);
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c9073d8c23e..7fc4e36d752 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -11,7 +11,6 @@ pub use BoundRegionConversionTime::*;
 pub use RegionVariableOrigin::*;
 pub use SubregionOrigin::*;
 
-use crate::error_reporting::infer::TypeErrCtxt;
 use crate::infer::relate::RelateResult;
 use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
 use free_regions::RegionRelations;
@@ -24,7 +23,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::Rollback;
 use rustc_data_structures::unify as ut;
-use rustc_errors::{Diag, ErrorGuaranteed};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::extension;
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
@@ -65,8 +65,6 @@ pub mod relate;
 pub mod resolve;
 pub(crate) mod snapshot;
 pub mod type_variable;
-// FIXME(error_reporting): Where should we put this?
-pub mod need_type_info;
 
 #[must_use]
 #[derive(Debug)]
@@ -698,36 +696,24 @@ impl<'tcx> InferCtxt<'tcx> {
         self.next_trait_solver
     }
 
-    /// Creates a `TypeErrCtxt` for emitting various inference errors.
-    /// During typeck, use `FnCtxt::err_ctxt` instead.
-    pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
-        TypeErrCtxt {
-            infcx: self,
-            sub_relations: Default::default(),
-            typeck_results: None,
-            fallback_has_occurred: false,
-            normalize_fn_sig: Box::new(|fn_sig| fn_sig),
-            autoderef_steps: Box::new(|ty| {
-                debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
-                vec![(ty, vec![])]
-            }),
-        }
-    }
-
     pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
 
-    /// Returns the origin of the type variable identified by `vid`, or `None`
-    /// if this is not a type variable.
+    /// Returns the origin of the type variable identified by `vid`.
     ///
-    /// No attempt is made to resolve `ty`.
-    pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
-        match *ty.kind() {
-            ty::Infer(ty::TyVar(vid)) => {
-                Some(self.inner.borrow_mut().type_variables().var_origin(vid))
-            }
-            _ => None,
+    /// No attempt is made to resolve `vid` to its root variable.
+    pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
+        self.inner.borrow_mut().type_variables().var_origin(vid)
+    }
+
+    /// Returns the origin of the const variable identified by `vid`
+    // FIXME: We should store origins separately from the unification table
+    // so this doesn't need to be optional.
+    pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin> {
+        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
+            ConstVariableValue::Known { .. } => None,
+            ConstVariableValue::Unknown { origin, .. } => Some(origin),
         }
     }
 
@@ -1589,60 +1575,6 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    // [Note-Type-error-reporting]
-    // An invariant is that anytime the expected or actual type is Error (the special
-    // error type, meaning that an error occurred when typechecking this expression),
-    // this is a derived error. The error cascaded from another error (that was already
-    // reported), so it's not useful to display it to the user.
-    // The following methods implement this logic.
-    // They check if either the actual or expected type is Error, and don't print the error
-    // in this case. The typechecker should only ever report type errors involving mismatched
-    // types using one of these methods, and should not call span_err directly for such
-    // errors.
-    pub fn type_error_struct_with_diag<M>(
-        &self,
-        sp: Span,
-        mk_diag: M,
-        actual_ty: Ty<'tcx>,
-    ) -> Diag<'a>
-    where
-        M: FnOnce(String) -> Diag<'a>,
-    {
-        let actual_ty = self.resolve_vars_if_possible(actual_ty);
-        debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
-
-        let mut err = mk_diag(self.ty_to_string(actual_ty));
-
-        // Don't report an error if actual type is `Error`.
-        if actual_ty.references_error() {
-            err.downgrade_to_delayed_bug();
-        }
-
-        err
-    }
-
-    pub fn report_mismatched_types(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        expected: Ty<'tcx>,
-        actual: Ty<'tcx>,
-        err: TypeError<'tcx>,
-    ) -> Diag<'a> {
-        self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
-    }
-
-    pub fn report_mismatched_consts(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        expected: ty::Const<'tcx>,
-        actual: ty::Const<'tcx>,
-        err: TypeError<'tcx>,
-    ) -> Diag<'a> {
-        self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
-    }
-}
-
 /// Helper for [InferCtxt::ty_or_const_infer_var_changed] (see comment on that), currently
 /// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
 #[derive(Copy, Clone, Debug)]
@@ -1888,3 +1820,32 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 
     args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
+
+impl<'tcx> InferCtxt<'tcx> {
+    /// Given a [`hir::Block`], get the span of its last expression or
+    /// statement, peeling off any inner blocks.
+    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
+        let block = block.innermost_block();
+        if let Some(expr) = &block.expr {
+            expr.span
+        } else if let Some(stmt) = block.stmts.last() {
+            // possibly incorrect trailing `;` in the else arm
+            stmt.span
+        } else {
+            // empty block; point at its entirety
+            block.span
+        }
+    }
+
+    /// Given a [`hir::HirId`] for a block, get the span of its last expression
+    /// or statement, peeling off any inner blocks.
+    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
+        match self.tcx.hir_node(hir_id) {
+            hir::Node::Block(blk) => self.find_block_span(blk),
+            // The parser was in a weird state if either of these happen, but
+            // it's better not to panic.
+            hir::Node::Expr(e) => e.span,
+            _ => rustc_span::DUMMY_SP,
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/need_type_info.rs b/compiler/rustc_infer/src/infer/need_type_info.rs
deleted file mode 100644
index 4f3dcd9043f..00000000000
--- a/compiler/rustc_infer/src/infer/need_type_info.rs
+++ /dev/null
@@ -1,1298 +0,0 @@
-use crate::error_reporting::infer::TypeErrCtxt;
-use crate::errors::{
-    AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
-    SourceKindMultiSuggestion, SourceKindSubdiag,
-};
-use crate::infer::InferCtxt;
-use rustc_errors::{codes::*, Diag, IntoDiagArg};
-use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::def::{CtorOf, DefKind, Namespace};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
-use rustc_middle::bug;
-use rustc_middle::hir::nested_filter;
-use rustc_middle::infer::unify_key::ConstVariableValue;
-use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
-use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::{
-    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
-    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
-};
-use rustc_span::symbol::{sym, Ident};
-use rustc_span::{BytePos, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::iter;
-use std::path::PathBuf;
-
-pub enum TypeAnnotationNeeded {
-    /// ```compile_fail,E0282
-    /// let x;
-    /// ```
-    E0282,
-    /// An implementation cannot be chosen unambiguously because of lack of information.
-    /// ```compile_fail,E0790
-    /// let _ = Default::default();
-    /// ```
-    E0283,
-    /// ```compile_fail,E0284
-    /// let mut d: u64 = 2;
-    /// d = d % 1u32.into();
-    /// ```
-    E0284,
-}
-
-impl Into<ErrCode> for TypeAnnotationNeeded {
-    fn into(self) -> ErrCode {
-        match self {
-            Self::E0282 => E0282,
-            Self::E0283 => E0283,
-            Self::E0284 => E0284,
-        }
-    }
-}
-
-/// Information about a constant or a type containing inference variables.
-pub struct InferenceDiagnosticsData {
-    pub name: String,
-    pub span: Option<Span>,
-    pub kind: UnderspecifiedArgKind,
-    pub parent: Option<InferenceDiagnosticsParentData>,
-}
-
-/// Data on the parent definition where a generic argument was declared.
-pub struct InferenceDiagnosticsParentData {
-    prefix: &'static str,
-    name: String,
-}
-
-#[derive(Clone)]
-pub enum UnderspecifiedArgKind {
-    Type { prefix: Cow<'static, str> },
-    Const { is_parameter: bool },
-}
-
-impl InferenceDiagnosticsData {
-    fn can_add_more_info(&self) -> bool {
-        !(self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }))
-    }
-
-    fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
-        if in_type.is_ty_or_numeric_infer() {
-            ""
-        } else if self.name == "_" {
-            // FIXME: Consider specializing this message if there is a single `_`
-            // in the type.
-            "underscore"
-        } else {
-            "has_name"
-        }
-    }
-
-    /// Generate a label for a generic argument which can't be inferred. When not
-    /// much is known about the argument, `use_diag` may be used to describe the
-    /// labeled value.
-    fn make_bad_error(&self, span: Span) -> InferenceBadError<'_> {
-        let has_parent = self.parent.is_some();
-        let bad_kind = if self.can_add_more_info() { "more_info" } else { "other" };
-        let (parent_prefix, parent_name) = self
-            .parent
-            .as_ref()
-            .map(|parent| (parent.prefix, parent.name.clone()))
-            .unwrap_or_default();
-        InferenceBadError {
-            span,
-            bad_kind,
-            prefix_kind: self.kind.clone(),
-            prefix: self.kind.try_get_prefix().unwrap_or_default(),
-            name: self.name.clone(),
-            has_parent,
-            parent_prefix,
-            parent_name,
-        }
-    }
-}
-
-impl InferenceDiagnosticsParentData {
-    fn for_parent_def_id(
-        tcx: TyCtxt<'_>,
-        parent_def_id: DefId,
-    ) -> Option<InferenceDiagnosticsParentData> {
-        let parent_name =
-            tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
-
-        Some(InferenceDiagnosticsParentData {
-            prefix: tcx.def_descr(parent_def_id),
-            name: parent_name,
-        })
-    }
-
-    fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
-        Self::for_parent_def_id(tcx, tcx.parent(def_id))
-    }
-}
-
-impl IntoDiagArg for UnderspecifiedArgKind {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        let kind = match self {
-            Self::Type { .. } => "type",
-            Self::Const { is_parameter: true } => "const_with_param",
-            Self::Const { is_parameter: false } => "const",
-        };
-        rustc_errors::DiagArgValue::Str(kind.into())
-    }
-}
-
-impl UnderspecifiedArgKind {
-    fn try_get_prefix(&self) -> Option<&str> {
-        match self {
-            Self::Type { prefix } => Some(prefix.as_ref()),
-            Self::Const { .. } => None,
-        }
-    }
-}
-
-struct ClosureEraser<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        match ty.kind() {
-            ty::Closure(_, args) => {
-                let closure_sig = args.as_closure().sig();
-                Ty::new_fn_ptr(
-                    self.tcx,
-                    self.tcx.signature_unclosure(closure_sig, hir::Safety::Safe),
-                )
-            }
-            _ => ty.super_fold_with(self),
-        }
-    }
-}
-
-fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
-    let mut printer = FmtPrinter::new(infcx.tcx, ns);
-    let ty_getter = move |ty_vid| {
-        if infcx.probe_ty_var(ty_vid).is_ok() {
-            warn!("resolved ty var in error message");
-        }
-
-        let mut infcx_inner = infcx.inner.borrow_mut();
-        let ty_vars = infcx_inner.type_variables();
-        let var_origin = ty_vars.var_origin(ty_vid);
-        if let Some(def_id) = var_origin.param_def_id
-            // The `Self` param of a trait has the def-id of the trait,
-            // since it's a synthetic parameter.
-            && infcx.tcx.def_kind(def_id) == DefKind::TyParam
-            && let name = infcx.tcx.item_name(def_id)
-            && !var_origin.span.from_expansion()
-        {
-            let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
-            let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
-            let generic_param_def = generics.param_at(idx as usize, infcx.tcx);
-            if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind {
-                None
-            } else {
-                Some(name)
-            }
-        } else {
-            None
-        }
-    };
-    printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
-    let const_getter = move |ct_vid| match infcx
-        .inner
-        .borrow_mut()
-        .const_unification_table()
-        .probe_value(ct_vid)
-    {
-        ConstVariableValue::Known { value: _ } => {
-            warn!("resolved const var in error message");
-            None
-        }
-        ConstVariableValue::Unknown { origin, universe: _ } => {
-            if let Some(def_id) = origin.param_def_id {
-                Some(infcx.tcx.item_name(def_id))
-            } else {
-                None
-            }
-        }
-    };
-    printer.const_infer_name_resolver = Some(Box::new(const_getter));
-    printer
-}
-
-fn ty_to_string<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    called_method_def_id: Option<DefId>,
-) -> String {
-    let mut printer = fmt_printer(infcx, Namespace::TypeNS);
-    let ty = infcx.resolve_vars_if_possible(ty);
-    // We use `fn` ptr syntax for closures, but this only works when the closure
-    // does not capture anything.
-    let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx });
-
-    match (ty.kind(), called_method_def_id) {
-        // We don't want the regular output for `fn`s because it includes its path in
-        // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        (ty::FnDef(..), _) => {
-            ty.fn_sig(infcx.tcx).print(&mut printer).unwrap();
-            printer.into_buffer()
-        }
-        (_, Some(def_id))
-            if ty.is_ty_or_numeric_infer()
-                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
-        {
-            "Vec<_>".to_string()
-        }
-        _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
-        _ => {
-            ty.print(&mut printer).unwrap();
-            printer.into_buffer()
-        }
-    }
-}
-
-/// We don't want to directly use `ty_to_string` for closures as their type isn't really
-/// something users are familiar with. Directly printing the `fn_sig` of closures also
-/// doesn't work as they actually use the "rust-call" API.
-fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
-    let ty::Closure(_, args) = ty.kind() else {
-        bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
-    };
-    let fn_sig = args.as_closure().sig();
-    let args = fn_sig
-        .inputs()
-        .skip_binder()
-        .iter()
-        .next()
-        .map(|args| {
-            args.tuple_fields()
-                .iter()
-                .map(|arg| ty_to_string(infcx, arg, None))
-                .collect::<Vec<_>>()
-                .join(", ")
-        })
-        .unwrap_or_default();
-    let ret = if fn_sig.output().skip_binder().is_unit() {
-        String::new()
-    } else {
-        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
-    };
-    format!("fn({args}){ret}")
-}
-
-impl<'tcx> InferCtxt<'tcx> {
-    /// Extracts data used by diagnostic for either types or constants
-    /// which were stuck during inference.
-    pub fn extract_inference_diagnostics_data(
-        &self,
-        arg: GenericArg<'tcx>,
-        highlight: Option<ty::print::RegionHighlightMode<'tcx>>,
-    ) -> InferenceDiagnosticsData {
-        match arg.unpack() {
-            GenericArgKind::Type(ty) => {
-                if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
-                    let mut inner = self.inner.borrow_mut();
-                    let ty_vars = &inner.type_variables();
-                    let var_origin = ty_vars.var_origin(ty_vid);
-                    if let Some(def_id) = var_origin.param_def_id
-                        // The `Self` param of a trait has the def-id of the trait,
-                        // since it's a synthetic parameter.
-                        && self.tcx.def_kind(def_id) == DefKind::TyParam
-                        && !var_origin.span.from_expansion()
-                    {
-                        return InferenceDiagnosticsData {
-                            name: self.tcx.item_name(def_id).to_string(),
-                            span: Some(var_origin.span),
-                            kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
-                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
-                        };
-                    }
-                }
-
-                let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
-                if let Some(highlight) = highlight {
-                    printer.region_highlight_mode = highlight;
-                }
-                ty.print(&mut printer).unwrap();
-                InferenceDiagnosticsData {
-                    name: printer.into_buffer(),
-                    span: None,
-                    kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
-                    parent: None,
-                }
-            }
-            GenericArgKind::Const(ct) => {
-                if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
-                    let origin =
-                        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
-                            ConstVariableValue::Known { value } => {
-                                bug!("resolved infer var: {vid:?} {value}")
-                            }
-                            ConstVariableValue::Unknown { origin, universe: _ } => origin,
-                        };
-                    if let Some(def_id) = origin.param_def_id {
-                        return InferenceDiagnosticsData {
-                            name: self.tcx.item_name(def_id).to_string(),
-                            span: Some(origin.span),
-                            kind: UnderspecifiedArgKind::Const { is_parameter: true },
-                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
-                        };
-                    }
-
-                    debug_assert!(!origin.span.is_dummy());
-                    let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS);
-                    if let Some(highlight) = highlight {
-                        printer.region_highlight_mode = highlight;
-                    }
-                    ct.print(&mut printer).unwrap();
-                    InferenceDiagnosticsData {
-                        name: printer.into_buffer(),
-                        span: Some(origin.span),
-                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
-                        parent: None,
-                    }
-                } else {
-                    // If we end up here the `FindInferSourceVisitor`
-                    // won't work, as its expected argument isn't an inference variable.
-                    //
-                    // FIXME: Ideally we should look into the generic constant
-                    // to figure out which inference var is actually unresolved so that
-                    // this path is unreachable.
-                    let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS);
-                    if let Some(highlight) = highlight {
-                        printer.region_highlight_mode = highlight;
-                    }
-                    ct.print(&mut printer).unwrap();
-                    InferenceDiagnosticsData {
-                        name: printer.into_buffer(),
-                        span: None,
-                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
-                        parent: None,
-                    }
-                }
-            }
-            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-        }
-    }
-
-    /// Used as a fallback in [TypeErrCtxt::emit_inference_failure_err]
-    /// in case we weren't able to get a better error.
-    fn bad_inference_failure_err(
-        &self,
-        span: Span,
-        arg_data: InferenceDiagnosticsData,
-        error_code: TypeAnnotationNeeded,
-    ) -> Diag<'_> {
-        let source_kind = "other";
-        let source_name = "";
-        let failure_span = None;
-        let infer_subdiags = Vec::new();
-        let multi_suggestions = Vec::new();
-        let bad_label = Some(arg_data.make_bad_error(span));
-        match error_code {
-            TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
-                span,
-                source_kind,
-                source_name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label,
-                was_written: None,
-                path: Default::default(),
-            }),
-            TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
-                span,
-                source_kind,
-                source_name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label,
-                was_written: None,
-                path: Default::default(),
-            }),
-            TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
-                span,
-                source_kind,
-                source_name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label,
-                was_written: None,
-                path: Default::default(),
-            }),
-        }
-    }
-}
-
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    #[instrument(level = "debug", skip(self, error_code))]
-    pub fn emit_inference_failure_err(
-        &self,
-        body_def_id: LocalDefId,
-        failure_span: Span,
-        arg: GenericArg<'tcx>,
-        error_code: TypeAnnotationNeeded,
-        should_label_span: bool,
-    ) -> Diag<'a> {
-        let arg = self.resolve_vars_if_possible(arg);
-        let arg_data = self.extract_inference_diagnostics_data(arg, None);
-
-        let Some(typeck_results) = &self.typeck_results else {
-            // If we don't have any typeck results we're outside
-            // of a body, so we won't be able to get better info
-            // here.
-            return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
-        };
-
-        let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
-        if let Some(body) = self.tcx.hir().maybe_body_owned_by(
-            self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
-        ) {
-            let expr = body.value;
-            local_visitor.visit_expr(expr);
-        }
-
-        let Some(InferSource { span, kind }) = local_visitor.infer_source else {
-            return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
-        };
-
-        let (source_kind, name, path) = kind.ty_localized_msg(self);
-        let failure_span = if should_label_span && !failure_span.overlaps(span) {
-            Some(failure_span)
-        } else {
-            None
-        };
-
-        let mut infer_subdiags = Vec::new();
-        let mut multi_suggestions = Vec::new();
-        match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
-                infer_subdiags.push(SourceKindSubdiag::LetLike {
-                    span: insert_span,
-                    name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
-                    x_kind: arg_data.where_x_is_kind(ty),
-                    prefix_kind: arg_data.kind.clone(),
-                    prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
-                    arg_name: arg_data.name,
-                    kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty, def_id),
-                });
-            }
-            InferSourceKind::ClosureArg { insert_span, ty } => {
-                infer_subdiags.push(SourceKindSubdiag::LetLike {
-                    span: insert_span,
-                    name: String::new(),
-                    x_kind: arg_data.where_x_is_kind(ty),
-                    prefix_kind: arg_data.kind.clone(),
-                    prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
-                    arg_name: arg_data.name,
-                    kind: "closure",
-                    type_name: ty_to_string(self, ty, None),
-                });
-            }
-            InferSourceKind::GenericArg {
-                insert_span,
-                argument_index,
-                generics_def_id,
-                def_id: _,
-                generic_args,
-                have_turbofish,
-            } => {
-                let generics = self.tcx.generics_of(generics_def_id);
-                let is_type = matches!(arg.unpack(), GenericArgKind::Type(_));
-
-                let (parent_exists, parent_prefix, parent_name) =
-                    InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
-                        .map_or((false, String::new(), String::new()), |parent| {
-                            (true, parent.prefix.to_string(), parent.name)
-                        });
-
-                infer_subdiags.push(SourceKindSubdiag::GenericLabel {
-                    span,
-                    is_type,
-                    param_name: generics.own_params[argument_index].name.to_string(),
-                    parent_exists,
-                    parent_prefix,
-                    parent_name,
-                });
-
-                let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
-                    == Some(generics_def_id)
-                {
-                    "Vec<_>".to_string()
-                } else {
-                    let mut printer = fmt_printer(self, Namespace::TypeNS);
-                    printer
-                        .comma_sep(generic_args.iter().copied().map(|arg| {
-                            if arg.is_suggestable(self.tcx, true) {
-                                return arg;
-                            }
-
-                            match arg.unpack() {
-                                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-                                GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
-                                GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
-                            }
-                        }))
-                        .unwrap();
-                    printer.into_buffer()
-                };
-
-                if !have_turbofish {
-                    infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
-                        span: insert_span,
-                        arg_count: generic_args.len(),
-                        args,
-                    });
-                }
-            }
-            InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
-                let placeholder = Some(self.next_ty_var(DUMMY_SP));
-                if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
-                    let mut printer = fmt_printer(self, Namespace::ValueNS);
-                    printer.print_def_path(def_id, args).unwrap();
-                    let def_path = printer.into_buffer();
-
-                    // We only care about whether we have to add `&` or `&mut ` for now.
-                    // This is the case if the last adjustment is a borrow and the
-                    // first adjustment was not a builtin deref.
-                    let adjustment = match typeck_results.expr_adjustments(receiver) {
-                        [
-                            Adjustment { kind: Adjust::Deref(None), target: _ },
-                            ..,
-                            Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ },
-                        ] => "",
-                        [
-                            ..,
-                            Adjustment {
-                                kind: Adjust::Borrow(AutoBorrow::Ref(_, mut_)),
-                                target: _,
-                            },
-                        ] => hir::Mutability::from(*mut_).ref_prefix_str(),
-                        _ => "",
-                    };
-
-                    multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(
-                        receiver.span,
-                        def_path,
-                        adjustment,
-                        successor,
-                    ));
-                }
-            }
-            InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let placeholder = Some(self.next_ty_var(DUMMY_SP));
-                if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
-                    let ty_info = ty_to_string(self, ty, None);
-                    multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
-                        ty_info,
-                        data,
-                        should_wrap_expr,
-                    ));
-                }
-            }
-        }
-        match error_code {
-            TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
-                span,
-                source_kind,
-                source_name: &name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
-                path: path.unwrap_or_default(),
-            }),
-            TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
-                span,
-                source_kind,
-                source_name: &name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
-                path: path.unwrap_or_default(),
-            }),
-            TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
-                span,
-                source_kind,
-                source_name: &name,
-                failure_span,
-                infer_subdiags,
-                multi_suggestions,
-                bad_label: None,
-                was_written: path.as_ref().map(|_| ()),
-                path: path.unwrap_or_default(),
-            }),
-        }
-    }
-}
-
-#[derive(Debug)]
-struct InferSource<'tcx> {
-    span: Span,
-    kind: InferSourceKind<'tcx>,
-}
-
-#[derive(Debug)]
-enum InferSourceKind<'tcx> {
-    LetBinding {
-        insert_span: Span,
-        pattern_name: Option<Ident>,
-        ty: Ty<'tcx>,
-        def_id: Option<DefId>,
-    },
-    ClosureArg {
-        insert_span: Span,
-        ty: Ty<'tcx>,
-    },
-    GenericArg {
-        insert_span: Span,
-        argument_index: usize,
-        generics_def_id: DefId,
-        def_id: DefId,
-        generic_args: &'tcx [GenericArg<'tcx>],
-        have_turbofish: bool,
-    },
-    FullyQualifiedMethodCall {
-        receiver: &'tcx Expr<'tcx>,
-        /// If the method has other arguments, this is ", " and the start of the first argument,
-        /// while for methods without arguments this is ")" and the end of the method call.
-        successor: (&'static str, BytePos),
-        args: GenericArgsRef<'tcx>,
-        def_id: DefId,
-    },
-    ClosureReturn {
-        ty: Ty<'tcx>,
-        data: &'tcx FnRetTy<'tcx>,
-        should_wrap_expr: Option<Span>,
-    },
-}
-
-impl<'tcx> InferSource<'tcx> {
-    fn from_expansion(&self) -> bool {
-        let source_from_expansion = match self.kind {
-            InferSourceKind::LetBinding { insert_span, .. }
-            | InferSourceKind::ClosureArg { insert_span, .. }
-            | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
-            InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
-                receiver.span.from_expansion()
-            }
-            InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
-                data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
-            }
-        };
-        source_from_expansion || self.span.from_expansion()
-    }
-}
-
-impl<'tcx> InferSourceKind<'tcx> {
-    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
-        let mut path = None;
-        match *self {
-            InferSourceKind::LetBinding { ty, .. }
-            | InferSourceKind::ClosureArg { ty, .. }
-            | InferSourceKind::ClosureReturn { ty, .. } => {
-                if ty.is_closure() {
-                    ("closure", closure_as_fn_str(infcx, ty), path)
-                } else if !ty.is_ty_or_numeric_infer() {
-                    ("normal", infcx.tcx.short_ty_string(ty, &mut path), path)
-                } else {
-                    ("other", String::new(), path)
-                }
-            }
-            // FIXME: We should be able to add some additional info here.
-            InferSourceKind::GenericArg { .. }
-            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path),
-        }
-    }
-}
-
-#[derive(Debug)]
-struct InsertableGenericArgs<'tcx> {
-    insert_span: Span,
-    args: GenericArgsRef<'tcx>,
-    generics_def_id: DefId,
-    def_id: DefId,
-    have_turbofish: bool,
-}
-
-/// A visitor which searches for the "best" spot to use in the inference error.
-///
-/// For this it walks over the hir body and tries to check all places where
-/// inference variables could be bound.
-///
-/// While doing so, the currently best spot is stored in `infer_source`.
-/// For details on how we rank spots, see [Self::source_cost]
-struct FindInferSourceVisitor<'a, 'tcx> {
-    tecx: &'a TypeErrCtxt<'a, 'tcx>,
-    typeck_results: &'a TypeckResults<'tcx>,
-
-    target: GenericArg<'tcx>,
-
-    attempt: usize,
-    infer_source_cost: usize,
-    infer_source: Option<InferSource<'tcx>>,
-}
-
-impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
-    fn new(
-        tecx: &'a TypeErrCtxt<'a, 'tcx>,
-        typeck_results: &'a TypeckResults<'tcx>,
-        target: GenericArg<'tcx>,
-    ) -> Self {
-        FindInferSourceVisitor {
-            tecx,
-            typeck_results,
-
-            target,
-
-            attempt: 0,
-            infer_source_cost: usize::MAX,
-            infer_source: None,
-        }
-    }
-
-    /// Computes cost for the given source.
-    ///
-    /// Sources with a small cost are prefer and should result
-    /// in a clearer and idiomatic suggestion.
-    fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
-        #[derive(Clone, Copy)]
-        struct CostCtxt<'tcx> {
-            tcx: TyCtxt<'tcx>,
-        }
-        impl<'tcx> CostCtxt<'tcx> {
-            fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
-                match arg.unpack() {
-                    GenericArgKind::Lifetime(_) => 0, // erased
-                    GenericArgKind::Type(ty) => self.ty_cost(ty),
-                    GenericArgKind::Const(_) => 3, // some non-zero value
-                }
-            }
-            fn ty_cost(self, ty: Ty<'tcx>) -> usize {
-                match *ty.kind() {
-                    ty::Closure(..) => 1000,
-                    ty::FnDef(..) => 150,
-                    ty::FnPtr(..) => 30,
-                    ty::Adt(def, args) => {
-                        5 + self
-                            .tcx
-                            .generics_of(def.did())
-                            .own_args_no_defaults(self.tcx, args)
-                            .iter()
-                            .map(|&arg| self.arg_cost(arg))
-                            .sum::<usize>()
-                    }
-                    ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
-                    ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
-                    ty::Infer(..) => 0,
-                    _ => 1,
-                }
-            }
-        }
-
-        // The sources are listed in order of preference here.
-        let tcx = self.tecx.tcx;
-        let ctx = CostCtxt { tcx };
-        match source.kind {
-            InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
-            InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
-            InferSourceKind::GenericArg { def_id, generic_args, .. } => {
-                let variant_cost = match tcx.def_kind(def_id) {
-                    // `None::<u32>` and friends are ugly.
-                    DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
-                    _ => 10,
-                };
-                variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
-            }
-            InferSourceKind::FullyQualifiedMethodCall { args, .. } => {
-                20 + args.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
-            }
-            InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
-                30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
-            }
-        }
-    }
-
-    /// Uses `fn source_cost` to determine whether this inference source is preferable to
-    /// previous sources. We generally prefer earlier sources.
-    #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
-        if new_source.from_expansion() {
-            return;
-        }
-
-        let cost = self.source_cost(&new_source) + self.attempt;
-        debug!(?cost);
-        self.attempt += 1;
-        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) =
-            self.infer_source
-            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, .. } = new_source.kind
-            && ty.is_ty_or_numeric_infer()
-        {
-            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
-            // `let x: _ = iter.collect();`, as this is a very common case.
-            *def_id = Some(did);
-        }
-
-        if cost < self.infer_source_cost {
-            self.infer_source_cost = cost;
-            self.infer_source = Some(new_source);
-        }
-    }
-
-    fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
-        let args = self.typeck_results.node_args_opt(hir_id);
-        self.tecx.resolve_vars_if_possible(args)
-    }
-
-    fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
-        let ty = self.typeck_results.node_type_opt(hir_id);
-        self.tecx.resolve_vars_if_possible(ty)
-    }
-
-    // Check whether this generic argument is the inference variable we
-    // are looking for.
-    fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
-        if arg == self.target {
-            return true;
-        }
-
-        match (arg.unpack(), self.target.unpack()) {
-            (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
-                use ty::{Infer, TyVar};
-                match (inner_ty.kind(), target_ty.kind()) {
-                    (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
-                        self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid)
-                    }
-                    _ => false,
-                }
-            }
-            (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => {
-                use ty::InferConst::*;
-                match (inner_ct.kind(), target_ct.kind()) {
-                    (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => {
-                        self.tecx.inner.borrow_mut().const_unification_table().unioned(a_vid, b_vid)
-                    }
-                    _ => false,
-                }
-            }
-            _ => false,
-        }
-    }
-
-    /// Does this generic argument contain our target inference variable
-    /// in a way which can be written by the user.
-    fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
-        let mut walker = arg.walk();
-        while let Some(inner) = walker.next() {
-            if self.generic_arg_is_target(inner) {
-                return true;
-            }
-            match inner.unpack() {
-                GenericArgKind::Lifetime(_) => {}
-                GenericArgKind::Type(ty) => {
-                    if matches!(
-                        ty.kind(),
-                        ty::Alias(ty::Opaque, ..)
-                            | ty::Closure(..)
-                            | ty::CoroutineClosure(..)
-                            | ty::Coroutine(..)
-                    ) {
-                        // Opaque types can't be named by the user right now.
-                        //
-                        // Both the generic arguments of closures and coroutines can
-                        // also not be named. We may want to only look into the closure
-                        // signature in case it has no captures, as that can be represented
-                        // using `fn(T) -> R`.
-
-                        // FIXME(type_alias_impl_trait): These opaque types
-                        // can actually be named, so it would make sense to
-                        // adjust this case and add a test for it.
-                        walker.skip_current_subtree();
-                    }
-                }
-                GenericArgKind::Const(ct) => {
-                    if matches!(ct.kind(), ty::ConstKind::Unevaluated(..)) {
-                        // You can't write the generic arguments for
-                        // unevaluated constants.
-                        walker.skip_current_subtree();
-                    }
-                }
-            }
-        }
-        false
-    }
-
-    fn expr_inferred_arg_iter(
-        &self,
-        expr: &'tcx hir::Expr<'tcx>,
-    ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
-        let tcx = self.tecx.tcx;
-        match expr.kind {
-            hir::ExprKind::Path(ref path) => {
-                if let Some(args) = self.node_args_opt(expr.hir_id) {
-                    return self.path_inferred_arg_iter(expr.hir_id, args, path);
-                }
-            }
-            // FIXME(#98711): Ideally we would also deal with type relative
-            // paths here, even if that is quite rare.
-            //
-            // See the `need_type_info/expr-struct-type-relative-gat.rs` test
-            // for an example where that would be needed.
-            //
-            // However, the `type_dependent_def_id` for `Self::Output` in an
-            // impl is currently the `DefId` of `Output` in the trait definition
-            // which makes this somewhat difficult and prevents us from just
-            // using `self.path_inferred_arg_iter` here.
-            hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
-            // FIXME(TaKO8Ki): Ideally we should support this. For that
-            // we have to map back from the self type to the
-            // type alias though. That's difficult.
-            //
-            // See the `need_type_info/issue-103053.rs` test for
-            // a example.
-            if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
-                if let Some(ty) = self.opt_node_type(expr.hir_id)
-                    && let ty::Adt(_, args) = ty.kind()
-                {
-                    return Box::new(self.resolved_path_inferred_arg_iter(path, args));
-                }
-            }
-            hir::ExprKind::MethodCall(segment, ..) => {
-                if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
-                    let generics = tcx.generics_of(def_id);
-                    let insertable: Option<_> = try {
-                        if generics.has_impl_trait() {
-                            None?
-                        }
-                        let args = self.node_args_opt(expr.hir_id)?;
-                        let span = tcx.hir().span(segment.hir_id);
-                        let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
-                        InsertableGenericArgs {
-                            insert_span,
-                            args,
-                            generics_def_id: def_id,
-                            def_id,
-                            have_turbofish: false,
-                        }
-                    };
-                    return Box::new(insertable.into_iter());
-                }
-            }
-            _ => {}
-        }
-
-        Box::new(iter::empty())
-    }
-
-    fn resolved_path_inferred_arg_iter(
-        &self,
-        path: &'tcx hir::Path<'tcx>,
-        args: GenericArgsRef<'tcx>,
-    ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
-        let tcx = self.tecx.tcx;
-        let have_turbofish = path.segments.iter().any(|segment| {
-            segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
-        });
-        // The last segment of a path often has `Res::Err` and the
-        // correct `Res` is the one of the whole path.
-        //
-        // FIXME: We deal with that one separately for now,
-        // would be good to remove this special case.
-        let last_segment_using_path_data: Option<_> = try {
-            let generics_def_id = tcx.res_generics_def_id(path.res)?;
-            let generics = tcx.generics_of(generics_def_id);
-            if generics.has_impl_trait() {
-                do yeet ();
-            }
-            let insert_span =
-                path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
-            InsertableGenericArgs {
-                insert_span,
-                args,
-                generics_def_id,
-                def_id: path.res.def_id(),
-                have_turbofish,
-            }
-        };
-
-        path.segments
-            .iter()
-            .filter_map(move |segment| {
-                let res = segment.res;
-                let generics_def_id = tcx.res_generics_def_id(res)?;
-                let generics = tcx.generics_of(generics_def_id);
-                if generics.has_impl_trait() {
-                    return None;
-                }
-                let span = tcx.hir().span(segment.hir_id);
-                let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
-                Some(InsertableGenericArgs {
-                    insert_span,
-                    args,
-                    generics_def_id,
-                    def_id: res.def_id(),
-                    have_turbofish,
-                })
-            })
-            .chain(last_segment_using_path_data)
-    }
-
-    fn path_inferred_arg_iter(
-        &self,
-        hir_id: HirId,
-        args: GenericArgsRef<'tcx>,
-        qpath: &'tcx hir::QPath<'tcx>,
-    ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
-        let tcx = self.tecx.tcx;
-        match qpath {
-            hir::QPath::Resolved(_self_ty, path) => {
-                Box::new(self.resolved_path_inferred_arg_iter(path, args))
-            }
-            hir::QPath::TypeRelative(ty, segment) => {
-                let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else {
-                    return Box::new(iter::empty());
-                };
-
-                let generics = tcx.generics_of(def_id);
-                let segment: Option<_> = try {
-                    if !segment.infer_args || generics.has_impl_trait() {
-                        do yeet ();
-                    }
-                    let span = tcx.hir().span(segment.hir_id);
-                    let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
-                    InsertableGenericArgs {
-                        insert_span,
-                        args,
-                        generics_def_id: def_id,
-                        def_id,
-                        have_turbofish: false,
-                    }
-                };
-
-                let parent_def_id = generics.parent.unwrap();
-                if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
-                    let parent_ty = tcx.type_of(parent_def_id).instantiate(tcx, args);
-                    match (parent_ty.kind(), &ty.kind) {
-                        (
-                            ty::Adt(def, args),
-                            hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
-                        ) => {
-                            if tcx.res_generics_def_id(path.res) != Some(def.did()) {
-                                match path.res {
-                                    Res::Def(DefKind::TyAlias, _) => {
-                                        // FIXME: Ideally we should support this. For that
-                                        // we have to map back from the self type to the
-                                        // type alias though. That's difficult.
-                                        //
-                                        // See the `need_type_info/type-alias.rs` test for
-                                        // some examples.
-                                    }
-                                    // There cannot be inference variables in the self type,
-                                    // so there's nothing for us to do here.
-                                    Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
-                                    _ => warn!(
-                                        "unexpected path: def={:?} args={:?} path={:?}",
-                                        def, args, path,
-                                    ),
-                                }
-                            } else {
-                                return Box::new(
-                                    self.resolved_path_inferred_arg_iter(path, args).chain(segment),
-                                );
-                            }
-                        }
-                        _ => (),
-                    }
-                }
-
-                Box::new(segment.into_iter())
-            }
-            hir::QPath::LangItem(_, _) => Box::new(iter::empty()),
-        }
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tecx.tcx.hir()
-    }
-
-    fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
-        intravisit::walk_local(self, local);
-
-        if let Some(ty) = self.opt_node_type(local.hir_id) {
-            if self.generic_arg_contains_target(ty.into()) {
-                match local.source {
-                    LocalSource::Normal if local.ty.is_none() => {
-                        self.update_infer_source(InferSource {
-                            span: local.pat.span,
-                            kind: InferSourceKind::LetBinding {
-                                insert_span: local.pat.span.shrink_to_hi(),
-                                pattern_name: local.pat.simple_ident(),
-                                ty,
-                                def_id: None,
-                            },
-                        })
-                    }
-                    _ => {}
-                }
-            }
-        }
-    }
-
-    /// For closures, we first visit the parameters and then the content,
-    /// as we prefer those.
-    fn visit_body(&mut self, body: &Body<'tcx>) {
-        for param in body.params {
-            debug!(
-                "param: span {:?}, ty_span {:?}, pat.span {:?}",
-                param.span, param.ty_span, param.pat.span
-            );
-            if param.ty_span != param.pat.span {
-                debug!("skipping param: has explicit type");
-                continue;
-            }
-
-            let Some(param_ty) = self.opt_node_type(param.hir_id) else { continue };
-
-            if self.generic_arg_contains_target(param_ty.into()) {
-                self.update_infer_source(InferSource {
-                    span: param.pat.span,
-                    kind: InferSourceKind::ClosureArg {
-                        insert_span: param.pat.span.shrink_to_hi(),
-                        ty: param_ty,
-                    },
-                })
-            }
-        }
-        intravisit::walk_body(self, body);
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        let tcx = self.tecx.tcx;
-        match expr.kind {
-            // When encountering `func(arg)` first look into `arg` and then `func`,
-            // as `arg` is "more specific".
-            ExprKind::Call(func, args) => {
-                for arg in args {
-                    self.visit_expr(arg);
-                }
-                self.visit_expr(func);
-            }
-            _ => intravisit::walk_expr(self, expr),
-        }
-
-        for args in self.expr_inferred_arg_iter(expr) {
-            debug!(?args);
-            let InsertableGenericArgs {
-                insert_span,
-                args,
-                generics_def_id,
-                def_id,
-                have_turbofish,
-            } = args;
-            let generics = tcx.generics_of(generics_def_id);
-            if let Some(mut argument_index) = generics
-                .own_args(args)
-                .iter()
-                .position(|&arg| self.generic_arg_contains_target(arg))
-            {
-                if generics.parent.is_none() && generics.has_self {
-                    argument_index += 1;
-                }
-                let args = self.tecx.resolve_vars_if_possible(args);
-                let generic_args =
-                    &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
-                let span = match expr.kind {
-                    ExprKind::MethodCall(path, ..) => path.ident.span,
-                    _ => expr.span,
-                };
-
-                self.update_infer_source(InferSource {
-                    span,
-                    kind: InferSourceKind::GenericArg {
-                        insert_span,
-                        argument_index,
-                        generics_def_id,
-                        def_id,
-                        generic_args,
-                        have_turbofish,
-                    },
-                });
-            }
-        }
-
-        if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
-            if let (
-                &ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
-                ty::Closure(_, args),
-            ) = (&expr.kind, node_ty.kind())
-            {
-                let output = args.as_closure().sig().output().skip_binder();
-                if self.generic_arg_contains_target(output.into()) {
-                    let body = self.tecx.tcx.hir().body(body);
-                    let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
-                        None
-                    } else {
-                        Some(body.value.span.shrink_to_hi())
-                    };
-                    self.update_infer_source(InferSource {
-                        span: fn_decl_span,
-                        kind: InferSourceKind::ClosureReturn {
-                            ty: output,
-                            data: &fn_decl.output,
-                            should_wrap_expr,
-                        },
-                    })
-                }
-            }
-        }
-
-        let has_impl_trait = |def_id| {
-            iter::successors(Some(tcx.generics_of(def_id)), |generics| {
-                generics.parent.map(|def_id| tcx.generics_of(def_id))
-            })
-            .any(|generics| generics.has_impl_trait())
-        };
-        if let ExprKind::MethodCall(path, receiver, method_args, span) = expr.kind
-            && let Some(args) = self.node_args_opt(expr.hir_id)
-            && args.iter().any(|arg| self.generic_arg_contains_target(arg))
-            && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
-            && self.tecx.tcx.trait_of_item(def_id).is_some()
-            && !has_impl_trait(def_id)
-        {
-            let successor =
-                method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
-            let args = self.tecx.resolve_vars_if_possible(args);
-            self.update_infer_source(InferSource {
-                span: path.ident.span,
-                kind: InferSourceKind::FullyQualifiedMethodCall {
-                    receiver,
-                    successor,
-                    args,
-                    def_id,
-                },
-            })
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 02ebf933f53..b65ac859667 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -34,7 +34,6 @@
 #[macro_use]
 extern crate tracing;
 
-pub mod error_reporting;
 mod errors;
 pub mod infer;
 pub mod traits;
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
deleted file mode 100644
index 83df1fd6510..00000000000
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-use super::ObjectSafetyViolation;
-
-use crate::infer::InferCtxt;
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::Span;
-use std::fmt;
-use std::iter;
-
-impl<'tcx> InferCtxt<'tcx> {
-    pub fn report_extra_impl_obligation<'a>(
-        &'a self,
-        error_span: Span,
-        impl_item_def_id: LocalDefId,
-        trait_item_def_id: DefId,
-        requirement: &dyn fmt::Display,
-    ) -> Diag<'a> {
-        let mut err = struct_span_code_err!(
-            self.dcx(),
-            error_span,
-            E0276,
-            "impl has stricter requirements than trait"
-        );
-
-        if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
-            if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                err.span_label(span, format!("definition of `{item_name}` from trait"));
-            }
-        }
-
-        err.span_label(error_span, format!("impl has extra requirement {requirement}"));
-
-        err
-    }
-}
-
-pub fn report_object_safety_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    hir_id: Option<hir::HirId>,
-    trait_def_id: DefId,
-    violations: &[ObjectSafetyViolation],
-) -> Diag<'tcx> {
-    let trait_str = tcx.def_path_str(trait_def_id);
-    let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
-        hir::Node::Item(item) => Some(item.ident.span),
-        _ => None,
-    });
-    let mut err = struct_span_code_err!(
-        tcx.dcx(),
-        span,
-        E0038,
-        "the trait `{}` cannot be made into an object",
-        trait_str
-    );
-    err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
-
-    if let Some(hir_id) = hir_id
-        && let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
-        && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
-    {
-        let mut hir_id = hir_id;
-        while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
-            hir_id = ty.hir_id;
-        }
-        if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
-            // Do not suggest `impl Trait` when dealing with things like super-traits.
-            err.span_suggestion_verbose(
-                ty.span.until(trait_ref.span),
-                "consider using an opaque type instead",
-                "impl ",
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-    let mut reported_violations = FxIndexSet::default();
-    let mut multi_span = vec![];
-    let mut messages = vec![];
-    for violation in violations {
-        if let ObjectSafetyViolation::SizedSelf(sp) = &violation
-            && !sp.is_empty()
-        {
-            // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
-            // with a `Span`.
-            reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
-        }
-        if reported_violations.insert(violation.clone()) {
-            let spans = violation.spans();
-            let msg = if trait_span.is_none() || spans.is_empty() {
-                format!("the trait cannot be made into an object because {}", violation.error_msg())
-            } else {
-                format!("...because {}", violation.error_msg())
-            };
-            if spans.is_empty() {
-                err.note(msg);
-            } else {
-                for span in spans {
-                    multi_span.push(span);
-                    messages.push(msg.clone());
-                }
-            }
-        }
-    }
-    let has_multi_span = !multi_span.is_empty();
-    let mut note_span = MultiSpan::from_spans(multi_span.clone());
-    if let (Some(trait_span), true) = (trait_span, has_multi_span) {
-        note_span.push_span_label(trait_span, "this trait cannot be made into an object...");
-    }
-    for (span, msg) in iter::zip(multi_span, messages) {
-        note_span.push_span_label(span, msg);
-    }
-    err.span_note(
-        note_span,
-        "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>",
-    );
-
-    // Only provide the help if its a local trait, otherwise it's not actionable.
-    if trait_span.is_some() {
-        let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
-        reported_violations.sort();
-
-        let mut potential_solutions: Vec<_> =
-            reported_violations.into_iter().map(|violation| violation.solution()).collect();
-        potential_solutions.sort();
-        // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
-        potential_solutions.dedup();
-        for solution in potential_solutions {
-            solution.add_to(&mut err);
-        }
-    }
-
-    let impls_of = tcx.trait_impls_of(trait_def_id);
-    let impls = if impls_of.blanket_impls().is_empty() {
-        impls_of
-            .non_blanket_impls()
-            .values()
-            .flatten()
-            .filter(|def_id| {
-                !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
-            })
-            .collect::<Vec<_>>()
-    } else {
-        vec![]
-    };
-    let externally_visible = if !impls.is_empty()
-        && let Some(def_id) = trait_def_id.as_local()
-        // We may be executing this during typeck, which would result in cycle
-        // if we used effective_visibilities query, which looks into opaque types
-        // (and therefore calls typeck).
-        && tcx.resolutions(()).effective_visibilities.is_exported(def_id)
-    {
-        true
-    } else {
-        false
-    };
-    match &impls[..] {
-        [] => {}
-        _ if impls.len() > 9 => {}
-        [only] if externally_visible => {
-            err.help(with_no_trimmed_paths!(format!(
-                "only type `{}` is seen to implement the trait in this crate, consider using it \
-                 directly instead",
-                tcx.type_of(*only).instantiate_identity(),
-            )));
-        }
-        [only] => {
-            err.help(with_no_trimmed_paths!(format!(
-                "only type `{}` implements the trait, consider using it directly instead",
-                tcx.type_of(*only).instantiate_identity(),
-            )));
-        }
-        impls => {
-            let types = impls
-                .iter()
-                .map(|t| {
-                    with_no_trimmed_paths!(format!("  {}", tcx.type_of(*t).instantiate_identity(),))
-                })
-                .collect::<Vec<_>>();
-            err.help(format!(
-                "the following types implement the trait, consider defining an enum where each \
-                 variant holds one of these types, implementing `{}` for this new enum and using \
-                 it instead:\n{}",
-                trait_str,
-                types.join("\n"),
-            ));
-        }
-    }
-    if externally_visible {
-        err.note(format!(
-            "`{trait_str}` can be implemented in other crates; if you want to support your users \
-             passing their own types here, you can't refer to a specific type",
-        ));
-    }
-
-    err
-}
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 556b3bd063d..7bc3af374fc 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -3,7 +3,6 @@
 //! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
 
 mod engine;
-pub mod error_reporting;
 mod project;
 mod structural_impls;
 pub mod util;