about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs46
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs23
-rw-r--r--compiler/rustc_middle/src/values.rs5
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs172
-rw-r--r--compiler/rustc_trait_selection/src/solve/infcx_ext.rs77
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs30
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs96
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs40
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs26
-rw-r--r--library/std/src/sys/unix/fd.rs5
-rw-r--r--src/bootstrap/test.rs12
-rw-r--r--src/librustdoc/clean/mod.rs24
-rw-r--r--tests/mir-opt/casts.redundant.InstCombine.diff25
-rw-r--r--tests/mir-opt/casts.redundant.PreCodegen.after.mir14
-rw-r--r--tests/mir-opt/casts.roundtrip.PreCodegen.after.mir15
-rw-r--r--tests/mir-opt/casts.rs17
-rw-r--r--tests/rustdoc/issue-108281.rs25
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr5
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.rs8
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr69
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs (renamed from tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs)0
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr (renamed from tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr)4
-rw-r--r--tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs (renamed from tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs)2
-rw-r--r--tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr (renamed from tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr)19
-rw-r--r--tests/ui/impl-trait/equal-hidden-lifetimes.rs1
-rw-r--r--tests/ui/impl-trait/equal-hidden-lifetimes.stderr10
-rw-r--r--tests/ui/infinite/auxiliary/alias.rs2
-rw-r--r--tests/ui/infinite/infinite-alias.rs9
-rw-r--r--tests/ui/infinite/infinite-alias.stderr14
-rw-r--r--tests/ui/issues/issue-26094.rs5
-rw-r--r--tests/ui/issues/issue-26094.stderr5
-rw-r--r--tests/ui/issues/issue-30438-c.rs1
-rw-r--r--tests/ui/issues/issue-30438-c.stderr12
-rw-r--r--tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs2
-rw-r--r--tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr7
-rw-r--r--tests/ui/regions/regions-static-bound-rpass.rs2
-rw-r--r--tests/ui/regions/regions-static-bound-rpass.stderr11
-rw-r--r--tests/ui/regions/regions-static-bound.rs8
-rw-r--r--tests/ui/regions/regions-static-bound.stderr30
-rw-r--r--tests/ui/static/static-lifetime-bound.rs2
-rw-r--r--tests/ui/static/static-lifetime-bound.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr34
47 files changed, 562 insertions, 400 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index c0c90e47a75..e977767e024 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -18,6 +18,7 @@ use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
 use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
+use rustc_session::lint;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
@@ -923,17 +924,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                         origin,
                         ..
                     }) => {
-
                         let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
                             bound_generic_params
-                            .iter()
-                            .enumerate()
-                            .map(|(late_bound_idx, param)| {
-                                let pair = ResolvedArg::late(late_bound_idx as u32, param);
-                                let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
-                                (pair, r)
-                            })
-                            .unzip();
+                                .iter()
+                                .enumerate()
+                                .map(|(late_bound_idx, param)| {
+                                    let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                                    let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
+                                    (pair, r)
+                                })
+                                .unzip();
                         this.record_late_bound_vars(hir_id, binders.clone());
                         // Even if there are no lifetimes defined here, we still wrap it in a binder
                         // scope. If there happens to be a nested poly trait ref (an error), that
@@ -968,20 +968,22 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                                     continue;
                                 }
                                 this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
-                                this.tcx
-                                    .sess
-                                    .struct_span_warn(
-                                        lifetime.ident.span,
-                                        &format!(
-                                            "unnecessary lifetime parameter `{}`",
+                                this.tcx.struct_span_lint_hir(
+                                    lint::builtin::UNUSED_LIFETIMES,
+                                    lifetime.hir_id,
+                                    lifetime.ident.span,
+                                    format!(
+                                        "unnecessary lifetime parameter `{}`",
+                                        lifetime.ident
+                                    ),
+                                    |lint| {
+                                        let help = &format!(
+                                            "you can use the `'static` lifetime directly, in place of `{}`",
                                             lifetime.ident,
-                                        ),
-                                    )
-                                    .help(&format!(
-                                        "you can use the `'static` lifetime directly, in place of `{}`",
-                                        lifetime.ident,
-                                    ))
-                                    .emit();
+                                        );
+                                        lint.help(help)
+                                    },
+                                );
                             }
                         }
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 69a7235802b..6a33826ea28 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -932,25 +932,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     labels
                         .push((provided_span, format!("unexpected argument{}", provided_ty_name)));
                     let mut span = provided_span;
-                    if arg_idx.index() > 0
+                    if span.can_be_used_for_suggestions() {
+                        if arg_idx.index() > 0
                         && let Some((_, prev)) = provided_arg_tys
                             .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
                     ) {
                         // Include previous comma
-                        span = span.with_lo(prev.hi());
-                    } else if let Some((_, next)) = provided_arg_tys.get(
-                        ProvidedIdx::from_usize(arg_idx.index() + 1),
-                    ) {
-                        // Include next comma
-                        span = span.until(*next);
+                        span = prev.shrink_to_hi().to(span);
                     }
-                    suggestions.push((span, String::new()));
+                        suggestions.push((span, String::new()));
 
