about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-02-05 19:53:46 -0800
committerGitHub <noreply@github.com>2025-02-05 19:53:46 -0800
commitb9bacc4da5541c2092a878e344943c8325e716a4 (patch)
tree423dcad9736548399e535d18e05e1f2154bb6cd8
parentcc0f3efe7b096bddf2f3f7f81b40678782bcecc8 (diff)
parent4e763c22976cf00e28d94c0f5af455c21327d1b8 (diff)
downloadrust-b9bacc4da5541c2092a878e344943c8325e716a4.tar.gz
rust-b9bacc4da5541c2092a878e344943c8325e716a4.zip
Rollup merge of #136269 - compiler-errors:spanned, r=lcnr
Pass spans around new solver

...so that when we instantiate canonical responses, we can actually have region obligations with the right span.

Within the solver itself, we still use dummy spans everywhere.
-rw-r--r--compiler/rustc_infer/src/infer/at.rs23
-rw-r--r--compiler/rustc_infer/src/infer/context.rs14
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs10
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs27
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs46
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs17
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs9
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs3
-rw-r--r--compiler/rustc_type_ir/src/relate/solver_relating.rs24
-rw-r--r--tests/ui/traits/next-solver/specialization-transmute.rs2
-rw-r--r--tests/ui/traits/next-solver/specialization-transmute.stderr8
-rw-r--r--tests/ui/traits/next-solver/unsound-region-obligation.rs2
-rw-r--r--tests/ui/traits/next-solver/unsound-region-obligation.stderr4
16 files changed, 139 insertions, 61 deletions
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index ad15b764bcc..2cd67cc4da2 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -137,6 +137,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
                 expected,
                 ty::Contravariant,
                 actual,
+                self.cause.span,
             )
             .map(|goals| self.goals_to_obligations(goals))
         } else {
@@ -163,8 +164,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
         T: ToTrace<'tcx>,
     {
         if self.infcx.next_trait_solver {
-            NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual)
-                .map(|goals| self.goals_to_obligations(goals))
+            NextSolverRelate::relate(
+                self.infcx,
+                self.param_env,
+                expected,
+                ty::Covariant,
+                actual,
+                self.cause.span,
+            )
+            .map(|goals| self.goals_to_obligations(goals))
         } else {
             let mut op = TypeRelating::new(
                 self.infcx,
@@ -208,8 +216,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
         T: Relate<TyCtxt<'tcx>>,
     {
         if self.infcx.next_trait_solver {
-            NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual)
-                .map(|goals| self.goals_to_obligations(goals))
+            NextSolverRelate::relate(
+                self.infcx,
+                self.param_env,
+                expected,
+                ty::Invariant,
+                actual,
+                self.cause.span,
+            )
+            .map(|goals| self.goals_to_obligations(goals))
         } else {
             let mut op = TypeRelating::new(
                 self.infcx,
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 69ab0e69e21..eae69ec3e0f 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -5,7 +5,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::{DUMMY_SP, ErrorGuaranteed};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
 
 use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
 
@@ -203,23 +203,23 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.probe(|_| probe())
     }
 
-    fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
+    fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, span: Span) {
         self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
-            SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
+            SubregionOrigin::RelateRegionParamBound(span, None),
             sub,
             sup,
         );
     }
 
-    fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) {
+    fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) {
         self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
-            SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
+            SubregionOrigin::RelateRegionParamBound(span, None),
             a,
             b,
         );
     }
 
-    fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
-        self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy());
+    fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
+        self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 2d2d50e62f9..a64941cce3a 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -4,15 +4,13 @@ use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
 use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
 
-pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized {
-    type Infcx: InferCtxtLike<Interner = <Self as SolverDelegate>::Interner>;
+pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
+    type Infcx: InferCtxtLike<Interner = Self::Interner>;
     type Interner: Interner;
     fn cx(&self) -> Self::Interner {
         (**self).cx()
     }
 
-    type Span: Copy;
-
     fn build_with_canonical<V>(
         cx: Self::Interner,
         canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
@@ -23,7 +21,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
     fn fresh_var_for_kind_with_span(
         &self,
         arg: <Self::Interner as Interner>::GenericArg,
-        span: Self::Span,
+        span: <Self::Interner as Interner>::Span,
     ) -> <Self::Interner as Interner>::GenericArg;
 
     // FIXME: Uplift the leak check into this crate.
@@ -61,6 +59,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
     fn instantiate_canonical_var_with_infer(
         &self,
         cv_info: ty::CanonicalVarInfo<Self::Interner>,
+        span: <Self::Interner as Interner>::Span,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> <Self::Interner as Interner>::GenericArg;
 
@@ -86,6 +85,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
         &self,
         key: ty::OpaqueTypeKey<Self::Interner>,
         hidden_ty: <Self::Interner as Interner>::Ty,
+        span: <Self::Interner as Interner>::Span,
     );
 
     fn reset_opaque_types(&self);
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index e99cd3d2727..39e365806cb 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -255,20 +255,29 @@ where
             self.delegate,
             &original_values,
             &response,
+            self.origin_span,
         );
 
         let Response { var_values, external_constraints, certainty } =
             self.delegate.instantiate_canonical(response, instantiation);
 
-        Self::unify_query_var_values(self.delegate, param_env, &original_values, var_values);
+        Self::unify_query_var_values(
+            self.delegate,
+            param_env,
+            &original_values,
+            var_values,
+            self.origin_span,
+        );
 
         let ExternalConstraintsData {
             region_constraints,
             opaque_types,
             normalization_nested_goals,
         } = &*external_constraints;
+
         self.register_region_constraints(region_constraints);
         self.register_new_opaque_types(opaque_types);
+
         (normalization_nested_goals.clone(), certainty)
     }
 
@@ -279,6 +288,7 @@ where
         delegate: &D,
         original_values: &[I::GenericArg],
         response: &Canonical<I, T>,
+        span: I::Span,
     ) -> CanonicalVarValues<I> {
         // FIXME: Longterm canonical queries should deal with all placeholders
         // created inside of the query directly instead of returning them to the
@@ -331,7 +341,7 @@ where
                     // A variable from inside a binder of the query. While ideally these shouldn't
                     // exist at all (see the FIXME at the start of this method), we have to deal with
                     // them for now.
-                    delegate.instantiate_canonical_var_with_infer(info, |idx| {
+                    delegate.instantiate_canonical_var_with_infer(info, span, |idx| {
                         ty::UniverseIndex::from(prev_universe.index() + idx.index())
                     })
                 } else if info.is_existential() {
@@ -345,7 +355,7 @@ where
                     if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] {
                         v
                     } else {
-                        delegate.instantiate_canonical_var_with_infer(info, |_| prev_universe)
+                        delegate.instantiate_canonical_var_with_infer(info, span, |_| prev_universe)
                     }
                 } else {
                     // For placeholders which were already part of the input, we simply map this
@@ -376,12 +386,13 @@ where
         param_env: I::ParamEnv,
         original_values: &[I::GenericArg],
         var_values: CanonicalVarValues<I>,
+        span: I::Span,
     ) {
         assert_eq!(original_values.len(), var_values.len());
 
         for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
             let goals =
-                delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap();
+                delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap();
             assert!(goals.is_empty());
         }
     }
@@ -401,7 +412,7 @@ where
 
     fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
         for &(key, ty) in opaque_types {
-            self.delegate.inject_new_hidden_type_unchecked(key, ty);
+            self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span);
         }
     }
 }
@@ -431,7 +442,7 @@ where
 // `rustc_trait_selection::solve::inspect::analyse`.
 pub fn instantiate_canonical_state<D, I, T: TypeFoldable<I>>(
     delegate: &D,
-    span: D::Span,
+    span: I::Span,
     param_env: I::ParamEnv,
     orig_values: &mut Vec<I::GenericArg>,
     state: inspect::CanonicalState<I, T>,
@@ -451,10 +462,10 @@ where
     }
 
     let instantiation =
-        EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state);
+        EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state, span);
 
     let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation);
 
-    EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values);
+    EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values, span);
     data
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 91ad24bff67..48a05488148 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -78,6 +78,8 @@ where
 
     nested_goals: NestedGoals<I>,
 
+    pub(super) origin_span: I::Span,
+
     // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
     //
     // If so, then it can no longer be used to make a canonical query response,
@@ -134,6 +136,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
         &self,
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
         generate_proof_tree: GenerateProofTree,
+        span: <Self::Interner as Interner>::Span,
     ) -> (
         Result<(HasChanged, Certainty), NoSolution>,
         Option<inspect::GoalEvaluation<Self::Interner>>,
@@ -174,8 +177,9 @@ where
         &self,
         goal: Goal<I, I::Predicate>,
         generate_proof_tree: GenerateProofTree,
+        span: I::Span,
     ) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
-        EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
+        EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
             ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
         })
     }
