88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use dep_graph:: DepGraph ;
1211use infer:: { InferCtxt , InferOk } ;
13- use ty:: { self , Ty , TypeFoldable , ToPolyTraitRef , TyCtxt , ToPredicate } ;
12+ use ty:: { self , Ty , TypeFoldable , ToPolyTraitRef , ToPredicate } ;
1413use ty:: error:: ExpectedFound ;
1514use rustc_data_structures:: obligation_forest:: { ObligationForest , Error } ;
1615use rustc_data_structures:: obligation_forest:: { ForestObligation , ObligationProcessor } ;
1716use std:: marker:: PhantomData ;
1817use syntax:: ast;
19- use util:: nodemap:: { FxHashSet , NodeMap } ;
18+ use util:: nodemap:: NodeMap ;
2019use hir:: def_id:: DefId ;
2120
2221use super :: CodeAmbiguity ;
@@ -34,11 +33,6 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
3433 fn as_predicate ( & self ) -> & Self :: Predicate { & self . obligation . predicate }
3534}
3635
37- pub struct GlobalFulfilledPredicates < ' tcx > {
38- set : FxHashSet < ty:: PolyTraitPredicate < ' tcx > > ,
39- dep_graph : DepGraph ,
40- }
41-
4236/// The fulfillment context is used to drive trait resolution. It
4337/// consists of a list of obligations that must be (eventually)
4438/// satisfied. The job is to track which are satisfied, which yielded
@@ -183,13 +177,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
183177
184178 assert ! ( !infcx. is_in_snapshot( ) ) ;
185179
186- let tcx = infcx. tcx ;
187-
188- if tcx. fulfilled_predicates . borrow ( ) . check_duplicate ( tcx, & obligation. predicate ) {
189- debug ! ( "register_predicate_obligation: duplicate" ) ;
190- return
191- }
192-
193180 self . predicates . register_obligation ( PendingPredicateObligation {
194181 obligation,
195182 stalled_on : vec ! [ ]
@@ -264,13 +251,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
264251 } ) ;
265252 debug ! ( "select: outcome={:?}" , outcome) ;
266253
267- // these are obligations that were proven to be true.
268- for pending_obligation in outcome. completed {
269- let predicate = & pending_obligation. obligation . predicate ;
270- selcx. tcx ( ) . fulfilled_predicates . borrow_mut ( )
271- . add_if_global ( selcx. tcx ( ) , predicate) ;
272- }
273-
274254 errors. extend (
275255 outcome. errors . into_iter ( )
276256 . map ( |e| to_fulfillment_error ( e) ) ) ;
@@ -318,7 +298,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
318298 _marker : PhantomData < & ' c PendingPredicateObligation < ' tcx > > )
319299 where I : Clone + Iterator < Item =& ' c PendingPredicateObligation < ' tcx > > ,
320300 {
321- if coinductive_match ( self . selcx , cycle. clone ( ) ) {
301+ if self . selcx . coinductive_match ( cycle. clone ( ) . map ( |s| s . obligation . predicate ) ) {
322302 debug ! ( "process_child_obligations: coinductive match" ) ;
323303 } else {
324304 let cycle : Vec < _ > = cycle. map ( |c| c. obligation . clone ( ) ) . collect ( ) ;
@@ -375,21 +355,31 @@ fn process_predicate<'a, 'gcx, 'tcx>(
375355
376356 match obligation. predicate {
377357 ty:: Predicate :: Trait ( ref data) => {
378- let tcx = selcx. tcx ( ) ;
379- if tcx. fulfilled_predicates . borrow ( ) . check_duplicate_trait ( tcx, data) {
380- return Ok ( Some ( vec ! [ ] ) ) ;
358+ let trait_obligation = obligation. with ( data. clone ( ) ) ;
359+
360+ if data. is_global ( ) {
361+ // no type variables present, can use evaluation for better caching.
362+ // FIXME: consider caching errors too.
363+ if
364+ // make defaulted unit go through the slow path for better warnings,
365+ // please remove this when the warnings are removed.
366+ !trait_obligation. predicate . skip_binder ( ) . self_ty ( ) . is_defaulted_unit ( ) &&
367+ selcx. evaluate_obligation_conservatively ( & obligation) {
368+ debug ! ( "selecting trait `{:?}` at depth {} evaluated to holds" ,
369+ data, obligation. recursion_depth) ;
370+ return Ok ( Some ( vec ! [ ] ) )
371+ }
381372 }
382373
383- let trait_obligation = obligation. with ( data. clone ( ) ) ;
384374 match selcx. select ( & trait_obligation) {
385375 Ok ( Some ( vtable) ) => {
386376 debug ! ( "selecting trait `{:?}` at depth {} yielded Ok(Some)" ,
387- data, obligation. recursion_depth) ;
377+ data, obligation. recursion_depth) ;
388378 Ok ( Some ( vtable. nested_obligations ( ) ) )
389379 }
390380 Ok ( None ) => {
391381 debug ! ( "selecting trait `{:?}` at depth {} yielded Ok(None)" ,
392- data, obligation. recursion_depth) ;
382+ data, obligation. recursion_depth) ;
393383
394384 // This is a bit subtle: for the most part, the
395385 // only reason we can fail to make progress on
@@ -549,40 +539,6 @@ fn process_predicate<'a, 'gcx, 'tcx>(
549539 }
550540}
551541
552- /// For defaulted traits, we use a co-inductive strategy to solve, so
553- /// that recursion is ok. This routine returns true if the top of the
554- /// stack (`cycle[0]`):
555- /// - is a defaulted trait, and
556- /// - it also appears in the backtrace at some position `X`; and,
557- /// - all the predicates at positions `X..` between `X` an the top are
558- /// also defaulted traits.
559- fn coinductive_match < ' a , ' c , ' gcx , ' tcx , I > ( selcx : & mut SelectionContext < ' a , ' gcx , ' tcx > ,
560- cycle : I ) -> bool
561- where I : Iterator < Item =& ' c PendingPredicateObligation < ' tcx > > ,
562- ' tcx : ' c
563- {
564- let mut cycle = cycle;
565- cycle
566- . all ( |bt_obligation| {
567- let result = coinductive_obligation ( selcx, & bt_obligation. obligation ) ;
568- debug ! ( "coinductive_match: bt_obligation={:?} coinductive={}" ,
569- bt_obligation, result) ;
570- result
571- } )
572- }
573-
574- fn coinductive_obligation < ' a , ' gcx , ' tcx > ( selcx : & SelectionContext < ' a , ' gcx , ' tcx > ,
575- obligation : & PredicateObligation < ' tcx > )
576- -> bool {
577- match obligation. predicate {
578- ty:: Predicate :: Trait ( ref data) => {
579- selcx. tcx ( ) . trait_has_default_impl ( data. def_id ( ) )
580- }
581- _ => {
582- false
583- }
584- }
585- }
586542
587543fn register_region_obligation < ' tcx > ( t_a : Ty < ' tcx > ,
588544 r_b : ty:: Region < ' tcx > ,
@@ -602,55 +558,6 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
602558
603559}
604560
605- impl < ' a , ' gcx , ' tcx > GlobalFulfilledPredicates < ' gcx > {
606- pub fn new ( dep_graph : DepGraph ) -> GlobalFulfilledPredicates < ' gcx > {
607- GlobalFulfilledPredicates {
608- set : FxHashSet ( ) ,
609- dep_graph,
610- }
611- }
612-
613- pub fn check_duplicate ( & self , tcx : TyCtxt , key : & ty:: Predicate < ' tcx > ) -> bool {
614- if let ty:: Predicate :: Trait ( ref data) = * key {
615- self . check_duplicate_trait ( tcx, data)
616- } else {
617- false
618- }
619- }
620-
621- pub fn check_duplicate_trait ( & self , tcx : TyCtxt , data : & ty:: PolyTraitPredicate < ' tcx > ) -> bool {
622- // For the global predicate registry, when we find a match, it
623- // may have been computed by some other task, so we want to
624- // add a read from the node corresponding to the predicate
625- // processing to make sure we get the transitive dependencies.
626- if self . set . contains ( data) {
627- debug_assert ! ( data. is_global( ) ) ;
628- self . dep_graph . read ( data. dep_node ( tcx) ) ;
629- debug ! ( "check_duplicate: global predicate `{:?}` already proved elsewhere" , data) ;
630-
631- true
632- } else {
633- false
634- }
635- }
636-
637- fn add_if_global ( & mut self , tcx : TyCtxt < ' a , ' gcx , ' tcx > , key : & ty:: Predicate < ' tcx > ) {
638- if let ty:: Predicate :: Trait ( ref data) = * key {
639- // We only add things to the global predicate registry
640- // after the current task has proved them, and hence
641- // already has the required read edges, so we don't need
642- // to add any more edges here.
643- if data. is_global ( ) {
644- if let Some ( data) = tcx. lift_to_global ( data) {
645- if self . set . insert ( data. clone ( ) ) {
646- debug ! ( "add_if_global: global predicate `{:?}` added" , data) ;
647- }
648- }
649- }
650- }
651- }
652- }
653-
654561fn to_fulfillment_error < ' tcx > (
655562 error : Error < PendingPredicateObligation < ' tcx > , FulfillmentErrorCode < ' tcx > > )
656563 -> FulfillmentError < ' tcx >
0 commit comments