@@ -384,39 +384,64 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
384
384
return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
385
385
}
386
386
387
- // FIXME: Could we extract a trait ref from a projection here too?
387
+ let tcx = goal . infcx ( ) . tcx ;
388
388
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
389
389
// for normalizes-to.
390
- let Some ( parent_trait_pred) = goal. goal ( ) . predicate . to_opt_poly_trait_pred ( ) else {
391
- return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
390
+ let pred_kind = goal. goal ( ) . predicate . kind ( ) ;
391
+ let child_mode = match pred_kind. skip_binder ( ) {
392
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( parent_trait_pred) ) => {
393
+ ChildMode :: Trait ( pred_kind. rebind ( parent_trait_pred) )
394
+ }
395
+ ty:: PredicateKind :: NormalizesTo ( normalizes_to)
396
+ if matches ! (
397
+ normalizes_to. alias. kind( tcx) ,
398
+ ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst
399
+ ) =>
400
+ {
401
+ ChildMode :: Trait ( pred_kind. rebind ( ty:: TraitPredicate {
402
+ trait_ref : normalizes_to. alias . trait_ref ( tcx) ,
403
+ polarity : ty:: PredicatePolarity :: Positive ,
404
+ } ) )
405
+ }
406
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( _) ) => {
407
+ ChildMode :: WellFormedObligation
408
+ }
409
+ _ => {
410
+ return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
411
+ }
392
412
} ;
393
413
394
- let tcx = goal. infcx ( ) . tcx ;
395
414
let mut impl_where_bound_count = 0 ;
396
415
for nested_goal in candidate. instantiate_nested_goals ( self . span ( ) ) {
416
+ let make_obligation = |cause| Obligation {
417
+ cause,
418
+ param_env : nested_goal. goal ( ) . param_env ,
419
+ predicate : nested_goal. goal ( ) . predicate ,
420
+ recursion_depth : self . obligation . recursion_depth + 1 ,
421
+ } ;
422
+
397
423
let obligation;
398
- match nested_goal. source ( ) {
399
- GoalSource :: Misc => {
424
+ match ( child_mode , nested_goal. source ( ) ) {
425
+ ( ChildMode :: Trait ( _ ) , GoalSource :: Misc ) => {
400
426
continue ;
401
427
}
402
- GoalSource :: ImplWhereBound => {
403
- obligation = Obligation {
404
- cause : derive_cause (
405
- tcx,
406
- candidate. kind ( ) ,
407
- self . obligation . cause . clone ( ) ,
408
- impl_where_bound_count,
409
- parent_trait_pred,
410
- ) ,
411
- param_env : nested_goal. goal ( ) . param_env ,
412
- predicate : nested_goal. goal ( ) . predicate ,
413
- recursion_depth : self . obligation . recursion_depth + 1 ,
414
- } ;
428
+ ( ChildMode :: Trait ( parent_trait_pred) , GoalSource :: ImplWhereBound ) => {
429
+ obligation = make_obligation ( derive_cause (
430
+ tcx,
431
+ candidate. kind ( ) ,
432
+ self . obligation . cause . clone ( ) ,
433
+ impl_where_bound_count,
434
+ parent_trait_pred,
435
+ ) ) ;
415
436
impl_where_bound_count += 1 ;
416
437
}
417
- GoalSource :: InstantiateHigherRanked => {
438
+ // Skip over a higher-ranked predicate.
439
+ ( _, GoalSource :: InstantiateHigherRanked ) => {
418
440
obligation = self . obligation . clone ( ) ;
419
441
}
442
+ ( ChildMode :: WellFormedObligation , _) => {
443
+ obligation = make_obligation ( self . obligation . cause . clone ( ) ) ;
444
+ }
420
445
}
421
446
422
447
// Skip nested goals that aren't the *reason* for our goal's failure.
@@ -436,6 +461,18 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
436
461
}
437
462
}
438
463
464
+ #[ derive( Copy , Clone ) ]
465
+ enum ChildMode < ' tcx > {
466
+ // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
467
+ // and skip all `GoalSource::Misc`, which represent useless obligations
468
+ // such as alias-eq which may not hold.
469
+ Trait ( ty:: PolyTraitPredicate < ' tcx > ) ,
470
+ // Skip trying to derive an `ObligationCause` from this obligation, and
471
+ // report *all* sub-obligations as if they came directly from the parent
472
+ // obligation.
473
+ WellFormedObligation ,
474
+ }
475
+
439
476
fn derive_cause < ' tcx > (
440
477
tcx : TyCtxt < ' tcx > ,
441
478
candidate_kind : ProbeKind < ' tcx > ,
0 commit comments