about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-04-09 17:25:46 +0000
committerMichael Goulet <michael@errs.io>2025-04-10 18:58:04 +0000
commitdecd7ecd1e3640c4bada4f4a3de411a8d507d40c (patch)
treee218ae1fdda6480bd5f7dc015d4966c01febfb8b /compiler/rustc_trait_selection/src
parent62d5fb85ac64f034f031423cb747cf57ee14a048 (diff)
downloadrust-decd7ecd1e3640c4bada4f4a3de411a8d507d40c.tar.gz
rust-decd7ecd1e3640c4bada4f4a3de411a8d507d40c.zip
Deeply normalize obligations in BestObligation
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs32
2 files changed, 33 insertions, 18 deletions
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 73d3f81296f..d8dcd12aecb 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as
 use rustc_type_ir::solve::NoSolution;
 use tracing::{instrument, trace};
 
-use crate::solve::Certainty;
 use crate::solve::delegate::SolverDelegate;
 use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
+use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
 use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
 
 pub(super) fn fulfillment_error_for_no_solution<'tcx>(
@@ -151,7 +151,7 @@ fn find_best_leaf_obligation<'tcx>(
     //
     // We should probably fix the visitor to not do so instead, as this also
     // means the leaf obligation may be incorrect.
-    infcx
+    let obligation = infcx
         .fudge_inference_if_ok(|| {
             infcx
                 .visit_proof_tree(
@@ -161,7 +161,8 @@ fn find_best_leaf_obligation<'tcx>(
                 .break_value()
                 .ok_or(())
         })
-        .unwrap_or(obligation)
+        .unwrap_or(obligation);
+    deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
 }
 
 struct BestObligation<'tcx> {
@@ -298,7 +299,7 @@ impl<'tcx> BestObligation<'tcx> {
     /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
     /// that should catch when a projection goal fails due to an unsatisfied trait
     /// goal.
-    fn detect_error_in_higher_ranked_projection(
+    fn detect_trait_error_in_higher_ranked_projection(
         &mut self,
         goal: &inspect::InspectGoal<'_, 'tcx>,
     ) -> ControlFlow<PredicateObligation<'tcx>> {
@@ -307,7 +308,13 @@ impl<'tcx> BestObligation<'tcx> {
             && !projection_clause.bound_vars().is_empty()
         {
             let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
-            self.with_derived_obligation(self.obligation.with(tcx, pred), |this| {
+            let obligation = Obligation::new(
+                tcx,
+                self.obligation.cause.clone(),
+                goal.goal().param_env,
+                deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
+            );
+            self.with_derived_obligation(obligation, |this| {
                 goal.infcx().visit_proof_tree_at_depth(
                     goal.goal().with(tcx, pred),
                     goal.depth() + 1,
@@ -526,7 +533,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             )?;
         }
 
-        self.detect_error_in_higher_ranked_projection(goal)?;
+        self.detect_trait_error_in_higher_ranked_projection(goal)?;
 
         ControlFlow::Break(self.obligation.clone())
     }
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 232357dc71a..79fb044a67f 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -253,20 +253,28 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        deeply_normalize_with_skipped_universes(
-            self.at,
-            ty,
-            vec![None; ty.outer_exclusive_binder().as_usize()],
-        )
-        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
+        let infcx = self.at.infcx;
+        infcx
+            .commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes(
+                    self.at,
+                    ty,
+                    vec![None; ty.outer_exclusive_binder().as_usize()],
+                )
+            })
+            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        deeply_normalize_with_skipped_universes(
-            self.at,
-            ct,
-            vec![None; ct.outer_exclusive_binder().as_usize()],
-        )
-        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
+        let infcx = self.at.infcx;
+        infcx
+            .commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes(
+                    self.at,
+                    ct,
+                    vec![None; ct.outer_exclusive_binder().as_usize()],
+                )
+            })
+            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
     }
 }