@@ -186,7 +190,7 @@ where
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
     ) -> bool {
         self.probe(|| {
-            EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| {
+            EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| {
                 ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
             })
             .0
@@ -203,9 +207,13 @@ where
         Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
         Option<inspect::GoalEvaluation<I>>,
     ) {
-        EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
-            ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
-        })
+        EvalCtxt::enter_root(
+            self,
+            self.cx().recursion_limit(),
+            generate_proof_tree,
+            I::Span::dummy(),
+            |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal),
+        )
     }
 }
 
@@ -229,6 +237,7 @@ where
         delegate: &D,
         root_depth: usize,
         generate_proof_tree: GenerateProofTree,
+        origin_span: I::Span,
         f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
     ) -> (R, Option<inspect::GoalEvaluation<I>>) {
         let mut search_graph = SearchGraph::new(root_depth);
@@ -248,6 +257,7 @@ where
             variables: Default::default(),
             var_values: CanonicalVarValues::dummy(),
             is_normalizes_to_goal: false,
+            origin_span,
             tainted: Ok(()),
         };
         let result = f(&mut ecx);
@@ -289,12 +299,13 @@ where
             max_input_universe: canonical_input.canonical.max_universe,
             search_graph,
             nested_goals: NestedGoals::new(),
+            origin_span: I::Span::dummy(),
             tainted: Ok(()),
             inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
         };
 
         for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
-            ecx.delegate.inject_new_hidden_type_unchecked(key, ty);
+            ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
         }
 
         if !ecx.nested_goals.is_empty() {
@@ -822,8 +833,12 @@ where
             let identity_args = self.fresh_args_for_item(alias.def_id);
             let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
             let ctor_term = rigid_ctor.to_term(cx);
-            let obligations =
-                self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
+            let obligations = self.delegate.eq_structurally_relating_aliases(
+                param_env,
+                term,
+                ctor_term,
+                self.origin_span,
+            )?;
             debug_assert!(obligations.is_empty());
             self.relate(param_env, alias, variance, rigid_ctor)
         } else {
@@ -841,7 +856,12 @@ where
         lhs: T,
         rhs: T,
     ) -> Result<(), NoSolution> {
-        let result = self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs)?;
+        let result = self.delegate.eq_structurally_relating_aliases(
+            param_env,
+            lhs,
+            rhs,
+            self.origin_span,
+        )?;
         assert_eq!(result, vec![]);
         Ok(())
     }
@@ -864,7 +884,7 @@ where
         variance: ty::Variance,
         rhs: T,
     ) -> Result<(), NoSolution> {
-        let goals = self.delegate.relate(param_env, lhs, variance, rhs)?;
+        let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
         self.add_goals(GoalSource::Misc, goals);
         Ok(())
     }
@@ -881,7 +901,7 @@ where
         lhs: T,
         rhs: T,
     ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
-        Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?)
+        Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
     }
 
     pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
@@ -917,12 +937,12 @@ where
     }
 
     pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
-        self.delegate.register_ty_outlives(ty, lt);
+        self.delegate.register_ty_outlives(ty, lt, self.origin_span);
     }
 
     pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
         // `b : a` ==> `a <= b`
-        self.delegate.sub_regions(b, a);
+        self.delegate.sub_regions(b, a, self.origin_span);
     }
 
     /// Computes the list of goals required for `arg` to be well-formed
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
index be69a6e84ea..add96a1fdf7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
@@ -39,6 +39,7 @@ where
             max_input_universe,
             search_graph: outer_ecx.search_graph,
             nested_goals: outer_ecx.nested_goals.clone(),
+            origin_span: outer_ecx.origin_span,
             tainted: outer_ecx.tainted,
             inspect: outer_ecx.inspect.take_and_enter_probe(),
         };
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index abb79493432..58d8a3a6254 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -43,8 +43,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         self.0.tcx
     }
 
-    type Span = Span;
-
     fn build_with_canonical<V>(
         interner: TyCtxt<'tcx>,
         canonical: &CanonicalQueryInput<'tcx, V>,
@@ -147,9 +145,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     fn instantiate_canonical_var_with_infer(
         &self,
         cv_info: CanonicalVarInfo<'tcx>,
+        span: Span,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> ty::GenericArg<'tcx> {
-        self.0.instantiate_canonical_var(DUMMY_SP, cv_info, universe_map)
+        self.0.instantiate_canonical_var(span, cv_info, universe_map)
     }
 
     fn insert_hidden_type(
@@ -175,11 +174,13 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals);
     }
 