-                    suggestion_text = match suggestion_text {
-                        SuggestionText::None => SuggestionText::Remove(false),
-                        SuggestionText::Remove(_) => SuggestionText::Remove(true),
-                        _ => SuggestionText::DidYouMean,
-                    };
+                        suggestion_text = match suggestion_text {
+                            SuggestionText::None => SuggestionText::Remove(false),
+                            SuggestionText::Remove(_) => SuggestionText::Remove(true),
+                            _ => SuggestionText::DidYouMean,
+                        };
+                    }
                 }
                 Error::Missing(expected_idx) => {
                     // If there are multiple missing arguments adjacent to each other,
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 34e8a559784..21f3ef9267f 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -2,7 +2,7 @@ use crate::dep_graph::DepKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::Representability;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc_query_system::query::QueryInfo;
@@ -199,7 +199,8 @@ fn find_item_ty_spans(
 ) {
     match ty.kind {
         hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
-            if let Some(def_id) = path.res.opt_def_id() {
+            if let Res::Def(kind, def_id) = path.res
+                && kind != DefKind::TyAlias {
                 let check_params = def_id.as_local().map_or(true, |def_id| {
                     if def_id == needle {
                         spans.push(ty.span);
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 0534e688703..3896f0e57ea 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -30,6 +30,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
                         ctx.combine_bool_cmp(&statement.source_info, rvalue);
                         ctx.combine_ref_deref(&statement.source_info, rvalue);
                         ctx.combine_len(&statement.source_info, rvalue);
+                        ctx.combine_cast(&statement.source_info, rvalue);
                     }
                     _ => {}
                 }
@@ -142,6 +143,14 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
         }
     }
 
+    fn combine_cast(&self, _source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
+        if let Rvalue::Cast(_kind, operand, ty) = rvalue {
+            if operand.ty(self.local_decls, self.tcx) == *ty {
+                *rvalue = Rvalue::Use(operand.clone());
+            }
+        }
+    }
+
     fn combine_primitive_clone(
         &self,
         terminator: &mut Terminator<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index 841169ac78d..d55aebf1a26 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -1,6 +1,5 @@
 //! Code shared by trait and projection goals for candidate assembly.
 
-use super::infcx_ext::InferCtxtExt;
 #[cfg(doc)]
 use super::trait_goals::structural_traits::*;
 use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
@@ -206,7 +205,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         &mut self,
         goal: Goal<'tcx, G>,
     ) -> Vec<Candidate<'tcx>> {
-        debug_assert_eq!(goal, self.infcx.resolve_vars_if_possible(goal));
+        debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
 
         // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
         // object bound, alias bound, etc. We are unable to determine this until we can at
@@ -250,8 +249,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
             return
         };
-        self.infcx.probe(|_| {
-            let normalized_ty = self.infcx.next_ty_infer();
+        self.probe(|this| {
+            let normalized_ty = this.next_ty_infer();
             let normalizes_to_goal = goal.with(
                 tcx,
                 ty::Binder::dummy(ty::ProjectionPredicate {
@@ -259,16 +258,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     term: normalized_ty.into(),
                 }),
             );
-            let normalization_certainty = match self.evaluate_goal(normalizes_to_goal) {
+            let normalization_certainty = match this.evaluate_goal(normalizes_to_goal) {
                 Ok((_, certainty)) => certainty,
                 Err(NoSolution) => return,
             };
-            let normalized_ty = self.infcx.resolve_vars_if_possible(normalized_ty);
+            let normalized_ty = this.resolve_vars_if_possible(normalized_ty);
 
             // NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
             // This doesn't work as long as we use `CandidateSource` in winnowing.
             let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
-            let normalized_candidates = self.assemble_and_evaluate_candidates(goal);
+            let normalized_candidates = this.assemble_and_evaluate_candidates(goal);
             for mut normalized_candidate in normalized_candidates {
                 normalized_candidate.result =
                     normalized_candidate.result.unchecked_map(|mut response| {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
new file mode 100644
index 00000000000..67addd732d0
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -0,0 +1,172 @@
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::at::ToTrace;
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::ty::{self, ir::TypeVisitor, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable};
+use rustc_span::DUMMY_SP;
+use std::ops::ControlFlow;
+
+use super::search_graph::SearchGraph;
+use super::Goal;
+
+pub struct EvalCtxt<'a, 'tcx> {
+    // FIXME: should be private.
+    pub(super) infcx: &'a InferCtxt<'tcx>,
+
+    pub(super) var_values: CanonicalVarValues<'tcx>,
+
+    pub(super) search_graph: &'a mut SearchGraph<'tcx>,
+
+    /// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
+    /// see the comment in that method for more details.
+    pub in_projection_eq_hack: bool,
+}
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    pub(super) fn probe<T>(&mut self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T {
+        self.infcx.probe(|_| f(self))
+    }
+
+    pub(super) fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    pub(super) fn next_ty_infer(&self) -> Ty<'tcx> {
+        self.infcx.next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::MiscVariable,
+            span: DUMMY_SP,
+        })
+    }
+
+    pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+        self.infcx.next_const_var(
+            ty,
+            ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
+        )
+    }
+
+    /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
+    ///
+    /// This is the case if the `term` is an inference variable in the innermost universe
+    /// and does not occur in any other part of the predicate.
+    pub(super) fn term_is_fully_unconstrained(
+        &self,
+        goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+    ) -> bool {
+        let term_is_infer = match goal.predicate.term.unpack() {
+            ty::TermKind::Ty(ty) => {
+                if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
+                    match self.infcx.probe_ty_var(vid) {
+                        Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
+                        Err(universe) => universe == self.universe(),
+                    }
+                } else {
+                    false
+                }
+            }
+            ty::TermKind::Const(ct) => {
+                if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
+                    match self.infcx.probe_const_var(vid) {
+                        Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
+                        Err(universe) => universe == self.universe(),
+                    }
+                } else {
+                    false
+                }
+            }
+        };
+
+        // Guard against `<T as Trait<?0>>::Assoc = ?0>`.
+        struct ContainsTerm<'tcx> {
+            term: ty::Term<'tcx>,
+        }
+        impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
+            type BreakTy = ();
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                if t.needs_infer() {
+                    if ty::Term::from(t) == self.term {
+                        ControlFlow::Break(())
+                    } else {
+                        t.super_visit_with(self)
+                    }
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
+
+            fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+                if c.needs_infer() {
+                    if ty::Term::from(c) == self.term {
+                        ControlFlow::Break(())
+                    } else {
+                        c.super_visit_with(self)
+                    }
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
+        }
+
+        let mut visitor = ContainsTerm { term: goal.predicate.term };
+
+        term_is_infer
+            && goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
+            && goal.param_env.visit_with(&mut visitor).is_continue()
+    }
+
+    #[instrument(level = "debug", skip(self, param_env), ret)]
+    pub(super) fn eq<T: ToTrace<'tcx>>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        lhs: T,
+        rhs: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+        self.infcx
+            .at(&ObligationCause::dummy(), param_env)
+            .eq(lhs, rhs)
+            .map(|InferOk { value: (), obligations }| {
+                obligations.into_iter().map(|o| o.into()).collect()
+            })
+            .map_err(|e| {
+                debug!(?e, "failed to equate");
+                NoSolution
+            })
+    }
+
+    pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+    ) -> T {
+        self.infcx.instantiate_binder_with_fresh_vars(
+            DUMMY_SP,
+            LateBoundRegionConversionTime::HigherRankedType,
+            value,
+        )
+    }
+
+    pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<'tcx> + Copy>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+    ) -> T {
+        self.infcx.instantiate_binder_with_placeholders(value)
+    }
+
+    pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.infcx.resolve_vars_if_possible(value)
+    }
+
+    pub(super) fn fresh_substs_for_item(&self, def_id: DefId) -> ty::SubstsRef<'tcx> {
+        self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
+    }
+
+    pub(super) fn universe(&self) -> ty::UniverseIndex {
+        self.infcx.universe()
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/infcx_ext.rs b/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
deleted file mode 100644
index 06570e1f4b4..00000000000
--- a/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc_infer::traits::query::NoSolution;
-use rustc_infer::traits::ObligationCause;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::ty::{self, Ty, TypeFoldable};
-use rustc_span::DUMMY_SP;
-
-use super::Goal;
-
-/// Methods used inside of the canonical queries of the solver.
-///
-/// Most notably these do not care about diagnostics information.
-/// If you find this while looking for methods to use outside of the
-/// solver, you may look at the implementation of these method for
-/// help.
-pub(super) trait InferCtxtExt<'tcx> {
-    fn next_ty_infer(&self) -> Ty<'tcx>;
-    fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx>;
-
-    fn eq<T: ToTrace<'tcx>>(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        lhs: T,
-        rhs: T,
-    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>;
-
-    fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
-        &self,
-        value: ty::Binder<'tcx, T>,
-    ) -> T;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
-    fn next_ty_infer(&self) -> Ty<'tcx> {
-        self.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::MiscVariable,
-            span: DUMMY_SP,
-        })
-    }
-    fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        self.next_const_var(
-            ty,
-            ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
-        )
-    }
-
-    #[instrument(level = "debug", skip(self, param_env), ret)]
-    fn eq<T: ToTrace<'tcx>>(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        lhs: T,
-        rhs: T,
-    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
-        self.at(&ObligationCause::dummy(), param_env)
-            .eq(lhs, rhs)
-            .map(|InferOk { value: (), obligations }| {
-                obligations.into_iter().map(|o| o.into()).collect()
-            })
-            .map_err(|e| {
-                debug!(?e, "failed to equate");
-                NoSolution
-            })
-    }
-
-    fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
-        &self,
-        value: ty::Binder<'tcx, T>,
-    ) -> T {
-        self.instantiate_binder_with_fresh_vars(
-            DUMMY_SP,
-            LateBoundRegionConversionTime::HigherRankedType,
-            value,
-        )
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 6890811fd04..c080f7e59fa 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -35,16 +35,15 @@ use crate::solve::search_graph::OverflowHandler;
 use crate::traits::ObligationCause;
 
 mod assembly;
+mod eval_ctxt;
 mod fulfill;
-mod infcx_ext;
 mod project_goals;
 mod search_graph;
 mod trait_goals;
 
+pub use eval_ctxt::EvalCtxt;
 pub use fulfill::FulfillmentCtxt;
 
-use self::infcx_ext::InferCtxtExt;
-
 /// A goal is a statement, i.e. `predicate`, we want to prove
 /// given some assumptions, i.e. `param_env`.
 ///
@@ -180,22 +179,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
     }
 }
 
