@@ -66,7 +66,7 @@ pub struct FulfillmentContext<'tcx> {
66
66
67
67
// A list of all obligations that have been registered with this
68
68
// fulfillment context.
69
- predicates : ObligationForest < PendingPredicateObligation < ' tcx > > ,
69
+ predicates : ObligationForest < PendingPredicateObligation < ' tcx > , ( ) > ,
70
70
71
71
// A set of constraints that regionck must validate. Each
72
72
// constraint has the form `T:'a`, meaning "some type `T` must
@@ -192,7 +192,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
192
192
obligation : obligation,
193
193
stalled_on : vec ! [ ]
194
194
} ;
195
- self . predicates . push_root ( obligation) ;
195
+ self . predicates . push_tree ( obligation, ( ) ) ;
196
196
}
197
197
198
198
pub fn region_obligations ( & self ,
@@ -278,10 +278,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
278
278
let outcome = {
279
279
let region_obligations = & mut self . region_obligations ;
280
280
self . predicates . process_obligations (
281
- |obligation, backtrace| process_predicate ( selcx,
282
- obligation,
283
- backtrace,
284
- region_obligations) )
281
+ |obligation, _tree , backtrace| process_predicate ( selcx,
282
+ obligation,
283
+ backtrace,
284
+ region_obligations) )
285
285
} ;
286
286
287
287
debug ! ( "select_where_possible: outcome={:?}" , outcome) ;
@@ -405,7 +405,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
405
405
pending_obligation. stalled_on = vec ! [ ] ;
406
406
}
407
407
408
- let obligation = & pending_obligation. obligation ;
408
+ let obligation = & mut pending_obligation. obligation ;
409
409
410
410
// If we exceed the recursion limit, take a moment to look for a
411
411
// cycle so we can give a better error report from here, where we
@@ -417,18 +417,31 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
417
417
}
418
418
}
419
419
420
+ if obligation. predicate . has_infer_types ( ) {
421
+ obligation. predicate = selcx. infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
422
+ }
423
+
420
424
match obligation. predicate {
421
425
ty:: Predicate :: Trait ( ref data) => {
426
+ if selcx. tcx ( ) . fulfilled_predicates . borrow ( ) . check_duplicate_trait ( data) {
427
+ return Ok ( Some ( vec ! [ ] ) ) ;
428
+ }
429
+
422
430
if coinductive_match ( selcx, obligation, data, & backtrace) {
423
431
return Ok ( Some ( vec ! [ ] ) ) ;
424
432
}
425
433
426
434
let trait_obligation = obligation. with ( data. clone ( ) ) ;
427
435
match selcx. select ( & trait_obligation) {
428
436
Ok ( Some ( vtable) ) => {
437
+ info ! ( "selecting trait `{:?}` at depth {} yielded Ok(Some)" ,
438
+ data, obligation. recursion_depth) ;
429
439
Ok ( Some ( vtable. nested_obligations ( ) ) )
430
440
}
431
441
Ok ( None ) => {
442
+ info ! ( "selecting trait `{:?}` at depth {} yielded Ok(None)" ,
443
+ data, obligation. recursion_depth) ;
444
+
432
445
// This is a bit subtle: for the most part, the
433
446
// only reason we can fail to make progress on
434
447
// trait selection is because we don't have enough
@@ -457,6 +470,8 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
457
470
Ok ( None )
458
471
}
459
472
Err ( selection_err) => {
473
+ info ! ( "selecting trait `{:?}` at depth {} yielded Err" ,
474
+ data, obligation. recursion_depth) ;
460
475
Err ( CodeSelectionError ( selection_err) )
461
476
}
462
477
}
@@ -642,18 +657,28 @@ impl<'tcx> GlobalFulfilledPredicates<'tcx> {
642
657
643
658
pub fn check_duplicate ( & self , key : & ty:: Predicate < ' tcx > ) -> bool {
644
659
if let ty:: Predicate :: Trait ( ref data) = * key {
645
- // For the global predicate registry, when we find a match, it
646
- // may have been computed by some other task, so we want to
647
- // add a read from the node corresponding to the predicate
648
- // processing to make sure we get the transitive dependencies.
649
- if self . set . contains ( data) {
650
- debug_assert ! ( data. is_global( ) ) ;
651
- self . dep_graph . read ( data. dep_node ( ) ) ;
652
- return true ;
653
- }
660
+ self . check_duplicate_trait ( data)
661
+ } else {
662
+ false
654
663
}
664
+ }
665
+
666
+ pub fn check_duplicate_trait ( & self , data : & ty:: PolyTraitPredicate < ' tcx > ) -> bool {
667
+ // For the global predicate registry, when we find a match, it
668
+ // may have been computed by some other task, so we want to
669
+ // add a read from the node corresponding to the predicate
670
+ // processing to make sure we get the transitive dependencies.
671
+ if self . set . contains ( data) {
672
+ debug_assert ! ( data. is_global( ) ) ;
673
+ self . dep_graph . read ( data. dep_node ( ) ) ;
674
+ debug ! ( "check_duplicate: global predicate `{:?}` already proved elsewhere" , data) ;
675
+
676
+ info ! ( "check_duplicate_trait hit: `{:?}`" , data) ;
655
677
656
- return false ;
678
+ true
679
+ } else {
680
+ false
681
+ }
657
682
}
658
683
659
684
fn add_if_global ( & mut self , key : & ty:: Predicate < ' tcx > ) {
@@ -663,7 +688,10 @@ impl<'tcx> GlobalFulfilledPredicates<'tcx> {
663
688
// already has the required read edges, so we don't need
664
689
// to add any more edges here.
665
690
if data. is_global ( ) {
666
- self . set . insert ( data. clone ( ) ) ;
691
+ if self . set . insert ( data. clone ( ) ) {
692
+ debug ! ( "add_if_global: global predicate `{:?}` added" , data) ;
693
+ info ! ( "check_duplicate_trait entry: `{:?}`" , data) ;
694
+ }
667
695
}
668
696
}
669
697
}
0 commit comments