@@ -359,17 +359,8 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
359
359
let obligation = & pending_obligation. obligation ;
360
360
match obligation. predicate {
361
361
ty:: Predicate :: Trait ( ref data) => {
362
- // For defaulted traits, we use a co-inductive strategy to
363
- // solve, so that recursion is ok.
364
- if selcx. tcx ( ) . trait_has_default_impl ( data. def_id ( ) ) {
365
- debug ! ( "process_predicate: trait has default impl" ) ;
366
- for bt_obligation in backtrace {
367
- debug ! ( "process_predicate: bt_obligation = {:?}" , bt_obligation. obligation) ;
368
- if bt_obligation. obligation . predicate == obligation. predicate {
369
- debug ! ( "process_predicate: found a match!" ) ;
370
- return Ok ( Some ( vec ! [ ] ) ) ;
371
- }
372
- }
362
+ if coinductive_match ( selcx, obligation, data, & backtrace) {
363
+ return Ok ( Some ( vec ! [ ] ) ) ;
373
364
}
374
365
375
366
let trait_obligation = obligation. with ( data. clone ( ) ) ;
@@ -483,6 +474,42 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
483
474
}
484
475
}
485
476
477
+ /// For defaulted traits, we use a co-inductive strategy to solve, so
478
+ /// that recursion is ok. This routine returns true if the top of the
479
+ /// stack (`top_obligation` and `top_data`):
480
+ /// - is a defaulted trait, and
481
+ /// - it also appears in the backtrace at some position `X`; and,
482
+ /// - all the predicates at positions `X..` between `X` an the top are
483
+ /// also defaulted traits.
484
+ fn coinductive_match < ' a , ' tcx > ( selcx : & mut SelectionContext < ' a , ' tcx > ,
485
+ top_obligation : & PredicateObligation < ' tcx > ,
486
+ top_data : & ty:: PolyTraitPredicate < ' tcx > ,
487
+ backtrace : & Backtrace < PendingPredicateObligation < ' tcx > > )
488
+ -> bool
489
+ {
490
+ if selcx. tcx ( ) . trait_has_default_impl ( top_data. def_id ( ) ) {
491
+ for bt_obligation in backtrace. clone ( ) {
492
+ // *Everything* in the backtrace must be a defaulted trait.
493
+ match bt_obligation. obligation . predicate {
494
+ ty:: Predicate :: Trait ( ref data) => {
495
+ if !selcx. tcx ( ) . trait_has_default_impl ( data. def_id ( ) ) {
496
+ break ;
497
+ }
498
+ }
499
+ _ => { break ; }
500
+ }
501
+
502
+ // And we must find a recursive match.
503
+ if bt_obligation. obligation . predicate == top_obligation. predicate {
504
+ debug ! ( "process_predicate: found a match in the backtrace" ) ;
505
+ return true ;
506
+ }
507
+ }
508
+ }
509
+
510
+ false
511
+ }
512
+
486
513
fn register_region_obligation < ' tcx > ( t_a : Ty < ' tcx > ,
487
514
r_b : ty:: Region ,
488
515
cause : ObligationCause < ' tcx > ,
0 commit comments