about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs58
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs22
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs72
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs70
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs181
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs101
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs37
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs4
19 files changed, 404 insertions, 195 deletions
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 911cc0b88c4..fcf86da08f4 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -41,7 +41,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let ty = self.resolve_vars_if_possible(ty);
 
-        if !(param_env, ty).needs_infer() {
+        if !(param_env, ty).has_infer() {
             return ty.is_copy_modulo_regions(self.tcx, param_env);
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 1a566e87dc8..996dc329dcb 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -91,14 +91,15 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
 ) -> ty::Binder<'tcx, Ty<'tcx>> {
     debug_assert!(!ty.has_late_bound_regions());
     let mut counter = 0;
-    let ty = tcx.fold_regions(ty, |mut r, current_depth| {
-        if let ty::ReErased = r.kind() {
+    let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
+        ty::ReErased => {
             let br =
                 ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
             counter += 1;
-            r = tcx.mk_re_late_bound(current_depth, br);
+            tcx.mk_re_late_bound(current_depth, br)
         }
-        r
+        // All free regions should be erased here.
+        r => bug!("unexpected region: {r:?}"),
     });
     let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
         (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 976849696e3..ff4bff10cc8 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
         };
 
         let value = value.fold_with(&mut canonicalizer);
-        assert!(!value.needs_infer());
+        assert!(!value.has_infer());
         assert!(!value.has_placeholders());
 
         let (max_universe, variables) = canonicalizer.finalize();
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index bd52957d162..63a73f8d50d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -3,7 +3,8 @@ use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
-    DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
+    DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, RegionVariableOrigin,
+    TyCtxtInferExt,
 };
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
@@ -223,18 +224,20 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         {
             debug!("rerunning goal to check result is stable");
             let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
-            let canonical_response =
+            let new_canonical_response =
                 EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
-            if !canonical_response.value.var_values.is_identity() {
+            if !new_canonical_response.value.var_values.is_identity() {
                 bug!(
                     "unstable result: re-canonicalized goal={canonical_goal:#?} \
-                     response={canonical_response:#?}"
+                    first_response={canonical_response:#?} \
+                    second_response={new_canonical_response:#?}"
                 );
             }
-            if certainty != canonical_response.value.certainty {
+            if certainty != new_canonical_response.value.certainty {
                 bug!(
                     "unstable certainty: {certainty:#?} re-canonicalized goal={canonical_goal:#?} \
-                     response={canonical_response:#?}"
+                     first_response={canonical_response:#?} \
+                     second_response={new_canonical_response:#?}"
                 );
             }
         }
@@ -434,6 +437,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         })
     }
 
+    pub(super) fn next_region_infer(&self) -> ty::Region<'tcx> {
+        self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
+    }
+
     pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
         self.infcx.next_const_var(
             ty,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 226d29687e3..67ad7fb4bd2 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -16,7 +16,7 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
+use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData, MaybeCause};
 use rustc_middle::ty::{self, BoundVar, GenericArgKind};
 use rustc_span::DUMMY_SP;
 use std::iter;
@@ -60,9 +60,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
         let certainty = certainty.unify_with(goals_certainty);
 
-        let external_constraints = self.compute_external_query_constraints()?;
+        let response = match certainty {
+            Certainty::Yes | Certainty::Maybe(MaybeCause::Ambiguity) => {
+                let external_constraints = self.compute_external_query_constraints()?;
+                Response { var_values: self.var_values, external_constraints, certainty }
+            }
+            Certainty::Maybe(MaybeCause::Overflow) => {
+                // If we have overflow, it's probable that we're substituting a type
+                // into itself infinitely and any partial substitutions in the query
+                // response are probably not useful anyways, so just return an empty
+                // query response.
+                //
+                // This may prevent us from potentially useful inference, e.g.
+                // 2 candidates, one ambiguous and one overflow, which both
+                // have the same inference constraints.
+                //
+                // Changing this to retain some constraints in the future
+                // won't be a breaking change, so this is good enough for now.
+                return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
+            }
+        };
 
-        let response = Response { var_values: self.var_values, external_constraints, certainty };
         let canonical = Canonicalizer::canonicalize(
             self.infcx,
             CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
@@ -72,6 +90,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         Ok(canonical)
     }
 
+    /// Constructs a totally unconstrained, ambiguous response to a goal.
+    ///
+    /// Take care when using this, since often it's useful to respond with
+    /// ambiguity but return constrained variables to guide inference.
+    pub(in crate::solve) fn make_ambiguous_response_no_constraints(
+        &self,
+        maybe_cause: MaybeCause,
+    ) -> CanonicalResponse<'tcx> {
+        let unconstrained_response = Response {
+            var_values: CanonicalVarValues {
+                var_values: self.tcx().mk_substs_from_iter(self.var_values.var_values.iter().map(
+                    |arg| -> ty::GenericArg<'tcx> {
+                        match arg.unpack() {
+                            GenericArgKind::Lifetime(_) => self.next_region_infer().into(),
+                            GenericArgKind::Type(_) => self.next_ty_infer().into(),
+                            GenericArgKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
+                        }
+                    },
+                )),
+            },
+            external_constraints: self
+                .tcx()
+                .mk_external_constraints(ExternalConstraintsData::default()),
+            certainty: Certainty::Maybe(maybe_cause),
+        };
+
+        Canonicalizer::canonicalize(
+            self.infcx,
+            CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
+            &mut Default::default(),
+            unconstrained_response,
+        )
+    }
+
     #[instrument(level = "debug", skip(self), ret)]
     fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
         // Cannot use `take_registered_region_obligations` as we may compute the response
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 19bcbd46144..d94679fef28 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -340,17 +340,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         if responses.is_empty() {
             return Err(NoSolution);
         }
-        let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
-            certainty.unify_with(response.value.certainty)
-        });
-
-        let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
-        if let Ok(response) = response {
-            assert!(response.has_no_inference_or_external_constraints());
-            Ok(response)
-        } else {
-            bug!("failed to make floundered response: {responses:?}");
-        }
+
+        let Certainty::Maybe(maybe_cause) = responses.iter().fold(
+            Certainty::AMBIGUOUS,
+            |certainty, response| {
+                certainty.unify_with(response.value.certainty)
+            },
+        ) else {
+            bug!("expected flounder response to be ambiguous")
+        };
+
+        Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 8e7097ce4a7..c97473e6241 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -86,8 +86,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     ) -> QueryResult<'tcx> {
         if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
             && poly_trait_pred.def_id() == goal.predicate.def_id()