-struct EvalCtxt<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
-    var_values: CanonicalVarValues<'tcx>,
-
-    search_graph: &'a mut search_graph::SearchGraph<'tcx>,
-
-    /// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
-    /// see the comment in that method for more details.
-    in_projection_eq_hack: bool,
-}
-
 impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
     /// The entry point of the solver.
     ///
     /// This function deals with (coinductive) cycles, overflow, and caching
@@ -427,7 +411,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
         let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| {
             debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other);
-            let r = ecx.infcx.probe(|_| {
+            let r = ecx.probe(|ecx| {
                 let (_, certainty) = ecx.evaluate_goal(goal.with(
                     tcx,
                     ty::Binder::dummy(ty::ProjectionPredicate {
@@ -462,10 +446,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 // Evaluate all 3 potential candidates for the alias' being equal
                 candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1));
                 candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0));
-                candidates.push(self.infcx.probe(|_| {
+                candidates.push(self.probe(|this| {
                     debug!("compute_alias_eq_goal: alias defids are equal, equating substs");
-                    let nested_goals = self.infcx.eq(goal.param_env, alias_lhs, alias_rhs)?;
-                    self.evaluate_all_and_make_canonical_response(nested_goals)
+                    let nested_goals = this.eq(goal.param_env, alias_lhs, alias_rhs)?;
+                    this.evaluate_all_and_make_canonical_response(nested_goals)
                 }));
 
                 debug!(?candidates);
@@ -481,7 +465,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
     ) -> QueryResult<'tcx> {
         let (ct, ty) = goal.predicate;
-        let nested_goals = self.infcx.eq(goal.param_env, ct.ty(), ty)?;
+        let nested_goals = self.eq(goal.param_env, ct.ty(), ty)?;
         self.evaluate_all_and_make_canonical_response(nested_goals)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 48153b465b7..9f83bfa1ccb 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -1,7 +1,6 @@
 use crate::traits::{specialization_graph, translate_substs};
 
 use super::assembly;
-use super::infcx_ext::InferCtxtExt;
 use super::trait_goals::structural_traits;
 use super::{Certainty, EvalCtxt, Goal, QueryResult};
 use rustc_errors::ErrorGuaranteed;
@@ -13,12 +12,11 @@ use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::specialization_graph::LeafDef;
 use rustc_infer::traits::Reveal;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::ProjectionPredicate;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ir::TypeVisitor, ProjectionPredicate, TypeSuperVisitable};
 use rustc_middle::ty::{ToPredicate, TypeVisitable};
 use rustc_span::{sym, DUMMY_SP};
 use std::iter;
-use std::ops::ControlFlow;
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
     pub(super) fn compute_projection_goal(
@@ -38,8 +36,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         } else {
             let predicate = goal.predicate;
             let unconstrained_rhs = match predicate.term.unpack() {
-                ty::TermKind::Ty(_) => self.infcx.next_ty_infer().into(),
-                ty::TermKind::Const(ct) => self.infcx.next_const_infer(ct.ty()).into(),
+                ty::TermKind::Ty(_) => self.next_ty_infer().into(),
+                ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
             };
             let unconstrained_predicate = ty::Clause::Projection(ProjectionPredicate {
                 projection_ty: goal.predicate.projection_ty,
@@ -49,8 +47,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 this.evaluate_goal(goal.with(this.tcx(), unconstrained_predicate))
             })?;
 
-            let nested_eq_goals =
-                self.infcx.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
+            let nested_eq_goals = self.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
             let eval_certainty = self.evaluate_all(nested_eq_goals)?;
             self.make_canonical_response(normalize_certainty.unify_and(eval_certainty))
         }
@@ -65,73 +62,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         result
     }
 
-    /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
-    ///
-    /// This is the case if the `term` is an inference variable in the innermost universe
-    /// and does not occur in any other part of the predicate.
-    fn term_is_fully_unconstrained(&self, goal: Goal<'tcx, ProjectionPredicate<'tcx>>) -> bool {
-        let infcx = self.infcx;
-        let term_is_infer = match goal.predicate.term.unpack() {
-            ty::TermKind::Ty(ty) => {
-                if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
-                    match infcx.probe_ty_var(vid) {
-                        Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
-                        Err(universe) => universe == infcx.universe(),
-                    }
-                } else {
-                    false
-                }
-            }
-            ty::TermKind::Const(ct) => {
-                if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
-                    match self.infcx.probe_const_var(vid) {
-                        Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
-                        Err(universe) => universe == infcx.universe(),
-                    }
-                } else {
-                    false
-                }
-            }
-        };
-
-        // Guard against `<T as Trait<?0>>::Assoc = ?0>`.
-        struct ContainsTerm<'tcx> {
-            term: ty::Term<'tcx>,
-        }
-        impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
-            type BreakTy = ();
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                if t.needs_infer() {
-                    if ty::Term::from(t) == self.term {
-                        ControlFlow::Break(())
-                    } else {
-                        t.super_visit_with(self)
-                    }
-                } else {
-                    ControlFlow::Continue(())
-                }
-            }
-
-            fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-                if c.needs_infer() {
-                    if ty::Term::from(c) == self.term {
-                        ControlFlow::Break(())
-                    } else {
-                        c.super_visit_with(self)
-                    }
-                } else {
-                    ControlFlow::Continue(())
-                }
-            }
-        }
-
-        let mut visitor = ContainsTerm { term: goal.predicate.term };
-
-        term_is_infer
-            && goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
-            && goal.param_env.visit_with(&mut visitor).is_continue()
-    }
-
     /// After normalizing the projection to `normalized_alias` with the given
     /// `normalization_certainty`, constrain the inference variable `term` to it
     /// and return a query response.
@@ -145,7 +75,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         //
         // It can however be ambiguous when the `normalized_alias` contains a projection.
         let nested_goals = self
-            .infcx
             .eq(goal.param_env, goal.predicate.term, normalized_alias.into())
             .expect("failed to unify with unconstrained term");
         let rhs_certainty =
