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