-    fn inject_new_hidden_type_unchecked(&self, key: ty::OpaqueTypeKey<'tcx>, hidden_ty: Ty<'tcx>) {
-        self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType {
-            ty: hidden_ty,
-            span: DUMMY_SP,
-        })
+    fn inject_new_hidden_type_unchecked(
+        &self,
+        key: ty::OpaqueTypeKey<'tcx>,
+        hidden_ty: Ty<'tcx>,
+        span: Span,
+    ) {
+        self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { ty: hidden_ty, span })
     }
 
     fn reset_opaque_types(&self) {
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 0db44eda847..c238e708ab8 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -82,7 +82,7 @@ impl<'tcx> ObligationStorage<'tcx> {
             self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| {
                 let goal = o.clone().into();
                 let result = <&SolverDelegate<'tcx>>::from(infcx)
-                    .evaluate_root_goal(goal, GenerateProofTree::No)
+                    .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span)
                     .0;
                 matches!(result, Ok((HasChanged::Yes, _)))
             }));
@@ -163,7 +163,7 @@ where
             for obligation in self.obligations.unstalled_for_select() {
                 let goal = obligation.clone().into();
                 let result = <&SolverDelegate<'tcx>>::from(infcx)
-                    .evaluate_root_goal(goal, GenerateProofTree::No)
+                    .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
                     .0;
                 self.inspect_evaluated_obligation(infcx, &obligation, &result);
                 let (changed, certainty) = match result {
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index c64bc19835b..8edd623e5d0 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -88,7 +88,11 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
 ) -> FulfillmentError<'tcx> {
     let (code, refine_obligation) = infcx.probe(|_| {
         match <&SolverDelegate<'tcx>>::from(infcx)
-            .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No)
+            .evaluate_root_goal(
+                root_obligation.clone().into(),
+                GenerateProofTree::No,
+                root_obligation.cause.span,
+            )
             .0
         {
             Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => {
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 9ba48cd588f..9f4ee54bd4c 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -238,7 +238,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 // constraints, we get an ICE if we already applied the constraints
                 // from the chosen candidate.
                 let proof_tree = infcx
-                    .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1)
+                    .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span).1)
                     .unwrap();
                 InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
             }
@@ -440,8 +440,11 @@ impl<'tcx> InferCtxt<'tcx> {
         depth: usize,
         visitor: &mut V,
     ) -> V::Result {
-        let (_, proof_tree) =
-            <&SolverDelegate<'tcx>>::from(self).evaluate_root_goal(goal, GenerateProofTree::Yes);
+        let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self).evaluate_root_goal(
+            goal,
+            GenerateProofTree::Yes,
+            visitor.span(),
+        );
         let proof_tree = proof_tree.unwrap();
         visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
     }
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index a892b88c2c6..c9b636132f8 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -201,17 +201,20 @@ pub trait InferCtxtLike: Sized {
         &self,
         sub: <Self::Interner as Interner>::Region,
         sup: <Self::Interner as Interner>::Region,
+        span: <Self::Interner as Interner>::Span,
     );
 
     fn equate_regions(
         &self,
         a: <Self::Interner as Interner>::Region,
         b: <Self::Interner as Interner>::Region,
+        span: <Self::Interner as Interner>::Span,
     );
 
     fn register_ty_outlives(
         &self,
         ty: <Self::Interner as Interner>::Ty,
         r: <Self::Interner as Interner>::Region,
+        span: <Self::Interner as Interner>::Span,
     );
 }
diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs
index ad10ad5af9c..dc2312b2da3 100644
--- a/compiler/rustc_type_ir/src/relate/solver_relating.rs
+++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs
@@ -13,6 +13,7 @@ pub trait RelateExt: InferCtxtLike {
         lhs: T,
         variance: ty::Variance,
         rhs: T,
+        span: <Self::Interner as Interner>::Span,
     ) -> Result<
         Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
         TypeError<Self::Interner>,
@@ -23,6 +24,7 @@ pub trait RelateExt: InferCtxtLike {
         param_env: <Self::Interner as Interner>::ParamEnv,
         lhs: T,
         rhs: T,
+        span: <Self::Interner as Interner>::Span,
     ) -> Result<
         Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
         TypeError<Self::Interner>,
@@ -36,12 +38,13 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
         lhs: T,
         variance: ty::Variance,
         rhs: T,
+        span: <Self::Interner as Interner>::Span,
     ) -> Result<
         Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
         TypeError<Self::Interner>,
     > {
         let mut relate =
-            SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env);
+            SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span);
         relate.relate(lhs, rhs)?;
         Ok(relate.goals)
     }
