diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-06 18:50:35 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-06 18:50:35 +0200 |
| commit | 43de8225dc2bdf2ad9a58f42192a32bf2b2eae98 (patch) | |
| tree | b474324b8c1b76a6ed480ba7f6460263e0e2cc95 /compiler/rustc_trait_selection/src/solve | |
| parent | 2d557ba9f4cbc1cdc01a515864867c12e3b85ad1 (diff) | |
| parent | 4e3350d43b2546281784d2ce4cf6803473a81645 (diff) | |
| download | rust-43de8225dc2bdf2ad9a58f42192a32bf2b2eae98.tar.gz rust-43de8225dc2bdf2ad9a58f42192a32bf2b2eae98.zip | |
Rollup merge of #124771 - compiler-errors:cand-has-failing-wc, r=lcnr
Don't consider candidates with no failing where clauses when refining obligation causes in new solver Improves error messages when we have param-env candidates that don't deeply unify (i.e. after alias-bounds). r? lcnr
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/fulfill.rs | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index fd4b5805f02..39d2ec4417c 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; use super::eval_ctxt::GenerateProofTree; -use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; +use super::inspect::{InspectCandidate, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; /// A trait engine using the new trait solver. @@ -304,6 +304,46 @@ impl<'tcx> BestObligation<'tcx> { self.obligation = old_obligation; res } + + /// Filter out the candidates that aren't either error or ambiguous (depending + /// on what we are looking for), and also throw out candidates that have no + /// failing WC (or higher-ranked obligations, for which there should only be + /// one candidate anyways -- but I digress). This most likely means that the + /// goal just didn't unify at all, e.g. a param candidate with an alias in it. + fn non_trivial_candidates<'a>( + &self, + goal: &'a InspectGoal<'a, 'tcx>, + ) -> Vec<InspectCandidate<'a, 'tcx>> { + let mut candidates = goal + .candidates() + .into_iter() + .filter(|candidate| match self.consider_ambiguities { + true => matches!(candidate.result(), Ok(Certainty::Maybe(_))), + false => matches!(candidate.result(), Err(_)), + }) + .collect::<Vec<_>>(); + + // If we have >1 candidate, one may still be due to "boring" reasons, like + // an alias-relate that failed to hold when deeply evaluated. We really + // don't care about reasons like this. + if candidates.len() > 1 { + candidates.retain(|candidate| { + goal.infcx().probe(|_| { + candidate.instantiate_nested_goals(self.span()).iter().any(|nested_goal| { + matches!( + nested_goal.source(), + GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked + ) && match self.consider_ambiguities { + true => matches!(nested_goal.result(), Ok(Certainty::Maybe(_))), + false => matches!(nested_goal.result(), Err(_)), + } + }) + }) + }); + } + + candidates + } } impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { @@ -314,11 +354,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { - // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal. - // This most likely means that the goal just didn't unify at all, e.g. a param - // candidate with an alias in it. - let candidates = goal.candidates(); - + let candidates = self.non_trivial_candidates(goal); let [candidate] = candidates.as_slice() else { return ControlFlow::Break(self.obligation.clone()); }; |
