about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/solve
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-01-06 22:04:13 -0500
committerGitHub <noreply@github.com>2025-01-06 22:04:13 -0500
commitb642740e4f52e858dec35a0accc3fa93ca3512b7 (patch)
treec6f54606ffe42da5d17b10a5b7d62a40ef8333bc /compiler/rustc_trait_selection/src/solve
parent4e4a93c2dd4bae8472924d03c37f387fbf3b074c (diff)
parentebdf19a8bbd1efb533bab35b0a2b327e4a33282f (diff)
Rollup merge of #132345 - compiler-errors:fx-diag, r=lcnr
Improve diagnostics for `HostEffectPredicate` in the new solver

Adds derived cause for host effect predicates. Some diagnostics regress, but that's connected to the fact that our predicate visitor doesn't play well with aliases just yet.
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs79
1 files changed, 75 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index c79a8abca20..7db0f2bb5a7 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -430,6 +430,7 @@ impl<'tcx> BestObligation<'tcx> {
                                     matches!(
                                         nested_goal.source(),
                                         GoalSource::ImplWhereBound
+                                            | GoalSource::AliasBoundConstCondition
                                             | GoalSource::InstantiateHigherRanked
                                             | GoalSource::AliasWellFormed
                                     ) && match self.consider_ambiguities {
@@ -491,8 +492,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         // for normalizes-to.
         let pred_kind = goal.goal().predicate.kind();
         let child_mode = match pred_kind.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
-                ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
+            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                ChildMode::Trait(pred_kind.rebind(pred))
+            }
+            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => {
+                ChildMode::Host(pred_kind.rebind(pred))
             }
             ty::PredicateKind::NormalizesTo(normalizes_to)
                 if matches!(
@@ -521,7 +525,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
 
             let obligation;
             match (child_mode, nested_goal.source()) {
-                (ChildMode::Trait(_), GoalSource::Misc) => {
+                (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => {
                     continue;
                 }
                 (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
@@ -534,11 +538,25 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                     ));
                     impl_where_bound_count += 1;
                 }
+                (
+                    ChildMode::Host(parent_host_pred),
+                    GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
+                ) => {
+                    obligation = make_obligation(derive_host_cause(
+                        tcx,
+                        candidate.kind(),
+                        self.obligation.cause.clone(),
+                        impl_where_bound_count,
+                        parent_host_pred,
+                    ));
+                    impl_where_bound_count += 1;
+                }
                 // Skip over a higher-ranked predicate.
                 (_, GoalSource::InstantiateHigherRanked) => {
                     obligation = self.obligation.clone();
                 }
-                (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
+                (ChildMode::PassThrough, _)
+                | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
                     obligation = make_obligation(self.obligation.cause.clone());
                 }
             }
@@ -592,6 +610,10 @@ enum ChildMode<'tcx> {
     // and skip all `GoalSource::Misc`, which represent useless obligations
     // such as alias-eq which may not hold.
     Trait(ty::PolyTraitPredicate<'tcx>),
+    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
+    // and skip all `GoalSource::Misc`, which represent useless obligations
+    // such as alias-eq which may not hold.
+    Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>),
     // Skip trying to derive an `ObligationCause` from this obligation, and
     // report *all* sub-obligations as if they came directly from the parent
     // obligation.
@@ -633,3 +655,52 @@ fn derive_cause<'tcx>(
     };
     cause
 }
+
+fn derive_host_cause<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
+    mut cause: ObligationCause<'tcx>,
+    idx: usize,
+    parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+) -> ObligationCause<'tcx> {
+    match candidate_kind {
+        inspect::ProbeKind::TraitCandidate {
+            source: CandidateSource::Impl(impl_def_id),
+            result: _,
+        } => {
+            if let Some((_, span)) = tcx
+                .predicates_of(impl_def_id)
+                .instantiate_identity(tcx)
+                .into_iter()
+                .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
+                    |(trait_ref, span)| {
+                        (
+                            trait_ref.to_host_effect_clause(
+                                tcx,
+                                parent_host_pred.skip_binder().constness,
+                            ),
+                            span,
+                        )
+                    },
+                ))
+                .nth(idx)
+            {
+                cause =
+                    cause.derived_host_cause(parent_host_pred, |derived| {
+                        ObligationCauseCode::ImplDerivedHost(Box::new(
+                            traits::ImplDerivedHostCause { derived, impl_def_id, span },
+                        ))
+                    })
+            }
+        }
+        inspect::ProbeKind::TraitCandidate {
+            source: CandidateSource::BuiltinImpl(..),
+            result: _,
+        } => {
+            cause =
+                cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost);
+        }
+        _ => {}
+    };
+    cause
+}