@@ -51,12 +54,18 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
         param_env: <Self::Interner as Interner>::ParamEnv,
         lhs: T,
         rhs: T,
+        span: <Self::Interner as Interner>::Span,
     ) -> Result<
         Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
         TypeError<Self::Interner>,
     > {
-        let mut relate =
-            SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env);
+        let mut relate = SolverRelating::new(
+            self,
+            StructurallyRelateAliases::Yes,
+            ty::Invariant,
+            param_env,
+            span,
+        );
         relate.relate(lhs, rhs)?;
         Ok(relate.goals)
     }
@@ -68,6 +77,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> {
     // Immutable fields.
     structurally_relate_aliases: StructurallyRelateAliases,
     param_env: I::ParamEnv,
+    span: I::Span,
     // Mutable fields.
     ambient_variance: ty::Variance,
     goals: Vec<Goal<I, I::Predicate>>,
@@ -106,10 +116,12 @@ where
         structurally_relate_aliases: StructurallyRelateAliases,
         ambient_variance: ty::Variance,
         param_env: I::ParamEnv,
+        span: I::Span,
     ) -> Self {
         SolverRelating {
             infcx,
             structurally_relate_aliases,
+            span,
             ambient_variance,
             param_env,
             goals: vec![],
@@ -241,10 +253,10 @@ where
     fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region> {
         match self.ambient_variance {
             // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
-            ty::Covariant => self.infcx.sub_regions(b, a),
+            ty::Covariant => self.infcx.sub_regions(b, a, self.span),
             // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
-            ty::Contravariant => self.infcx.sub_regions(a, b),
-            ty::Invariant => self.infcx.equate_regions(a, b),
+            ty::Contravariant => self.infcx.sub_regions(a, b, self.span),
+            ty::Invariant => self.infcx.equate_regions(a, b, self.span),
             ty::Bivariant => {
                 unreachable!("Expected bivariance to be handled in relate_with_variance")
             }
diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs
index 9e31fed9b18..376fa22ae19 100644
--- a/tests/ui/traits/next-solver/specialization-transmute.rs
+++ b/tests/ui/traits/next-solver/specialization-transmute.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Znext-solver
-//~^ ERROR cannot normalize `<T as Default>::Id: '_`
 #![feature(specialization)]
 //~^ WARN the feature `specialization` is incomplete
 
@@ -14,6 +13,7 @@ impl<T> Default for T {
     // This will be fixed by #111994
     fn intu(&self) -> &Self::Id {
         //~^ ERROR type annotations needed
+        //~| ERROR cannot normalize `<T as Default>::Id: '_`
         self //~ ERROR cannot satisfy
     }
 }
diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr
index 2d0c503bc95..eeb101911c4 100644
--- a/tests/ui/traits/next-solver/specialization-transmute.stderr
+++ b/tests/ui/traits/next-solver/specialization-transmute.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-transmute.rs:3:12
+  --> $DIR/specialization-transmute.rs:2:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -9,9 +9,13 @@ LL | #![feature(specialization)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: cannot normalize `<T as Default>::Id: '_`
+  --> $DIR/specialization-transmute.rs:14:5
+   |
+LL |     fn intu(&self) -> &Self::Id {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0282]: type annotations needed
-  --> $DIR/specialization-transmute.rs:15:23
+  --> $DIR/specialization-transmute.rs:14:23
    |
 LL |     fn intu(&self) -> &Self::Id {
    |                       ^^^^^^^^^ cannot infer type for reference `&<T as Default>::Id`
diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs
index 733be204354..e7fa60a2e3f 100644
--- a/tests/ui/traits/next-solver/unsound-region-obligation.rs
+++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs
@@ -1,4 +1,3 @@
-//~ ERROR the type `&'a ()` does not fulfill the required lifetime
 //@ compile-flags: -Znext-solver
 // Regression test for rust-lang/trait-system-refactor-initiative#59
 
@@ -8,6 +7,7 @@ trait StaticTy {
 
 impl StaticTy for () {
     type Item<'a> = &'a ();
+    //~^ ERROR the type `&'a ()` does not fulfill the required lifetime
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr
index fe96a184f43..dea3b62334c 100644
--- a/tests/ui/traits/next-solver/unsound-region-obligation.stderr
+++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr
@@ -1,4 +1,8 @@
 error[E0477]: the type `&'a ()` does not fulfill the required lifetime
+  --> $DIR/unsound-region-obligation.rs:9:21
+   |
+LL |     type Item<'a> = &'a ();
+   |                     ^^^^^^
    |
    = note: type must satisfy the static lifetime