@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt};
14
14
use rustc_span:: symbol:: sym;
15
15
16
16
use super :: eval_ctxt:: GenerateProofTree ;
17
- use super :: inspect:: { ProofTreeInferCtxtExt , ProofTreeVisitor } ;
17
+ use super :: inspect:: { InspectCandidate , InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor } ;
18
18
use super :: { Certainty , InferCtxtEvalExt } ;
19
19
20
20
/// A trait engine using the new trait solver.
@@ -304,6 +304,46 @@ impl<'tcx> BestObligation<'tcx> {
304
304
self . obligation = old_obligation;
305
305
res
306
306
}
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
+ }
307
347
}
308
348
309
349
impl < ' tcx > ProofTreeVisitor < ' tcx > for BestObligation < ' tcx > {
@@ -314,11 +354,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
314
354
}
315
355
316
356
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) ;
322
358
let [ candidate] = candidates. as_slice ( ) else {
323
359
return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
324
360
} ;
0 commit comments