@@ -177,10 +106,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
             && poly_projection_pred.projection_def_id() == goal.predicate.def_id()
         {
-            ecx.infcx.probe(|_| {
+            ecx.probe(|ecx| {
                 let assumption_projection_pred =
-                    ecx.infcx.instantiate_binder_with_infer(poly_projection_pred);
-                let mut nested_goals = ecx.infcx.eq(
+                    ecx.instantiate_binder_with_infer(poly_projection_pred);
+                let mut nested_goals = ecx.eq(
                     goal.param_env,
                     goal.predicate.projection_ty,
                     assumption_projection_pred.projection_ty,
@@ -215,11 +144,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        ecx.infcx.probe(|_| {
-            let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+        ecx.probe(|ecx| {
+            let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
             let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
 
-            let mut nested_goals = ecx.infcx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
+            let mut nested_goals = ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
             let where_clause_bounds = tcx
                 .predicates_of(impl_def_id)
                 .instantiate(tcx, impl_substs)
@@ -367,7 +296,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let tcx = ecx.tcx();
-        ecx.infcx.probe(|_| {
+        ecx.probe(|ecx| {
             let metadata_ty = match goal.predicate.self_ty().kind() {
                 ty::Bool
                 | ty::Char
@@ -546,8 +475,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
-        ecx.infcx
-            .probe(|_| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
+        ecx.probe(|ecx| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index f2f25ef850a..6d1381bbf0c 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -3,11 +3,9 @@
 use std::iter;
 
 use super::assembly;
-use super::infcx_ext::InferCtxtExt;
 use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@@ -45,12 +43,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        ecx.infcx.probe(|_| {
-            let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+        ecx.probe(|ecx| {
+            let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
             let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
 
             let mut nested_goals =
-                ecx.infcx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
+                ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
             let where_clause_bounds = tcx
                 .predicates_of(impl_def_id)
                 .instantiate(tcx, impl_substs)
@@ -72,10 +70,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             && poly_trait_pred.def_id() == goal.predicate.def_id()
         {
             // FIXME: Constness and polarity
-            ecx.infcx.probe(|_| {
+            ecx.probe(|ecx| {
                 let assumption_trait_pred =
-                    ecx.infcx.instantiate_binder_with_infer(poly_trait_pred);
-                let mut nested_goals = ecx.infcx.eq(
+                    ecx.instantiate_binder_with_infer(poly_trait_pred);
+                let mut nested_goals = ecx.eq(
                     goal.param_env,
                     goal.predicate.trait_ref,
                     assumption_trait_pred.trait_ref,
@@ -118,7 +116,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     ) -> QueryResult<'tcx> {
         let tcx = ecx.tcx();
 
-        ecx.infcx.probe(|_| {
+        ecx.probe(|ecx| {
             let nested_obligations = tcx
                 .predicates_of(goal.predicate.def_id())
                 .instantiate(tcx, goal.predicate.trait_ref.substs);
@@ -275,7 +273,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         if b_ty.is_ty_var() {
             return ecx.make_canonical_response(Certainty::AMBIGUOUS);
         }
-        ecx.infcx.probe(|_| {
+        ecx.probe(|ecx| {
             match (a_ty.kind(), b_ty.kind()) {
                 // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
                 (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
@@ -318,7 +316,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                 // `[T; n]` -> `[T]` unsizing
                 (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
                     // We just require that the element type stays the same
-                    let nested_goals = ecx.infcx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
+                    let nested_goals = ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
                     ecx.evaluate_all_and_make_canonical_response(nested_goals)
                 }
                 // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
@@ -352,7 +350,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
                     // Finally, we require that `TailA: Unsize<TailB>` for the tail field
                     // types.
-                    let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+                    let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
                     nested_goals.push(goal.with(
                         tcx,
                         ty::Binder::dummy(
@@ -371,7 +369,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
                     // Substitute just the tail field of B., and require that they're equal.
                     let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]).copied());
-                    let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+                    let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
 
                     // Similar to ADTs, require that the rest of the fields are equal.
                     nested_goals.push(goal.with(
@@ -411,7 +409,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         }
 
         let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
-            ecx.infcx.probe(|_| -> Result<_, NoSolution> {
+            ecx.probe(|ecx| -> Result<_, NoSolution> {
                 // Require that all of the trait predicates from A match B, except for
                 // the auto traits. We do this by constructing a new A type with B's
                 // auto traits, and equating these types.
@@ -431,7 +429,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                 let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn);
 
                 // We also require that A's lifetime outlives B's lifetime.
-                let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?;
+                let mut nested_obligations = ecx.eq(goal.param_env, new_a_ty, b_ty)?;
                 nested_obligations.push(
                     goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
                 );
@@ -482,16 +480,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     fn probe_and_evaluate_goal_for_constituent_tys(
         &mut self,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
-        constituent_tys: impl Fn(&InferCtxt<'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
+        constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
     ) -> QueryResult<'tcx> {
-        self.infcx.probe(|_| {
-            self.evaluate_all_and_make_canonical_response(
-                constituent_tys(self.infcx, goal.predicate.self_ty())?
+        self.probe(|this| {
+            this.evaluate_all_and_make_canonical_response(
+                constituent_tys(this, goal.predicate.self_ty())?
                     .into_iter()
                     .map(|ty| {
                         goal.with(
-                            self.tcx(),
-                            ty::Binder::dummy(goal.predicate.with_self_ty(self.tcx(), ty)),
+                            this.tcx(),
+                            ty::Binder::dummy(goal.predicate.with_self_ty(this.tcx(), ty)),
                         )
                     })
                     .collect(),
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 3662463178f..2c13465d347 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -1,16 +1,18 @@
 use rustc_hir::{Movability, Mutability};
-use rustc_infer::{infer::InferCtxt, traits::query::NoSolution};
+use rustc_infer::traits::query::NoSolution;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
+use crate::solve::EvalCtxt;
+
 // Calculates the constituent types of a type for `auto trait` purposes.
 //
 // For types with an "existential" binder, i.e. generator witnesses, we also
 // instantiate the binder with placeholders eagerly.
 pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
-    infcx: &InferCtxt<'tcx>,
+    ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<Ty<'tcx>>, NoSolution> {
-    let tcx = infcx.tcx;
+    let tcx = ecx.tcx();
     match *ty.kind() {
         ty::Uint(_)
         | ty::Int(_)
@@ -53,9 +55,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
             Ok(vec![generator_substs.tupled_upvars_ty(), generator_substs.witness()])
         }
 
-        ty::GeneratorWitness(types) => {
-            Ok(infcx.instantiate_binder_with_placeholders(types).to_vec())
-        }
+        ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
 
         ty::GeneratorWitnessMIR(..) => todo!(),
 
@@ -74,7 +74,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
 }
 
 pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
-    infcx: &InferCtxt<'tcx>,
+    ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<Ty<'tcx>>, NoSolution> {
     match *ty.kind() {
@@ -113,18 +113,18 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
         ty::Tuple(tys) => Ok(tys.to_vec()),
 
         ty::Adt(def, substs) => {
-            let sized_crit = def.sized_constraint(infcx.tcx);
+            let sized_crit = def.sized_constraint(ecx.tcx());
             Ok(sized_crit
                 .0
                 .iter()
-                .map(|ty| sized_crit.rebind(*ty).subst(infcx.tcx, substs))
+                .map(|ty| sized_crit.rebind(*ty).subst(ecx.tcx(), substs))
                 .collect())
         }
     }
 }
 
 pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
-    infcx: &InferCtxt<'tcx>,
+    ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<Ty<'tcx>>, NoSolution> {
     match *ty.kind() {
@@ -165,7 +165,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
         ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]),
 
         ty::Generator(_, substs, Movability::Movable) => {
-            if infcx.tcx.features().generator_clone {
+            if ecx.tcx().features().generator_clone {
                 let generator = substs.as_generator();
                 Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
             } else {
@@ -173,9 +173,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
             }
         }
 
-        ty::GeneratorWitness(types) => {
-            Ok(infcx.instantiate_binder_with_placeholders(types).to_vec())
-        }
+        ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
 
         ty::GeneratorWitnessMIR(..) => todo!(),
     }
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index ab57fba6c9f..66c33d58d6c 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -197,11 +197,6 @@ impl FileDesc {
         }
     }
 
-    #[cfg(target_os = "linux")]
-    pub fn get_cloexec(&self) -> io::Result<bool> {
-        unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
-    }
-
     #[cfg(not(any(
         target_env = "newlib",
         target_os = "solaris",
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 9cd6107b43a..b4f1506dc8f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -435,6 +435,10 @@ impl Step for Rustfmt {
             &[],
         );
 
+        if !builder.fail_fast {
+            cargo.arg("--no-fail-fast");
+        }
+
         let dir = testdir(builder, compiler.host);
         t!(fs::create_dir_all(&dir));
         cargo.env("RUSTFMT_TEST_DIR", dir);
@@ -615,6 +619,10 @@ impl Step for Miri {
         );
         cargo.add_rustc_lib_path(builder, compiler);
 
+        if !builder.fail_fast {
+            cargo.arg("--no-fail-fast");
+        }
+
         // miri tests need to know about the stage sysroot
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
         cargo.env("MIRI_HOST_SYSROOT", sysroot);
@@ -746,6 +754,10 @@ impl Step for Clippy {
             &[],
         );
 
+        if !builder.fail_fast {
+            cargo.arg("--no-fail-fast");
+        }
+
         cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
         cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
         let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0c70d31ed60..5541136ef49 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2114,17 +2114,29 @@ fn get_all_import_attributes<'hir>(
     attributes: &mut Vec<ast::Attribute>,
     is_inline: bool,
 ) {
+    let mut first = true;
     let hir_map = tcx.hir();
     let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
     let mut visited = FxHashSet::default();
+
     // If the item is an import and has at least a path with two parts, we go into it.
     while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
-        // We add the attributes from this import into the list.
-        add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+        if first {
+            // This is the "original" reexport so we get all its attributes without filtering them.
+            attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
+            first = false;
+        } else {
+            add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+        }
 
-        let def_id = if path.segments.len() > 1 {
-            match path.segments[path.segments.len() - 2].res {
+        let def_id = if let [.., parent_segment, _] = &path.segments {
+            match parent_segment.res {
                 hir::def::Res::Def(_, def_id) => def_id,
+                _ if parent_segment.ident.name == kw::Crate => {
+                    // In case the "parent" is the crate, it'll give `Res::Err` so we need to
+                    // circumvent it this way.
+                    tcx.parent(item.owner_id.def_id.to_def_id())
+                }
                 _ => break,
             }
         } else {
@@ -2341,9 +2353,7 @@ fn clean_maybe_renamed_item<'tcx>(
         if let Some(import_id) = import_id &&
             let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id)
         {
-            // First, we add the attributes from the current import.
-            extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id()));
-            let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some();
+            let is_inline = inline::load_attrs(cx, import_id.to_def_id()).lists(sym::doc).get_word_attr(sym::inline).is_some();
             // Then we get all the various imports' attributes.
             get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline);
             add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline);
diff --git a/tests/mir-opt/casts.redundant.InstCombine.diff b/tests/mir-opt/casts.redundant.InstCombine.diff
new file mode 100644
index 00000000000..528a8e5a90f
--- /dev/null
+++ b/tests/mir-opt/casts.redundant.InstCombine.diff
@@ -0,0 +1,25 @@
+- // MIR for `redundant` before InstCombine
++ // MIR for `redundant` after InstCombine
+  
+  fn redundant(_1: *const &u8) -> *const &u8 {
+      debug x => _1;                       // in scope 0 at $DIR/casts.rs:+0:30: +0:31
+      let mut _0: *const &u8;              // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
+      let mut _2: *const &u8;              // in scope 0 at $DIR/casts.rs:+1:5: +1:55
+      let mut _3: *const &u8;              // in scope 0 at $DIR/casts.rs:+1:36: +1:37
+      scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
+          debug x => _3;                   // in scope 1 at $DIR/casts.rs:10:23: 10:24
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/casts.rs:+1:5: +1:55
+          StorageLive(_3);                 // scope 0 at $DIR/casts.rs:+1:36: +1:37
+          _3 = _1;                         // scope 0 at $DIR/casts.rs:+1:36: +1:37
+-         _2 = _3 as *const &u8 (PtrToPtr); // scope 1 at $DIR/casts.rs:11:5: 11:18
++         _2 = _3;                         // scope 1 at $DIR/casts.rs:11:5: 11:18
+          StorageDead(_3);                 // scope 0 at $DIR/casts.rs:+1:37: +1:38
+          _0 = _2;                         // scope 0 at $DIR/casts.rs:+1:5: +1:55
+          StorageDead(_2);                 // scope 0 at $DIR/casts.rs:+2:1: +2:2
+          return;                          // scope 0 at $DIR/casts.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/casts.redundant.PreCodegen.after.mir b/tests/mir-opt/casts.redundant.PreCodegen.after.mir
new file mode 100644
index 00000000000..21a470ea300
--- /dev/null
+++ b/tests/mir-opt/casts.redundant.PreCodegen.after.mir
@@ -0,0 +1,14 @@
+// MIR for `redundant` after PreCodegen
+
+fn redundant(_1: *const &u8) -> *const &u8 {
+    debug x => _1;                       // in scope 0 at $DIR/casts.rs:+0:30: +0:31
+    let mut _0: *const &u8;              // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
+    scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
+        debug x => _1;                   // in scope 1 at $DIR/casts.rs:10:23: 10:24
+    }
+
+    bb0: {
+        _0 = _1;                         // scope 0 at $DIR/casts.rs:+1:5: +1:55
+        return;                          // scope 0 at $DIR/casts.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir
new file mode 100644
index 00000000000..0c793984ceb
--- /dev/null
+++ b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir
@@ -0,0 +1,15 @@
+// MIR for `roundtrip` after PreCodegen
+
+fn roundtrip(_1: *const u8) -> *const u8 {
+    debug x => _1;                       // in scope 0 at $DIR/casts.rs:+0:18: +0:19
+    let mut _0: *const u8;               // return place in scope 0 at $DIR/casts.rs:+0:35: +0:44
+    let mut _2: *mut u8;                 // in scope 0 at $DIR/casts.rs:+1:5: +1:17
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/casts.rs:+1:5: +1:17
+        _2 = _1 as *mut u8 (PtrToPtr);   // scope 0 at $DIR/casts.rs:+1:5: +1:17
+        _0 = move _2 as *const u8 (Pointer(MutToConstPointer)); // scope 0 at $DIR/casts.rs:+1:5: +1:17
+        StorageDead(_2);                 // scope 0 at $DIR/casts.rs:+1:16: +1:17
+        return;                          // scope 0 at $DIR/casts.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/casts.rs b/tests/mir-opt/casts.rs
new file mode 100644
index 00000000000..259c462da3d
--- /dev/null
+++ b/tests/mir-opt/casts.rs
@@ -0,0 +1,17 @@
+#![crate_type = "lib"]
+
+// EMIT_MIR casts.redundant.InstCombine.diff
+// EMIT_MIR casts.redundant.PreCodegen.after.mir
+pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
+    generic_cast::<&'a u8, &'b u8>(x) as *const &'a u8
+}
+
+#[inline]
+fn generic_cast<T, U>(x: *const T) -> *const U {
+    x as *const U
+}
+
+// EMIT_MIR casts.roundtrip.PreCodegen.after.mir
+pub fn roundtrip(x: *const u8) -> *const u8 {
+    x as *mut u8 as *const u8
+}
diff --git a/tests/rustdoc/issue-108281.rs b/tests/rustdoc/issue-108281.rs
new file mode 100644
index 00000000000..8e1b6ba88a6
--- /dev/null
+++ b/tests/rustdoc/issue-108281.rs
@@ -0,0 +1,25 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/108281>.
+// It ensures that the attributes on the first reexport are not duplicated.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+
+#[doc(hidden)]
+pub fn bar() {}
+mod sub {
+    pub fn public() {}
+}
+
+// @matches - '//*[@class="desc docblock-short"]' '^Displayed$'
+/// Displayed
+#[doc(inline)]
+pub use crate::bar as Bar;
+// @matches - '//*[@class="desc docblock-short"]' '^Hello\sDisplayed$'
+#[doc(inline)]
+/// Hello
+pub use crate::Bar as Bar2;
+
+// @matches - '//*[@class="desc docblock-short"]' '^Public$'
+/// Public
+pub use crate::sub::public as Public;
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index d1b9d7a40b4..eb739b149a1 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -7,10 +7,7 @@ LL |   fn oom() -> ! {
    |  _-^^^^^^^^^^^^
 LL | |     loop {}
 LL | | }
-   | | -
-   | | |
-   | |_unexpected argument of type `core::alloc::Layout`
-   |   help: remove the extra argument
+   | |_- unexpected argument of type `core::alloc::Layout`
    |
 note: function defined here
   --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4
diff --git a/tests/ui/argument-suggestions/extra_arguments.rs b/tests/ui/argument-suggestions/extra_arguments.rs
index 3f83de95e2d..1442062326d 100644
--- a/tests/ui/argument-suggestions/extra_arguments.rs
+++ b/tests/ui/argument-suggestions/extra_arguments.rs
@@ -3,8 +3,15 @@ fn one_arg(_a: i32) {}
 fn two_arg_same(_a: i32, _b: i32) {}
 fn two_arg_diff(_a: i32, _b: &str) {}
 
+macro_rules! foo {
+    ($x:expr) => {
+        empty($x, 1); //~ ERROR function takes
+    }
+}
+
 fn main() {
   empty(""); //~ ERROR function takes
+  empty(1, 1); //~ ERROR function takes
 
   one_arg(1, 1); //~ ERROR function takes
   one_arg(1, ""); //~ ERROR function takes
@@ -32,4 +39,5 @@ fn main() {
     1,
     ""
   );
+  foo!(1);
 }
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index 0911685b428..11c71099743 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -1,5 +1,5 @@
 error[E0061]: this function takes 0 arguments but 1 argument was supplied
-  --> $DIR/extra_arguments.rs:7:3
+  --> $DIR/extra_arguments.rs:13:3
    |
 LL |   empty("");
    |   ^^^^^ --
@@ -13,8 +13,27 @@ note: function defined here
 LL | fn empty() {}
    |    ^^^^^
 
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:14:3
+   |
+LL |   empty(1, 1);
+   |   ^^^^^ -  - unexpected argument of type `{integer}`
+   |         |
+   |         unexpected argument of type `{integer}`
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:1:4
+   |
+LL | fn empty() {}
+   |    ^^^^^
+help: remove the extra arguments
+   |
+LL -   empty(1, 1);
+LL +   empty();
+   |
+
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/extra_arguments.rs:9:3
+  --> $DIR/extra_arguments.rs:16:3
    |
 LL |   one_arg(1, 1);
    |   ^^^^^^^  ---
@@ -29,7 +48,7 @@ LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/extra_arguments.rs:10:3
+  --> $DIR/extra_arguments.rs:17:3
    |
 LL |   one_arg(1, "");
    |   ^^^^^^^  ----
@@ -44,7 +63,7 @@ LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
 
 error[E0061]: this function takes 1 argument but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:11:3
+  --> $DIR/extra_arguments.rs:18:3
    |
 LL |   one_arg(1, "", 1.0);
    |   ^^^^^^^    --  --- unexpected argument of type `{float}`
@@ -63,7 +82,7 @@ LL +   one_arg(1);
    |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:13:3
+  --> $DIR/extra_arguments.rs:20:3
    |
 LL |   two_arg_same(1, 1, 1);
    |   ^^^^^^^^^^^^     ---
@@ -78,7 +97,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:14:3
+  --> $DIR/extra_arguments.rs:21:3
    |
 LL |   two_arg_same(1, 1, 1.0);
    |   ^^^^^^^^^^^^     -----
@@ -93,7 +112,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:16:3
+  --> $DIR/extra_arguments.rs:23:3
    |
 LL |   two_arg_diff(1, 1, "");
    |   ^^^^^^^^^^^^  ---
@@ -108,7 +127,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:17:3
+  --> $DIR/extra_arguments.rs:24:3
    |
 LL |   two_arg_diff(1, "", "");
    |   ^^^^^^^^^^^^      ----
@@ -123,7 +142,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
-  --> $DIR/extra_arguments.rs:18:3
+  --> $DIR/extra_arguments.rs:25:3
    |
 LL |   two_arg_diff(1, 1, "", "");
    |   ^^^^^^^^^^^^    -      -- unexpected argument of type `&'static str`
@@ -142,7 +161,7 @@ LL +   two_arg_diff(1, "");
    |
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
-  --> $DIR/extra_arguments.rs:19:3
+  --> $DIR/extra_arguments.rs:26:3
    |
 LL |   two_arg_diff(1, "", 1, "");
    |   ^^^^^^^^^^^^        -  -- unexpected argument of type `&'static str`
@@ -161,7 +180,7 @@ LL +   two_arg_diff(1, "");
    |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:22:3
+  --> $DIR/extra_arguments.rs:29:3
    |
 LL |   two_arg_same(1, 1,     "");
    |   ^^^^^^^^^^^^     --------
@@ -176,7 +195,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:23:3
+  --> $DIR/extra_arguments.rs:30:3
    |
 LL |   two_arg_diff(1, 1,     "");
    |   ^^^^^^^^^^^^  ---
@@ -191,7 +210,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:24:3
+  --> $DIR/extra_arguments.rs:31:3
    |
 LL |     two_arg_same(
    |     ^^^^^^^^^^^^
@@ -211,7 +230,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:30:3
+  --> $DIR/extra_arguments.rs:37:3
    |
 LL |     two_arg_diff(
    |     ^^^^^^^^^^^^
@@ -229,6 +248,26 @@ note: function defined here
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
-error: aborting due to 14 previous errors
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:8:9
+   |
+LL |         empty($x, 1);
+   |         ^^^^^     - unexpected argument of type `{integer}`
+...
+LL |   foo!(1);
+   |   -------
+   |   |    |
+   |   |    unexpected argument of type `{integer}`
+   |   |    help: remove the extra argument
+   |   in this macro invocation
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:1:4
+   |
+LL | fn empty() {}
+   |    ^^^^^
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
index 83655341d6a..83655341d6a 100644
--- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
index baef38f6b80..4246f8c069d 100644
--- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
@@ -1,5 +1,5 @@
 error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:28:7
+  --> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7
    |
 LL | struct S;
    | --------
@@ -12,7 +12,7 @@ LL |     a.f();
    |       ^ method cannot be called on `S` due to unsatisfied trait bounds
    |
 note: trait bound `<S as X>::Y<i32> = i32` was not satisfied
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:12:11
+  --> $DIR/method-unsatisfied-assoc-type-predicate.rs:12:11
    |
 LL | impl<T: X<Y<i32> = i32>> M for T {}
    |           ^^^^^^^^^^^^   -     -
diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs
index 1cc09aa6dd4..060ee8821d8 100644
--- a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs
+++ b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs
@@ -1,3 +1,5 @@
+#![warn(unused_lifetimes)]
+
 pub trait X {
     type Y<'a: 'static>;
     //~^ WARNING unnecessary lifetime parameter
diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr
index fbd79879d0f..a69cd0028c1 100644
--- a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
+++ b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr
@@ -1,45 +1,50 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/unsatified-item-lifetime-bound.rs:2:12
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:4:12
    |
 LL |     type Y<'a: 'static>;
    |            ^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:1:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:11:8
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:13:8
    |
 LL |     f: <T as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'a` as defined here
-  --> $DIR/unsatified-item-lifetime-bound.rs:10:10
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:12:10
    |
 LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
    |          ^^
    = note: but lifetime parameter must outlive the static lifetime
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:16:8
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:18:8
    |
 LL |     f: <T as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'a` as defined here
-  --> $DIR/unsatified-item-lifetime-bound.rs:15:10
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:17:10
    |
 LL | struct C<'a, T: X> {
    |          ^^
    = note: but lifetime parameter must outlive the static lifetime
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/unsatified-item-lifetime-bound.rs:21:8
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:23:8
    |
 LL |     f: <() as X>::Y<'a>,
    |        ^^^^^^^^^^^^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'a` as defined here
-  --> $DIR/unsatified-item-lifetime-bound.rs:20:10
+  --> $DIR/unsatisfied-item-lifetime-bound.rs:22:10
    |
 LL | struct D<'a> {
    |          ^^
diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.rs b/tests/ui/impl-trait/equal-hidden-lifetimes.rs
index 79db88828b9..a6dbf3f08f2 100644
--- a/tests/ui/impl-trait/equal-hidden-lifetimes.rs
+++ b/tests/ui/impl-trait/equal-hidden-lifetimes.rs
@@ -5,7 +5,6 @@
 
 // `'a == 'static` so `&'a i32` is fine as the return type
 fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
-    //~^ WARNING unnecessary lifetime parameter `'a`
     x
 }
 
diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.stderr b/tests/ui/impl-trait/equal-hidden-lifetimes.stderr
deleted file mode 100644
index 3e48aef553b..00000000000
--- a/tests/ui/impl-trait/equal-hidden-lifetimes.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/equal-hidden-lifetimes.rs:7:25
-   |
-LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
-   |                         ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/infinite/auxiliary/alias.rs b/tests/ui/infinite/auxiliary/alias.rs
new file mode 100644
index 00000000000..59add7eb18b
--- /dev/null
+++ b/tests/ui/infinite/auxiliary/alias.rs
@@ -0,0 +1,2 @@
+pub struct W<T>(T);
+pub type Wrapper<T> = W<T>;
diff --git a/tests/ui/infinite/infinite-alias.rs b/tests/ui/infinite/infinite-alias.rs
new file mode 100644
index 00000000000..45356f359ce
--- /dev/null
+++ b/tests/ui/infinite/infinite-alias.rs
@@ -0,0 +1,9 @@
+// aux-build: alias.rs
+// regression test for 108160
+
+extern crate alias;
+
+use alias::Wrapper;
+struct Rec(Wrapper<Rec>); //~ ERROR recursive type `Rec` has infinite
+
+fn main() {}
diff --git a/tests/ui/infinite/infinite-alias.stderr b/tests/ui/infinite/infinite-alias.stderr
new file mode 100644
index 00000000000..9d9265f8c36
--- /dev/null
+++ b/tests/ui/infinite/infinite-alias.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `Rec` has infinite size
+  --> $DIR/infinite-alias.rs:7:1
+   |
+LL | struct Rec(Wrapper<Rec>);
+   | ^^^^^^^^^^ ------------ recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL | struct Rec(Box<Wrapper<Rec>>);
+   |            ++++            +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/issues/issue-26094.rs b/tests/ui/issues/issue-26094.rs
index abf3543ddb9..2742529edd3 100644
--- a/tests/ui/issues/issue-26094.rs
+++ b/tests/ui/issues/issue-26094.rs
@@ -1,7 +1,7 @@
 macro_rules! some_macro {
-    ($other: expr) => ({
+    ($other: expr) => {{
         $other(None) //~ NOTE unexpected argument of type `Option<_>`
-    })
+    }};
 }
 
 fn some_function() {} //~ NOTE defined here
@@ -9,5 +9,4 @@ fn some_function() {} //~ NOTE defined here
 fn main() {
     some_macro!(some_function);
     //~^ ERROR function takes 0 arguments but 1 argument was supplied
-    //~| NOTE in this expansion of some_macro!
 }
diff --git a/tests/ui/issues/issue-26094.stderr b/tests/ui/issues/issue-26094.stderr
index 608d2c7aff9..ecdf48470f7 100644
--- a/tests/ui/issues/issue-26094.stderr
+++ b/tests/ui/issues/issue-26094.stderr
@@ -2,10 +2,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-26094.rs:10:17
    |
 LL |         $other(None)
-   |                ----
-   |                |
-   |                unexpected argument of type `Option<_>`
-   |                help: remove the extra argument
+   |                ---- unexpected argument of type `Option<_>`
 ...
 LL |     some_macro!(some_function);
    |                 ^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-30438-c.rs b/tests/ui/issues/issue-30438-c.rs
index 4cf634245be..813c1d3e2cc 100644
--- a/tests/ui/issues/issue-30438-c.rs
+++ b/tests/ui/issues/issue-30438-c.rs
@@ -5,7 +5,6 @@ trait Trait { type Out; }
 struct Test<'a> { s: &'a str }
 
 fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
-    //~^ WARN unnecessary lifetime parameter `'z`
     let x = Test { s: "this cannot last" };
     &x
     //~^ ERROR: cannot return reference to local variable `x`
diff --git a/tests/ui/issues/issue-30438-c.stderr b/tests/ui/issues/issue-30438-c.stderr
index a7a5c0500fd..7c001088097 100644
--- a/tests/ui/issues/issue-30438-c.stderr
+++ b/tests/ui/issues/issue-30438-c.stderr
@@ -1,17 +1,9 @@
-warning: unnecessary lifetime parameter `'z`
-  --> $DIR/issue-30438-c.rs:7:74
-   |
-LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
-   |                                                                          ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'z`
-
 error[E0515]: cannot return reference to local variable `x`
-  --> $DIR/issue-30438-c.rs:10:5
+  --> $DIR/issue-30438-c.rs:9:5
    |
 LL |     &x
    |     ^^ returns a reference to data owned by the current function
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
index 7c2e1aeeea6..46462c432a8 100644
--- a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
+++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
@@ -8,6 +8,8 @@
 //
 //     'a : 'b
 
+#![warn(unused_lifetimes)]
+
 fn test<'a,'b>(x: &'a i32) -> &'b i32
     where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
 {
diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
index 70ed418d5cb..9f03a6553ba 100644
--- a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
+++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
@@ -1,10 +1,15 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11
+  --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:14:11
    |
 LL |     where 'a: 'static
    |           ^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+  --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:11:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/regions/regions-static-bound-rpass.rs b/tests/ui/regions/regions-static-bound-rpass.rs
index 25232b455b6..e2ebb394d0a 100644
--- a/tests/ui/regions/regions-static-bound-rpass.rs
+++ b/tests/ui/regions/regions-static-bound-rpass.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![warn(unused_lifetimes)]
+
 fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
     where 'a: 'static { t }
 //~^ WARN unnecessary lifetime parameter `'a`
diff --git a/tests/ui/regions/regions-static-bound-rpass.stderr b/tests/ui/regions/regions-static-bound-rpass.stderr
index 9355a409d50..f0f3a4c5261 100644
--- a/tests/ui/regions/regions-static-bound-rpass.stderr
+++ b/tests/ui/regions/regions-static-bound-rpass.stderr
@@ -1,13 +1,18 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/regions-static-bound-rpass.rs:4:11
+  --> $DIR/regions-static-bound-rpass.rs:6:11
    |
 LL |     where 'a: 'static { t }
    |           ^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+  --> $DIR/regions-static-bound-rpass.rs:3:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
 
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/regions-static-bound-rpass.rs:8:11
+  --> $DIR/regions-static-bound-rpass.rs:10:11
    |
 LL |     where 'a: 'static { t }
    |           ^^
@@ -15,7 +20,7 @@ LL |     where 'a: 'static { t }
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: unnecessary lifetime parameter `'b`
-  --> $DIR/regions-static-bound-rpass.rs:12:19
+  --> $DIR/regions-static-bound-rpass.rs:14:19
    |
 LL |     where 'a: 'b, 'b: 'static { t }
    |                   ^^
diff --git a/tests/ui/regions/regions-static-bound.rs b/tests/ui/regions/regions-static-bound.rs
index 4d2455470e2..e7aa8795f01 100644
--- a/tests/ui/regions/regions-static-bound.rs
+++ b/tests/ui/regions/regions-static-bound.rs
@@ -1,6 +1,8 @@
-fn static_id<'a,'b>(t: &'a ()) -> &'static ()
-    where 'a: 'static { t }
-//~^ WARN unnecessary lifetime parameter `'a`
+#![warn(unused_lifetimes)]
+
+fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+//~^ WARN lifetime parameter `'b` never used
+//~| WARN unnecessary lifetime parameter `'a`
 
 fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'b, 'b: 'static { t }
diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr
index 2886ec3ead5..b314e9fe85d 100644
--- a/tests/ui/regions/regions-static-bound.stderr
+++ b/tests/ui/regions/regions-static-bound.stderr
@@ -1,13 +1,27 @@
+warning: lifetime parameter `'b` never used
+  --> $DIR/regions-static-bound.rs:3:17
+   |
+LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+   |                -^^
+   |                |
+   |                help: elide the unused lifetime
+   |
+note: the lint level is defined here
+  --> $DIR/regions-static-bound.rs:1:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/regions-static-bound.rs:2:11
+  --> $DIR/regions-static-bound.rs:3:53
    |
-LL |     where 'a: 'static { t }
-   |           ^^
+LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+   |                                                     ^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: unnecessary lifetime parameter `'b`
-  --> $DIR/regions-static-bound.rs:6:19
+  --> $DIR/regions-static-bound.rs:8:19
    |
 LL |     where 'a: 'b, 'b: 'static { t }
    |                   ^^
@@ -15,7 +29,7 @@ LL |     where 'a: 'b, 'b: 'static { t }
    = help: you can use the `'static` lifetime directly, in place of `'b`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-static-bound.rs:10:5
+  --> $DIR/regions-static-bound.rs:12:5
    |
 LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
    |                        -- lifetime `'a` defined here
@@ -23,7 +37,7 @@ LL |     t
    |     ^ returning this value requires that `'a` must outlive `'static`
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/regions-static-bound.rs:15:5
+  --> $DIR/regions-static-bound.rs:17:5
    |
 LL | fn error(u: &(), v: &()) {
    |          -  - let's call the lifetime of this reference `'1`
@@ -36,7 +50,7 @@ LL |     static_id(&u);
    |     argument requires that `'1` must outlive `'static`
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/regions-static-bound.rs:17:5
+  --> $DIR/regions-static-bound.rs:19:5
    |
 LL | fn error(u: &(), v: &()) {
    |                  -  - let's call the lifetime of this reference `'2`
@@ -49,6 +63,6 @@ LL |     static_id_indirect(&v);
    |     `v` escapes the function body here
    |     argument requires that `'2` must outlive `'static`
 
-error: aborting due to 3 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 3 warnings emitted
 
 For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/static/static-lifetime-bound.rs b/tests/ui/static/static-lifetime-bound.rs
index b5da91ec3b6..847fe87b2ea 100644
--- a/tests/ui/static/static-lifetime-bound.rs
+++ b/tests/ui/static/static-lifetime-bound.rs
@@ -1,4 +1,4 @@
-fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
+fn f<'a: 'static>(_: &'a i32) {}
 
 fn main() {
     let x = 0;
diff --git a/tests/ui/static/static-lifetime-bound.stderr b/tests/ui/static/static-lifetime-bound.stderr
index e22411b13b7..19e55a6582e 100644
--- a/tests/ui/static/static-lifetime-bound.stderr
+++ b/tests/ui/static/static-lifetime-bound.stderr
@@ -1,11 +1,3 @@
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/static-lifetime-bound.rs:1:6
-   |
-LL | fn f<'a: 'static>(_: &'a i32) {}
-   |      ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
 error[E0597]: `x` does not live long enough
   --> $DIR/static-lifetime-bound.rs:5:7
    |
@@ -19,6 +11,6 @@ LL |     f(&x);
 LL | }
    | - `x` dropped here while still borrowed
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
index eeb5dca07f0..7c3a3a84406 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
@@ -6,7 +6,6 @@
 type X<'a> = impl Into<&'static str> + From<&'a str>;
 
 fn f<'a: 'static>(t: &'a str) -> X<'a> {
-    //~^ WARNING unnecessary lifetime parameter
     t
     //~^ ERROR expected generic lifetime parameter, found `'static`
 }
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
index 94882597a62..962dedde09a 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
@@ -1,13 +1,5 @@
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/bounds-are-checked.rs:8:6
-   |
-LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
-   |      ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
 error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/bounds-are-checked.rs:10:5
+  --> $DIR/bounds-are-checked.rs:9:5
    |
 LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
    |        -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -15,6 +7,6 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
 LL |     t
    |     ^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
index 07f825aea50..6f9434255a8 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
@@ -4,7 +4,6 @@ mod test_lifetime_param {
     type Ty<'a> = impl Sized + 'a;
     fn defining(a: &str) -> Ty<'_> { a }
     fn assert_static<'a: 'static>() {}
-    //~^ WARN: unnecessary lifetime parameter `'a`
     fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
     //~^ ERROR: lifetime may not live long enough
 }
@@ -13,14 +12,12 @@ mod test_higher_kinded_lifetime_param {
     type Ty<'a> = impl Sized + 'a;
     fn defining(a: &str) -> Ty<'_> { a }
     fn assert_static<'a: 'static>() {}
-    //~^ WARN: unnecessary lifetime parameter `'a`
     fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
     //~^ ERROR: lifetime may not live long enough
 }
 
 mod test_higher_kinded_lifetime_param2 {
     fn assert_static<'a: 'static>() {}
-    //~^ WARN: unnecessary lifetime parameter `'a`
     fn test<'a>() { assert_static::<'a>() }
     //~^ ERROR: lifetime may not live long enough
 }
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
index 887620a4d50..399775641f8 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
@@ -1,41 +1,17 @@
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/implied_lifetime_wf_check3.rs:6:22
-   |
-LL |     fn assert_static<'a: 'static>() {}
-   |                      ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/implied_lifetime_wf_check3.rs:15:22
-   |
-LL |     fn assert_static<'a: 'static>() {}
-   |                      ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: unnecessary lifetime parameter `'a`
-  --> $DIR/implied_lifetime_wf_check3.rs:22:22
-   |
-LL |     fn assert_static<'a: 'static>() {}
-   |                      ^^
-   |
-   = help: you can use the `'static` lifetime directly, in place of `'a`
-
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:8:43
+  --> $DIR/implied_lifetime_wf_check3.rs:7:43
    |
 LL |     fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
    |             -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:17:46
+  --> $DIR/implied_lifetime_wf_check3.rs:15:46
    |
 LL |     fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
    |             -- lifetime `'a` defined here    ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:24:21
+  --> $DIR/implied_lifetime_wf_check3.rs:21:21
    |
 LL |     fn test<'a>() { assert_static::<'a>() }
    |             --      ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
@@ -43,7 +19,7 @@ LL |     fn test<'a>() { assert_static::<'a>() }
    |             lifetime `'a` defined here
 
 error[E0310]: the parameter type `A` may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:32:41
+  --> $DIR/implied_lifetime_wf_check3.rs:29:41
    |
 LL |     fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
    |                                         ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
@@ -53,6 +29,6 @@ help: consider adding an explicit lifetime bound...
 LL |     fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
    |              +++++++++
 
-error: aborting due to 4 previous errors; 3 warnings emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0310`.