@@ -66,7 +66,7 @@ pub struct FulfillmentContext<'tcx> {
6666
6767 // A list of all obligations that have been registered with this
6868 // fulfillment context.
69- predicates : ObligationForest < PendingPredicateObligation < ' tcx > > ,
69+ predicates : ObligationForest < PendingPredicateObligation < ' tcx > , ( ) > ,
7070
7171 // A set of constraints that regionck must validate. Each
7272 // constraint has the form `T:'a`, meaning "some type `T` must
@@ -192,7 +192,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
192192 obligation : obligation,
193193 stalled_on : vec ! [ ]
194194 } ;
195- self . predicates . push_root ( obligation) ;
195+ self . predicates . push_tree ( obligation, ( ) ) ;
196196 }
197197
198198 pub fn region_obligations ( & self ,
@@ -278,10 +278,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
278278 let outcome = {
279279 let region_obligations = & mut self . region_obligations ;
280280 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) )
285285 } ;
286286
287287 debug ! ( "select_where_possible: outcome={:?}" , outcome) ;
@@ -405,7 +405,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
405405 pending_obligation. stalled_on = vec ! [ ] ;
406406 }
407407
408- let obligation = & pending_obligation. obligation ;
408+ let obligation = & mut pending_obligation. obligation ;
409409
410410 // If we exceed the recursion limit, take a moment to look for a
411411 // 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>,
417417 }
418418 }
419419
420+ if obligation. predicate . has_infer_types ( ) {
421+ obligation. predicate = selcx. infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
422+ }
423+
420424 match obligation. predicate {
421425 ty:: Predicate :: Trait ( ref data) => {
426+ if selcx. tcx ( ) . fulfilled_predicates . borrow ( ) . check_duplicate_trait ( data) {
427+ return Ok ( Some ( vec ! [ ] ) ) ;
428+ }
429+
422430 if coinductive_match ( selcx, obligation, data, & backtrace) {
423431 return Ok ( Some ( vec ! [ ] ) ) ;
424432 }
425433
426434 let trait_obligation = obligation. with ( data. clone ( ) ) ;
427435 match selcx. select ( & trait_obligation) {
428436 Ok ( Some ( vtable) ) => {
437+ info ! ( "selecting trait `{:?}` at depth {} yielded Ok(Some)" ,
438+ data, obligation. recursion_depth) ;
429439 Ok ( Some ( vtable. nested_obligations ( ) ) )
430440 }
431441 Ok ( None ) => {
442+ info ! ( "selecting trait `{:?}` at depth {} yielded Ok(None)" ,
443+ data, obligation. recursion_depth) ;
444+
432445 // This is a bit subtle: for the most part, the
433446 // only reason we can fail to make progress on
434447 // trait selection is because we don't have enough
@@ -457,6 +470,8 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
457470 Ok ( None )
458471 }
459472 Err ( selection_err) => {
473+ info ! ( "selecting trait `{:?}` at depth {} yielded Err" ,
474+ data, obligation. recursion_depth) ;
460475 Err ( CodeSelectionError ( selection_err) )
461476 }
462477 }
@@ -642,18 +657,28 @@ impl<'tcx> GlobalFulfilledPredicates<'tcx> {
642657
643658 pub fn check_duplicate ( & self , key : & ty:: Predicate < ' tcx > ) -> bool {
644659 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
654663 }
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) ;
655677
656- return false ;
678+ true
679+ } else {
680+ false
681+ }
657682 }
658683
659684 fn add_if_global ( & mut self , key : & ty:: Predicate < ' tcx > ) {
@@ -663,7 +688,10 @@ impl<'tcx> GlobalFulfilledPredicates<'tcx> {
663688 // already has the required read edges, so we don't need
664689 // to add any more edges here.
665690 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+ }
667695 }
668696 }
669697 }
0 commit comments