+            && poly_trait_pred.polarity() == goal.predicate.polarity
         {
-            // FIXME: Constness and polarity
+            // FIXME: Constness
             ecx.probe(|ecx| {
                 let assumption_trait_pred =
                     ecx.instantiate_binder_with_infer(poly_trait_pred);
@@ -111,6 +112,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     ) -> QueryResult<'tcx> {
         if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
             && poly_trait_pred.def_id() == goal.predicate.def_id()
+            && poly_trait_pred.polarity() == goal.predicate.polarity
         {
             // FIXME: Constness and polarity
             ecx.probe(|ecx| {
@@ -147,6 +149,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
             return result;
         }
@@ -161,6 +167,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         let tcx = ecx.tcx();
 
         ecx.probe(|ecx| {
@@ -176,6 +186,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         ecx.probe_and_evaluate_goal_for_constituent_tys(
             goal,
             structural_traits::instantiate_constituent_tys_for_sized_trait,
@@ -186,6 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         ecx.probe_and_evaluate_goal_for_constituent_tys(
             goal,
             structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
@@ -196,6 +214,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         if goal.predicate.self_ty().has_non_region_infer() {
             return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
         }
@@ -217,6 +239,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         if let ty::FnPtr(..) = goal.predicate.self_ty().kind() {
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         } else {
@@ -229,6 +255,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         let tcx = ecx.tcx();
         let tupled_inputs_and_output =
             match structural_traits::extract_tupled_inputs_and_output_from_callable(
@@ -259,6 +289,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         } else {
@@ -268,8 +302,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
     fn consider_builtin_pointee_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
-        _goal: Goal<'tcx, Self>,
+        goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 
@@ -277,6 +315,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else {
             return Err(NoSolution);
         };
@@ -297,6 +339,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         let self_ty = goal.predicate.self_ty();
         let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
             return Err(NoSolution);
@@ -326,6 +372,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         let tcx = ecx.tcx();
         let a_ty = goal.predicate.self_ty();
         let b_ty = goal.predicate.trait_ref.substs.type_at(1);
@@ -447,6 +497,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> Vec<CanonicalResponse<'tcx>> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return vec![];
+        }
+
         let tcx = ecx.tcx();
 
         let a_ty = goal.predicate.self_ty();
@@ -521,8 +575,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
     fn consider_builtin_discriminant_kind_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
-        _goal: Goal<'tcx, Self>,
+        goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         // `DiscriminantKind` is automatically implemented for every type.
         ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
@@ -531,6 +589,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         if !goal.param_env.is_const() {
             // `Destruct` is automatically implemented for every type in
             // non-const environments.
@@ -545,6 +607,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
         // `rustc_transmute` does not have support for type or const params
         if goal.has_non_region_placeholders() {
             return Err(NoSolution);
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 20c2605f219..b7690f79933 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -582,7 +582,7 @@ fn orphan_check_trait_ref<'tcx>(
     trait_ref: ty::TraitRef<'tcx>,
     in_crate: InCrate,
 ) -> Result<(), OrphanCheckErr<'tcx>> {
-    if trait_ref.needs_infer() && trait_ref.needs_subst() {
+    if trait_ref.has_infer() && trait_ref.has_param() {
         bug!(
             "can't orphan check a trait ref with both params and inference variables {:?}",
             trait_ref
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index ce187fbdf84..69b3c1e7eff 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -271,7 +271,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                 let underscores = vec!["_"; expected_args.len()].join(", ");
                 err.span_suggestion_verbose(
                     closure_arg_span.unwrap_or(found_span),
-                    &format!(
+                    format!(
                         "consider changing the closure to take and ignore the expected argument{}",
                         pluralize!(expected_args.len())
                     ),
@@ -575,7 +575,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             Limit(0) => Limit(2),
             limit => limit * 2,
         };
-        err.help(&format!(
+        err.help(format!(
             "consider increasing the recursion limit by adding a \
              `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
             suggested_limit,
@@ -737,7 +737,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
                             err.span_label(
                                 ret_span,
-                                &format!(
+                                format!(
                                     "expected `{}` because of this",
                                     trait_ref.skip_binder().self_ty()
                                 ),
@@ -780,7 +780,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             err.emit();
                             return;
                         }
-                        if let Some(ref s) = label {
+                        if let Some(s) = label {
                             // If it has a custom `#[rustc_on_unimplemented]`
                             // error message, let's display it as the label!
                             err.span_label(span, s);
@@ -788,7 +788,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 // When the self type is a type param We don't need to "the trait
                                 // `std::marker::Sized` is not implemented for `T`" as we will point
                                 // at the type param with a label to suggest constraining it.
-                                err.help(&explanation);
+                                err.help(explanation);
                             }
                         } else if let Some(custom_explanation) = safe_transmute_explanation {
                             err.span_label(span, custom_explanation);
@@ -811,13 +811,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             );
 
                         if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
+                            err.span_label(span, msg);
                         }
-                        if let Some(ref s) = note {
+                        if let Some(s) = note {
                             // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
+                            err.note(s);
                         }
-                        if let Some(ref s) = parent_label {
+                        if let Some(s) = parent_label {
                             let body = obligation.cause.body_id;
                             err.span_label(tcx.def_span(body), s);
                         }
@@ -1028,7 +1028,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 // which bounds actually failed to hold.
                                 self.tcx.sess.struct_span_err(
                                     span,
-                                    &format!("the type `{}` is not well-formed", ty),
+                                    format!("the type `{}` is not well-formed", ty),
                                 )
                             }
                         }
@@ -1071,7 +1071,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
                         let mut diag = self.tcx.sess.struct_span_err(
                             span,
-                            &format!("the constant `{}` is not of type `{}`", ct, ty),
+                            format!("the constant `{}` is not of type `{}`", ct, ty),
                         );
                         self.note_type_err(
                             &mut diag,
@@ -1835,7 +1835,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             candidates.sort();
             candidates.dedup();
             let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
-            err.help(&format!(
+            err.help(format!(
                 "the following {other}types implement trait `{}`:{}{}",
                 trait_ref.print_only_trait_path(),
                 candidates[..end].join(""),
@@ -2026,7 +2026,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 "perhaps two different versions of crate `{}` are being used?",
                 trait_crate
             );
-            err.note(&crate_msg);
+            err.note(crate_msg);
             suggested = true;
         }
         suggested
@@ -2158,7 +2158,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 err.cancel();
                                 return;
                             }
-                            err.note(&format!("cannot satisfy `{}`", predicate));
+                            err.note(format!("cannot satisfy `{}`", predicate));
                             let impl_candidates = self.find_similar_impl_candidates(
                                 predicate.to_opt_poly_trait_pred().unwrap(),
                             );
@@ -2178,7 +2178,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             err.cancel();
                             return;
                         }
-                        err.note(&format!("cannot satisfy `{}`", predicate));
+                        err.note(format!("cannot satisfy `{}`", predicate));
                     }
                 }
 
@@ -2223,9 +2223,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         err.cancel();
                         err = self.tcx.sess.struct_span_err_with_code(
                             span,
-                            &format!(
+                            format!(
                                 "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
-                             ),
+                            ),
                             rustc_errors::error_code!(E0790),
                         );
 
@@ -2332,7 +2332,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ErrorCode::E0284,
                         true,
                     );
-                    err.note(&format!("cannot satisfy `{}`", predicate));
+                    err.note(format!("cannot satisfy `{}`", predicate));
                     err
                 } else {
                     // If we can't find a substitution, just print a generic error
@@ -2343,7 +2343,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         "type annotations needed: cannot satisfy `{}`",
                         predicate,
                     );
-                    err.span_label(span, &format!("cannot satisfy `{}`", predicate));
+                    err.span_label(span, format!("cannot satisfy `{}`", predicate));
                     err
                 }
             }
@@ -2371,7 +2371,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         "type annotations needed: cannot satisfy `{}`",
                         predicate,
                     );
-                    err.span_label(span, &format!("cannot satisfy `{}`", predicate));
+                    err.span_label(span, format!("cannot satisfy `{}`", predicate));
                     err
                 }
             }
@@ -2386,7 +2386,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     "type annotations needed: cannot satisfy `{}`",
                     predicate,
                 );
-                err.span_label(span, &format!("cannot satisfy `{}`", predicate));
+                err.span_label(span, format!("cannot satisfy `{}`", predicate));
                 err
             }
         };
@@ -2459,13 +2459,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         match (spans.len(), crates.len(), crate_names.len()) {
             (0, 0, 0) => {
-                err.note(&format!("cannot satisfy `{}`", predicate));
+                err.note(format!("cannot satisfy `{}`", predicate));
             }
             (0, _, 1) => {
-                err.note(&format!("{} in the `{}` crate{}", msg, crates[0], post,));
+                err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,));
             }
             (0, _, _) => {
-                err.note(&format!(
+                err.note(format!(
                     "{} in the following crates: {}{}",
                     msg,
                     crate_names.join(", "),
@@ -2474,19 +2474,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             (_, 0, 0) => {
                 let span: MultiSpan = spans.into();
-                err.span_note(span, &msg);
+                err.span_note(span, msg);
             }
             (_, 1, 1) => {
                 let span: MultiSpan = spans.into();
-                err.span_note(span, &msg);
-                err.note(
-                    &format!("and another `impl` found in the `{}` crate{}", crates[0], post,),
-                );
+                err.span_note(span, msg);
+                err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,));
             }
             _ => {
                 let span: MultiSpan = spans.into();
-                err.span_note(span, &msg);
-                err.note(&format!(
+                err.span_note(span, msg);
+                err.note(format!(
                     "and more `impl`s found in the following crates: {}{}",
                     crate_names.join(", "),
                     post,
@@ -2657,7 +2655,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
         err.span_help(
             multispan,
-            &format!(
+            format!(
                 "you could relax the implicit `Sized` bound on `{T}` if it were \
                 used through indirection like `&{T}` or `Box<{T}>`",
                 T = param.name.ident(),
@@ -2882,7 +2880,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             .fn_trait_kind_from_def_id(trait_ref.def_id())
             .expect("expected to map DefId to ClosureKind");
         if !implemented_kind.extends(selected_kind) {
-            err.note(&format!(
+            err.note(format!(
                 "`{}` implements `{}`, but it must implement `{}`, which is more general",
                 trait_ref.skip_binder().self_ty(),
                 implemented_kind,
@@ -2899,7 +2897,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             if expected.len() != given.len() {
                 // Note number of types that were expected and given
                 err.note(
-                    &format!(
+                    format!(
                         "expected a closure taking {} argument{}, but one taking {} argument{} was given",
                         given.len(),
                         pluralize!(given.len()),
@@ -2942,7 +2940,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 unsatisfied_const = UnsatisfiedConst(true);
                 err.span_note(
                     span,
-                    &format!(
+                    format!(
                         "the trait `{}` is implemented for `{}`, \
                         but that implementation is not `const`",
                         non_const_predicate.print_modifiers_and_trait_path(),
@@ -3171,7 +3169,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
                 let const_span = self.tcx.def_span(uv.def);
                 match self.tcx.sess.source_map().span_to_snippet(const_span) {
-                    Ok(snippet) => err.help(&format!(
+                    Ok(snippet) => err.help(format!(
                         "try adding a `where` bound using this expression: `where [(); {}]:`",
                         snippet
                     )),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index c969e5d4975..08220c4fe9f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -515,7 +515,7 @@ fn suggest_restriction<'tcx>(
 
         err.span_suggestion_verbose(
             sp,
-            &format!("consider further restricting {}", msg),
+            format!("consider further restricting {}", msg),
             suggestion,
             Applicability::MachineApplicable,
         );
@@ -964,7 +964,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // a more general note.
             err.span_suggestion_verbose(
                 obligation.cause.span.shrink_to_hi(),
-                &msg,
+                msg,
                 format!("({args})"),
                 Applicability::HasPlaceholders,
             );
@@ -994,7 +994,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 _ => return false,
             };
-            err.help(&format!("{msg}: `{name}({args})`"));
+            err.help(format!("{msg}: `{name}({args})`"));
         }
         true
     }
@@ -1334,7 +1334,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                     let msg = format!("the trait bound `{}` is not satisfied", old_pred);
                     if has_custom_message {
-                        err.note(&msg);
+                        err.note(msg);
                     } else {
                         err.message =
                             vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
@@ -1358,7 +1358,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     } else {
                         let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
                         let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" });
-                        let sugg_msg = &format!(
+                        let sugg_msg = format!(
                             "consider{} borrowing here",
                             if is_mut { " mutably" } else { "" }
                         );
@@ -1452,7 +1452,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         err.span_suggestion(
             obligation.cause.span.shrink_to_lo(),
-            &format!(
+            format!(
                 "consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
             ),
             "&",
@@ -1505,7 +1505,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 };
 
                 err.multipart_suggestion_verbose(
-                    &msg,
+                    msg,
                     suggestions,
                     Applicability::MachineApplicable,
                 );
@@ -1583,55 +1583,68 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 
     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
-        let span = obligation.cause.span;
-
-        if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() {
-            let hir = self.tcx.hir();
-            if let Some(hir::Node::Expr(expr)) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
-                // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
-                // and if not maybe suggest doing something else? If we kept the expression around we
-                // could also check if it is an fn call (very likely) and suggest changing *that*, if
-                // it is from the local crate.
+        let hir = self.tcx.hir();
+        if let ObligationCauseCode::AwaitableExpr(Some(hir_id)) = obligation.cause.code().peel_derives()
+            && let hir::Node::Expr(expr) = hir.get(*hir_id)
+        {
+            // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
+            // and if not maybe suggest doing something else? If we kept the expression around we
+            // could also check if it is an fn call (very likely) and suggest changing *that*, if
+            // it is from the local crate.
+
+            // use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
+            if let Some((_, hir::Node::Expr(await_expr))) = hir.parent_iter(*hir_id).nth(1)
+                && let Some(expr_span) = expr.span.find_ancestor_inside(await_expr.span)
+            {
+                let removal_span = self.tcx
+                    .sess
+                    .source_map()
+                    .span_extend_while(expr_span, char::is_whitespace)
+                    .unwrap_or(expr_span)
+                    .shrink_to_hi()
+                    .to(await_expr.span.shrink_to_hi());
                 err.span_suggestion(
-                    span,
+                    removal_span,
                     "remove the `.await`",
                     "",
                     Applicability::MachineApplicable,
                 );
-                // FIXME: account for associated `async fn`s.
-                if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
-                    if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
-                        obligation.predicate.kind().skip_binder()
+            } else {
+                err.span_label(obligation.cause.span, "remove the `.await`");
+            }
+            // FIXME: account for associated `async fn`s.
+            if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
+                if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
+                    obligation.predicate.kind().skip_binder()
+                {
+                    err.span_label(*span, format!("this call returns `{}`", pred.self_ty()));
+                }
+                if let Some(typeck_results) = &self.typeck_results
+                        && let ty = typeck_results.expr_ty_adjusted(base)
+                        && let ty::FnDef(def_id, _substs) = ty.kind()
+                        && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
+                            hir.get_if_local(*def_id)
                     {
-                        err.span_label(*span, &format!("this call returns `{}`", pred.self_ty()));
-                    }
-                    if let Some(typeck_results) = &self.typeck_results
-                            && let ty = typeck_results.expr_ty_adjusted(base)
-                            && let ty::FnDef(def_id, _substs) = ty.kind()
-                            && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
-                                hir.get_if_local(*def_id)
-                        {
-                            let msg = format!(
-                                "alternatively, consider making `fn {}` asynchronous",
-                                ident
+                        let msg = format!(
+                            "alternatively, consider making `fn {}` asynchronous",
+                            ident
+                        );
+                        if vis_span.is_empty() {
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                msg,
+                                "async ",
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            err.span_suggestion_verbose(
+                                vis_span.shrink_to_hi(),
+                                msg,
+                                " async",
+                                Applicability::MaybeIncorrect,
                             );
-                            if vis_span.is_empty() {
-                                err.span_suggestion_verbose(
-                                    span.shrink_to_lo(),
-                                    &msg,
-                                    "async ",
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                err.span_suggestion_verbose(
-                                    vis_span.shrink_to_hi(),
-                                    &msg,
-                                    " async",
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
                         }
-                }
+                    }
             }
         }
     }
@@ -1704,7 +1717,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             Applicability::MachineApplicable,
                         );
                     } else {
-                        err.note(&format!(
+                        err.note(format!(
                             "`{}` is implemented for `{:?}`, but not for `{:?}`",
                             trait_pred.print_modifiers_and_trait_path(),
                             suggested_ty,
@@ -1741,7 +1754,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         {
             err.span_label(
                 expr.span,
-                &format!(
+                format!(
                     "this expression has type `{}`, which implements `{}`",
                     ty,
                     trait_pred.print_modifiers_and_trait_path()
@@ -1933,7 +1946,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // Suggest `-> impl Trait`.
             err.span_suggestion(
                 ret_ty.span,
-                &format!(
+                format!(
                     "use `impl {1}` as the return type, as all return paths are of type `{}`, \
                      which implements `{1}`",
                     last_ty, trait_obj,
@@ -1968,13 +1981,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             } else {
                 // This is currently not possible to trigger because E0038 takes precedence, but
                 // leave it in for completeness in case anything changes in an earlier stage.
-                err.note(&format!(
+                err.note(format!(
                     "if trait `{}` were object-safe, you could return a trait object",
                     trait_obj,
                 ));
             }
             err.note(trait_obj_msg);
-            err.note(&format!(
+            err.note(format!(
                 "if all the returned values were of the same type you could use `impl {}` as the \
                  return type",
                 trait_obj,
@@ -2014,7 +2027,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     } else {
                         err.span_label(
                             expr.span,
-                            &format!("this returned value is of type `{}`", ty),
+                            format!("this returned value is of type `{}`", ty),
                         );
                     }
                 }
@@ -2164,7 +2177,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) {
         if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
             if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
-                err.note(&format!(
+                err.note(format!(
                     "{}s cannot be accessed directly on a `trait`, they can only be \
                         accessed through a specific `impl`",
                     self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id)
@@ -2594,7 +2607,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 err.span_note(
                     span,
-                    &format!(
+                    format!(
                         "{} {} as this value is used across {}",
                         future_or_generator, trait_explanation, an_await_or_yield
                     ),
@@ -2615,7 +2628,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         );
                         err.span_note(
                             span,
-                            &format!(
+                            format!(
                                 "future {not_trait} as it awaits another future which {not_trait}",
                                 not_trait = trait_explanation
                             ),
@@ -2717,7 +2730,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 let mut span = MultiSpan::from_span(upvar_span);
                 span.push_span_label(upvar_span, span_label);
-                err.span_note(span, &span_note);
+                err.span_note(span, span_note);
             }
         }
 
@@ -2781,15 +2794,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{data}` is well-formed"));
+                err.note(format!("required so that the projection `{data}` is well-formed"));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!(
+                err.note(format!(
                     "required so that reference `{ref_ty}` does not outlive its referent"
                 ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!(
+                err.note(format!(
                     "required so that the lifetime bound of `{}` for `{}` is satisfied",
                     region, object_ty,
                 ));
@@ -2825,9 +2838,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if span.is_visible(sm) {
                     let msg = format!("required by this bound in `{short_item_name}`");
                     multispan.push_span_label(span, msg);
-                    err.span_note(multispan, &descr);
+                    err.span_note(multispan, descr);
                 } else {
-                    err.span_note(tcx.def_span(item_def_id), &descr);
+                    err.span_note(tcx.def_span(item_def_id), descr);
                 }
             }
             ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
@@ -2835,24 +2848,24 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
                 let (object_ty, object_file) =
                     self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
-                err.note(&with_forced_trimmed_paths!(format!(
+                err.note(with_forced_trimmed_paths!(format!(
                     "required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
                 )));
                 if let Some(file) = concrete_file {
-                    err.note(&format!(
+                    err.note(format!(
                         "the full name for the casted type has been written to '{}'",
                         file.display(),
                     ));
                 }
                 if let Some(file) = object_file {
-                    err.note(&format!(
+                    err.note(format!(
                         "the full name for the object type has been written to '{}'",
                         file.display(),
                     ));
                 }
             }
             ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
+                err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
             }
             ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
                 err.note(
@@ -3055,8 +3068,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ));
                         match ty.kind() {
                             ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
-                                Some(ident) => err.span_note(ident.span, &msg),
-                                None => err.note(&msg),
+                                Some(ident) => err.span_note(ident.span, msg),
+                                None => err.note(msg),
                             },
                             ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                                 // If the previous type is async fn, this is the future generated by the body of an async function.
@@ -3077,7 +3090,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 {
                                     break 'print;
                                 }
-                                err.span_note(self.tcx.def_span(def_id), &msg)
+                                err.span_note(self.tcx.def_span(def_id), msg)
                             }
                             ty::GeneratorWitness(bound_tys) => {
                                 use std::fmt::Write;
@@ -3113,7 +3126,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let kind = tcx.generator_kind(def_id).unwrap().descr();
                                 err.span_note(
                                     sp,
-                                    with_forced_trimmed_paths!(&format!(
+                                    with_forced_trimmed_paths!(format!(
                                         "required because it's used within this {kind}",
                                     )),
                                 )
@@ -3123,7 +3136,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 "required because it's used within this closure",
                             ),
                             ty::Str => err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes"),
-                            _ => err.note(&msg),
+                            _ => err.note(msg),
                         };
                     }
                 }
@@ -3177,7 +3190,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         // FIXME: we should do something else so that it works even on crate foreign
                         // auto traits.
                         is_auto_trait = matches!(is_auto, hir::IsAuto::Yes);
-                        err.span_note(ident.span, &msg);
+                        err.span_note(ident.span, msg);
                     }
                     Some(Node::Item(hir::Item {
                         kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
@@ -3206,15 +3219,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 "unsatisfied trait bound introduced here",
                             );
                         }
-                        err.span_note(spans, &msg);
+                        err.span_note(spans, msg);
                     }
                     _ => {
-                        err.note(&msg);
+                        err.note(msg);
                     }
                 };
 
                 if let Some(file) = file {
-                    err.note(&format!(
+                    err.note(format!(
                         "the full type name has been written to '{}'",
                         file.display(),
                     ));
@@ -3254,19 +3267,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     parent_trait_pred = child_trait_pred;
                 }
                 if count > 0 {
-                    err.note(&format!(
+                    err.note(format!(
                         "{} redundant requirement{} hidden",
                         count,
                         pluralize!(count)
                     ));
                     let (self_ty, file) =
                         self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
-                    err.note(&format!(
+                    err.note(format!(
                         "required for `{self_ty}` to implement `{}`",
                         parent_trait_pred.print_modifiers_and_trait_path()
                     ));
                     if let Some(file) = file {
-                        err.note(&format!(
+                        err.note(format!(
                             "the full type name has been written to '{}'",
                             file.display(),
                         ));
@@ -3347,7 +3360,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 {
                     assoc_span.push_span_label(ident.span, "in this trait");
                 }
-                err.span_note(assoc_span, &msg);
+                err.span_note(assoc_span, msg);
             }
             ObligationCauseCode::TrivialBound => {
                 err.help("see issue #48214");
@@ -3503,7 +3516,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if can_derive {
             err.span_suggestion_verbose(
                 self.tcx.def_span(adt.did()).shrink_to_lo(),
-                &format!(
+                format!(
                     "consider annotating `{}` with `#[derive({})]`",
                     trait_pred.skip_binder().self_ty(),
                     diagnostic_name,
@@ -3890,7 +3903,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             .map(|trait_ref| trait_ref.trait_ref.self_ty())
             .find(|t| is_slice(*t))
         {
-            let msg = &format!("convert the array to a `{}` slice instead", slice_ty);
+            let msg = format!("convert the array to a `{}` slice instead", slice_ty);
 
             if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                 let mut suggestions = vec![];
@@ -4111,7 +4124,7 @@ fn suggest_trait_object_return_type_alternatives(
 ) {
     err.span_suggestion(
         ret_ty,
-        &format!(
+        format!(
             "use `impl {}` as the return type if all return paths have the same type but you \
                 want to expose only the trait in the signature",
             trait_obj,
@@ -4121,7 +4134,7 @@ fn suggest_trait_object_return_type_alternatives(
     );
     if is_object_safe {
         err.multipart_suggestion(
-            &format!(
+            format!(
                 "use a boxed trait object if all return paths implement trait `{}`",
                 trait_obj,
             ),
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 63949843aed..2210ef975e6 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -2,13 +2,14 @@
 
 use crate::traits::{self, ObligationCause, ObligationCtxt};
 
+use hir::LangItem;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtDef, GenericArg, List, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::DUMMY_SP;
 
 use super::outlives_bounds::InferCtxtExt;
@@ -19,6 +20,11 @@ pub enum CopyImplementationError<'tcx> {
     HasDestructor,
 }
 
+pub enum ConstParamTyImplementationError<'tcx> {
+    InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
+    NotAnAdtOrBuiltinAllowed,
+}
+
 pub enum InfringingFieldsReason<'tcx> {
     Fulfill(Vec<FulfillmentError<'tcx>>),
     Regions(Vec<RegionResolutionError<'tcx>>),
@@ -27,7 +33,10 @@ pub enum InfringingFieldsReason<'tcx> {
 /// Checks that the fields of the type (an ADT) all implement copy.
 ///
 /// If fields don't implement copy, return an error containing a list of
-/// those violating fields. If it's not an ADT, returns `Err(NotAnAdt)`.
+/// those violating fields.
+///
+/// If it's not an ADT, int ty, `bool`, float ty, `char`, raw pointer, `!`,
+/// a reference or an array returns `Err(NotAnAdt)`.
 pub fn type_allowed_to_implement_copy<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -47,12 +56,82 @@ pub fn type_allowed_to_implement_copy<'tcx>(
         | ty::Ref(_, _, hir::Mutability::Not)
         | ty::Array(..) => return Ok(()),
 
-        ty::Adt(adt, substs) => (adt, substs),
+        &ty::Adt(adt, substs) => (adt, substs),
 
         _ => return Err(CopyImplementationError::NotAnAdt),
     };
 
-    let copy_def_id = tcx.require_lang_item(hir::LangItem::Copy, Some(parent_cause.span));
+    all_fields_implement_trait(
+        tcx,
+        param_env,
+        self_type,
+        adt,
+        substs,
+        parent_cause,
+        hir::LangItem::Copy,
+    )
+    .map_err(CopyImplementationError::InfringingFields)?;
+
+    if adt.has_dtor(tcx) {
+        return Err(CopyImplementationError::HasDestructor);
+    }
+
+    Ok(())
+}
+
+/// Checks that the fields of the type (an ADT) all implement `ConstParamTy`.
+///
+/// If fields don't implement `ConstParamTy`, return an error containing a list of
+/// those violating fields.
+///
+/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
+pub fn type_allowed_to_implement_const_param_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    self_type: Ty<'tcx>,
+    parent_cause: ObligationCause<'tcx>,
+) -> Result<(), ConstParamTyImplementationError<'tcx>> {
+    let (adt, substs) = match self_type.kind() {
+        // `core` provides these impls.
+        ty::Uint(_)
+        | ty::Int(_)
+        | ty::Bool
+        | ty::Char
+        | ty::Str
+        | ty::Array(..)
+        | ty::Slice(_)
+        | ty::Ref(.., hir::Mutability::Not) => return Ok(()),
+
+        &ty::Adt(adt, substs) => (adt, substs),
+
+        _ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
+    };
+
+    all_fields_implement_trait(
+        tcx,
+        param_env,
+        self_type,
+        adt,
+        substs,
+        parent_cause,
+        hir::LangItem::ConstParamTy,
+    )
+    .map_err(ConstParamTyImplementationError::InfrigingFields)?;
+
+    Ok(())
+}
+
+/// Check that all fields of a given `adt` implement `lang_item` trait.
+pub fn all_fields_implement_trait<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    self_type: Ty<'tcx>,
+    adt: AdtDef<'tcx>,
+    substs: &'tcx List<GenericArg<'tcx>>,
+    parent_cause: ObligationCause<'tcx>,
+    lang_item: LangItem,
+) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> {
+    let trait_def_id = tcx.require_lang_item(lang_item, Some(parent_cause.span));
 
     let mut infringing = Vec::new();
     for variant in adt.variants() {
@@ -93,7 +172,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
             // between expected and found const-generic types. Don't report an
             // additional copy error here, since it's not typically useful.
             if !normalization_errors.is_empty() || ty.references_error() {
-                tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking Copy implementation"));
+                tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking {tr} implementation", tr = tcx.def_path_str(trait_def_id)));
                 continue;
             }
 
@@ -101,7 +180,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
                 ObligationCause::dummy_with_span(field_ty_span),
                 param_env,
                 ty,
-                copy_def_id,
+                trait_def_id,
             );
             let errors = ocx.select_all_or_error();
             if !errors.is_empty() {
@@ -124,15 +203,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
         }
     }
 
-    if !infringing.is_empty() {
-        return Err(CopyImplementationError::InfringingFields(infringing));
-    }
-
-    if adt.has_dtor(tcx) {
-        return Err(CopyImplementationError::HasDestructor);
-    }
-
-    Ok(())
+    if infringing.is_empty() { Ok(()) } else { Err(infringing) }
 }
 
 pub fn check_tys_might_be_eq<'tcx>(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 4c9df5d9d0a..0e8c74a6765 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -414,7 +414,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
         predicates.push(ty::Binder::dummy(trait_ref).to_predicate(tcx));
     }
 
-    predicates.retain(|predicate| !predicate.needs_subst());
+    predicates.retain(|predicate| !predicate.has_param());
     let result = impossible_predicates(tcx, predicates);
 
     debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index b8ad1925e4e..384b6ae93a1 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -297,8 +297,8 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
     tcx.associated_items(trait_def_id)
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
-        .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
-        .filter_map(|pred_span| predicate_references_self(tcx, *pred_span))
+        .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
+        .filter_map(|pred_span| predicate_references_self(tcx, pred_span))
         .collect()
 }
 
@@ -525,7 +525,7 @@ fn virtual_call_violation_for_method<'tcx>(
                         // #78372
                         tcx.sess.delay_span_bug(
                             tcx.def_span(method.def_id),
-                            &format!("error: {}\n while computing layout for type {:?}", err, ty),
+                            format!("error: {}\n while computing layout for type {:?}", err, ty),
                         );
                         None
                     }
@@ -541,7 +541,7 @@ fn virtual_call_violation_for_method<'tcx>(
                 abi => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(method.def_id),
-                        &format!(
+                        format!(
                             "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
                             abi
                         ),
@@ -560,7 +560,7 @@ fn virtual_call_violation_for_method<'tcx>(
                 abi => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(method.def_id),
-                        &format!(
+                        format!(
                             "receiver when `Self = {}` should have a ScalarPair ABI; found {:?}",
                             trait_object_ty, abi
                         ),
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index e01a57ea4fe..0db80232891 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -60,7 +60,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
         // We may however encounter unconstrained lifetime variables in invalid
         // code. See #110161 for context.
         assert!(!ty.has_non_region_infer());
-        if ty.needs_infer() {
+        if ty.has_infer() {
             self.tcx.sess.delay_span_bug(
                 self.tcx.def_span(body_id),
                 "skipped implied_outlives_bounds due to unconstrained lifetimes",
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index ea45412e47f..4369b257f5f 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1749,7 +1749,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
-                    &format!("Cannot project an associated type from `{:?}`", impl_source),
+                    format!("Cannot project an associated type from `{:?}`", impl_source),
                 );
                 return Err(());
             }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 8f1b05c1190..1f8e756043d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -79,7 +79,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     if !errors.is_empty() {
         infcx.tcx.sess.diagnostic().delay_span_bug(
             DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", errors),
+            format!("errors selecting obligation during MIR typeck: {:?}", errors),
         );
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 081e4d7cfa4..9890e990eeb 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -67,7 +67,7 @@ impl IntercrateAmbiguityCause {
     /// Emits notes when the overlap is caused by complex intercrate ambiguities.
     /// See #23980 for details.
     pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diagnostic) {
-        err.note(&self.intercrate_ambiguity_hint());
+        err.note(self.intercrate_ambiguity_hint());
     }
 
     pub fn intercrate_ambiguity_hint(&self) -> String {
@@ -449,7 +449,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
 
-        let needs_infer = stack.obligation.predicate.has_non_region_infer();
+        let has_non_region_infer = stack.obligation.predicate.has_non_region_infer();
 
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
@@ -461,7 +461,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.candidate_should_be_dropped_in_favor_of(
                         &candidates[i],
                         &candidates[j],
-                        needs_infer,
+                        has_non_region_infer,
                     ) == DropVictim::Yes
                 });
                 if should_drop_i {
@@ -1000,7 +1000,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<EvaluationResult, OverflowError> {
         if !self.is_intercrate()
             && obligation.is_global()
-            && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
+            && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())
         {
             // If a param env has no global bounds, global obligations do not
             // depend on its particular value in order to work, so we can clear
@@ -1330,7 +1330,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         if self.can_use_global_caches(param_env) {
-            if !trait_pred.needs_infer() {
+            if !trait_pred.has_infer() {
                 debug!(?trait_pred, ?result, "insert_evaluation_cache global");
                 // This may overwrite the cache with the same value
                 // FIXME: Due to #50507 this overwrites the different values
@@ -1516,7 +1516,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // If there are any inference variables in the `ParamEnv`, then we
         // always use a cache local to this particular scope. Otherwise, we
         // switch to a global cache.
-        if param_env.needs_infer() {
+        if param_env.has_infer() {
             return false;
         }
 
@@ -1587,7 +1587,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return false;
         }
         match result {
-            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
+            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
             _ => true,
         }
     }
@@ -1613,8 +1613,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         if self.can_use_global_caches(param_env) {
             if let Err(Overflow(OverflowError::Canonical)) = candidate {
                 // Don't cache overflow globally; we only produce this in certain modes.
-            } else if !pred.needs_infer() {
-                if !candidate.needs_infer() {
+            } else if !pred.has_infer() {
+                if !candidate.has_infer() {
                     debug!(?pred, ?candidate, "insert_candidate_cache global");
                     // This may overwrite the cache with the same value.
                     tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
@@ -1724,7 +1724,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .map(|InferOk { obligations: _, value: () }| {
                 // This method is called within a probe, so we can't have
                 // inference variables and placeholders escape.
-                if !trait_bound.needs_infer() && !trait_bound.has_placeholders() {
+                if !trait_bound.has_infer() && !trait_bound.has_placeholders() {
                     Some(trait_bound)
                 } else {
                     None
@@ -1840,7 +1840,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         &mut self,
         victim: &EvaluatedCandidate<'tcx>,
         other: &EvaluatedCandidate<'tcx>,
-        needs_infer: bool,
+        has_non_region_infer: bool,
     ) -> DropVictim {
         if victim.candidate == other.candidate {
             return DropVictim::Yes;
@@ -1956,7 +1956,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             | (ObjectCandidate(i), ObjectCandidate(j)) => {
                 // Arbitrarily pick the lower numbered candidate for backwards
                 // compatibility reasons. Don't let this affect inference.
-                DropVictim::drop_if(i < j && !needs_infer)
+                DropVictim::drop_if(i < j && !has_non_region_infer)
             }
             (ObjectCandidate(_), ProjectionCandidate(..))
             | (ProjectionCandidate(..), ObjectCandidate(_)) => {
@@ -2062,7 +2062,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                         // existence of multiple marker trait impls tells us nothing
                         // about which one should actually apply.
                         DropVictim::drop_if(
-                            !needs_infer && other.evaluation.must_apply_considering_regions(),
+                            !has_non_region_infer
+                                && other.evaluation.must_apply_considering_regions(),
                         )
                     }
                     None => DropVictim::No,
@@ -2448,7 +2449,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 // for a variable being generalized...
                 let guar = self.infcx.tcx.sess.delay_span_bug(
                     obligation.cause.span,
-                    &format!(
+                    format!(
                         "Impl {:?} was matchable against {:?} but now is not",
                         impl_def_id, obligation
                     ),
@@ -3006,16 +3007,16 @@ fn bind_generator_hidden_types_above<'tcx>(
 
             // Only remap erased regions if we use them.
             if considering_regions {
-                ty = tcx.fold_regions(ty, |mut r, current_depth| {
-                    if let ty::ReErased = r.kind() {
+                ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
+                    ty::ReErased => {
                         let br = ty::BoundRegion {
                             var: ty::BoundVar::from_u32(counter),
                             kind: ty::BrAnon(None),
                         };
                         counter += 1;
-                        r = tcx.mk_re_late_bound(current_depth, br);
+                        tcx.mk_re_late_bound(current_depth, br)
                     }
-                    r
+                    r => bug!("unexpected region: {r:?}"),
                 })
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 8546bbe52dc..233d35aed38 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -373,7 +373,7 @@ fn report_conflicting_impls<'tcx>(
                     }
                     None => format!("conflicting implementation in crate `{}`", cname),
                 };
-                err.note(&msg);
+                err.note(msg);
             }
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index a4e9928f8b2..c56e7c7cadd 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -353,8 +353,8 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
     ),
 ) -> Option<usize> {
     let (source, target) = key;
-    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
-    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
+    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.has_infer());
+    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.has_infer());
 
     // this has been typecked-before, so diagnostics is not really needed.
     let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);