@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt};
1414use rustc_span:: symbol:: sym;
1515
1616use super :: eval_ctxt:: GenerateProofTree ;
17- use super :: inspect:: { ProofTreeInferCtxtExt , ProofTreeVisitor } ;
17+ use super :: inspect:: { InspectCandidate , InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor } ;
1818use super :: { Certainty , InferCtxtEvalExt } ;
1919
2020/// A trait engine using the new trait solver.
@@ -304,6 +304,46 @@ impl<'tcx> BestObligation<'tcx> {
304304 self . obligation = old_obligation;
305305 res
306306 }
307+
308+ /// Filter out the candidates that aren't either error or ambiguous (depending
309+ /// on what we are looking for), and also throw out candidates that have no
310+ /// failing WC (or higher-ranked obligations, for which there should only be
311+ /// one candidate anyways -- but I digress). This most likely means that the
312+ /// goal just didn't unify at all, e.g. a param candidate with an alias in it.
313+ fn non_trivial_candidates < ' a > (
314+ & self ,
315+ goal : & ' a InspectGoal < ' a , ' tcx > ,
316+ ) -> Vec < InspectCandidate < ' a , ' tcx > > {
317+ let mut candidates = goal
318+ . candidates ( )
319+ . into_iter ( )
320+ . filter ( |candidate| match self . consider_ambiguities {
321+ true => matches ! ( candidate. result( ) , Ok ( Certainty :: Maybe ( _) ) ) ,
322+ false => matches ! ( candidate. result( ) , Err ( _) ) ,
323+ } )
324+ . collect :: < Vec < _ > > ( ) ;
325+
326+ // If we have >1 candidate, one may still be due to "boring" reasons, like
327+ // an alias-relate that failed to hold when deeply evaluated. We really
328+ // don't care about reasons like this.
329+ if candidates. len ( ) > 1 {
330+ candidates. retain ( |candidate| {
331+ goal. infcx ( ) . probe ( |_| {
332+ candidate. instantiate_nested_goals ( self . span ( ) ) . iter ( ) . any ( |nested_goal| {
333+ matches ! (
334+ nested_goal. source( ) ,
335+ GoalSource :: ImplWhereBound | GoalSource :: InstantiateHigherRanked
336+ ) && match self . consider_ambiguities {
337+ true => matches ! ( nested_goal. result( ) , Ok ( Certainty :: Maybe ( _) ) ) ,
338+ false => matches ! ( nested_goal. result( ) , Err ( _) ) ,
339+ }
340+ } )
341+ } )
342+ } ) ;
343+ }
344+
345+ candidates
346+ }
307347}
308348
309349impl < ' tcx > ProofTreeVisitor < ' tcx > for BestObligation < ' tcx > {
@@ -314,11 +354,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
314354 }
315355
316356 fn visit_goal ( & mut self , goal : & super :: inspect:: InspectGoal < ' _ , ' tcx > ) -> Self :: Result {
317- // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
318- // This most likely means that the goal just didn't unify at all, e.g. a param
319- // candidate with an alias in it.
320- let candidates = goal. candidates ( ) ;
321-
357+ let candidates = self . non_trivial_candidates ( goal) ;
322358 let [ candidate] = candidates. as_slice ( ) else {
323359 return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
324360 } ;
0 commit comments