1010
1111use dep_graph:: DepGraph ;
1212use infer:: { InferCtxt , InferOk } ;
13- use ty:: { self , Ty , TypeFoldable , ToPolyTraitRef , TyCtxt } ;
13+ use ty:: { self , Ty , TypeFoldable , ToPolyTraitRef , TyCtxt , ToPredicate } ;
14+ use ty:: subst:: { Substs , Subst } ;
1415use rustc_data_structures:: obligation_forest:: { ObligationForest , Error } ;
1516use rustc_data_structures:: obligation_forest:: { ForestObligation , ObligationProcessor } ;
1617use std:: marker:: PhantomData ;
@@ -22,10 +23,9 @@ use util::nodemap::{FnvHashSet, NodeMap};
2223use super :: CodeAmbiguity ;
2324use super :: CodeProjectionError ;
2425use super :: CodeSelectionError ;
25- use super :: FulfillmentError ;
26- use super :: FulfillmentErrorCode ;
27- use super :: ObligationCause ;
28- use super :: PredicateObligation ;
26+ use super :: { FulfillmentError , FulfillmentErrorCode , SelectionError } ;
27+ use super :: { ObligationCause , BuiltinDerivedObligation } ;
28+ use super :: { PredicateObligation , TraitObligation , Obligation } ;
2929use super :: project;
3030use super :: select:: SelectionContext ;
3131use super :: Unimplemented ;
@@ -51,6 +51,7 @@ pub struct GlobalFulfilledPredicates<'tcx> {
5151/// along. Once all type inference constraints have been generated, the
5252/// method `select_all_or_error` can be used to report any remaining
5353/// ambiguous cases as errors.
54+
5455pub struct FulfillmentContext < ' tcx > {
5556 // A list of all obligations that have been registered with this
5657 // fulfillment context.
@@ -84,6 +85,10 @@ pub struct FulfillmentContext<'tcx> {
8485 // obligations (otherwise, it's easy to fail to walk to a
8586 // particular node-id).
8687 region_obligations : NodeMap < Vec < RegionObligation < ' tcx > > > ,
88+
89+ // A list of obligations that need to be deferred to
90+ // a later time for them to be properly fulfilled.
91+ deferred_obligations : Vec < DeferredObligation < ' tcx > > ,
8792}
8893
8994#[ derive( Clone ) ]
@@ -99,13 +104,98 @@ pub struct PendingPredicateObligation<'tcx> {
99104 pub stalled_on : Vec < Ty < ' tcx > > ,
100105}
101106
107+ /// An obligation which cannot be fulfilled in the context
108+ /// it was registered in, such as auto trait obligations on
109+ /// `impl Trait`, which require the concrete type to be
110+ /// available, only guaranteed after finishing type-checking.
111+ #[ derive( Clone , Debug ) ]
112+ pub struct DeferredObligation < ' tcx > {
113+ pub predicate : ty:: PolyTraitPredicate < ' tcx > ,
114+ pub cause : ObligationCause < ' tcx >
115+ }
116+
117+ impl < ' a , ' gcx , ' tcx > DeferredObligation < ' tcx > {
118+ /// If possible, create a `DeferredObligation` from
119+ /// a trait predicate which had failed selection,
120+ /// but could succeed later.
121+ pub fn from_select_error ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
122+ obligation : & TraitObligation < ' tcx > ,
123+ selection_err : & SelectionError < ' tcx > )
124+ -> Option < DeferredObligation < ' tcx > > {
125+ if let Unimplemented = * selection_err {
126+ if DeferredObligation :: must_defer ( tcx, & obligation. predicate ) {
127+ return Some ( DeferredObligation {
128+ predicate : obligation. predicate . clone ( ) ,
129+ cause : obligation. cause . clone ( )
130+ } ) ;
131+ }
132+ }
133+
134+ None
135+ }
136+
137+ /// Returns true if the given trait predicate can be
138+ /// fulfilled at a later time.
139+ pub fn must_defer ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
140+ predicate : & ty:: PolyTraitPredicate < ' tcx > )
141+ -> bool {
142+ // Auto trait obligations on `impl Trait`.
143+ if tcx. trait_has_default_impl ( predicate. def_id ( ) ) {
144+ let substs = predicate. skip_binder ( ) . trait_ref . substs ;
145+ if substs. types . as_slice ( ) . len ( ) == 1 && substs. regions . is_empty ( ) {
146+ if let ty:: TyAnon ( ..) = predicate. skip_binder ( ) . self_ty ( ) . sty {
147+ return true ;
148+ }
149+ }
150+ }
151+
152+ false
153+ }
154+
155+ /// If possible, return the nested obligations required
156+ /// to fulfill this obligation.
157+ pub fn try_select ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > )
158+ -> Option < Vec < PredicateObligation < ' tcx > > > {
159+ if let ty:: TyAnon ( def_id, substs) = self . predicate . skip_binder ( ) . self_ty ( ) . sty {
160+ // We can resolve the `impl Trait` to its concrete type.
161+ if let Some ( ty_scheme) = tcx. opt_lookup_item_type ( def_id) {
162+ let concrete_ty = ty_scheme. ty . subst ( tcx, substs) ;
163+ let concrete_substs = Substs :: new_trait ( vec ! [ ] , vec ! [ ] , concrete_ty) ;
164+ let predicate = ty:: TraitRef {
165+ def_id : self . predicate . def_id ( ) ,
166+ substs : tcx. mk_substs ( concrete_substs)
167+ } . to_predicate ( ) ;
168+
169+ let original_obligation = Obligation :: new ( self . cause . clone ( ) ,
170+ self . predicate . clone ( ) ) ;
171+ let cause = original_obligation. derived_cause ( BuiltinDerivedObligation ) ;
172+ return Some ( vec ! [ Obligation :: new( cause, predicate) ] ) ;
173+ }
174+ }
175+
176+ None
177+ }
178+
179+ /// Return the `PredicateObligation` this was created from.
180+ pub fn to_obligation ( & self ) -> PredicateObligation < ' tcx > {
181+ let predicate = ty:: Predicate :: Trait ( self . predicate . clone ( ) ) ;
182+ Obligation :: new ( self . cause . clone ( ) , predicate)
183+ }
184+
185+ /// Return an error as if this obligation had failed.
186+ pub fn to_error ( & self ) -> FulfillmentError < ' tcx > {
187+ FulfillmentError :: new ( self . to_obligation ( ) , CodeSelectionError ( Unimplemented ) )
188+ }
189+ }
190+
102191impl < ' a , ' gcx , ' tcx > FulfillmentContext < ' tcx > {
103192 /// Creates a new fulfillment context.
104193 pub fn new ( ) -> FulfillmentContext < ' tcx > {
105194 FulfillmentContext {
106195 predicates : ObligationForest :: new ( ) ,
107196 rfc1592_obligations : Vec :: new ( ) ,
108197 region_obligations : NodeMap ( ) ,
198+ deferred_obligations : vec ! [ ] ,
109199 }
110200 }
111201
@@ -224,10 +314,16 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
224314 {
225315 self . select_where_possible ( infcx) ?;
226316
317+ // Fail all of the deferred obligations that haven't
318+ // been otherwise removed from the context.
319+ let deferred_errors = self . deferred_obligations . iter ( )
320+ . map ( |d| d. to_error ( ) ) ;
321+
227322 let errors: Vec < _ > =
228323 self . predicates . to_errors ( CodeAmbiguity )
229324 . into_iter ( )
230325 . map ( |e| to_fulfillment_error ( e) )
326+ . chain ( deferred_errors)
231327 . collect ( ) ;
232328 if errors. is_empty ( ) {
233329 Ok ( ( ) )
@@ -248,6 +344,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
248344 self . predicates . pending_obligations ( )
249345 }
250346
347+ pub fn take_deferred_obligations ( & mut self ) -> Vec < DeferredObligation < ' tcx > > {
348+ mem:: replace ( & mut self . deferred_obligations , vec ! [ ] )
349+ }
350+
251351 /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
252352 /// only attempts to select obligations that haven't been seen before.
253353 fn select ( & mut self , selcx : & mut SelectionContext < ' a , ' gcx , ' tcx > )
@@ -261,9 +361,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
261361
262362 // Process pending obligations.
263363 let outcome = self . predicates . process_obligations ( & mut FulfillProcessor {
264- selcx : selcx,
265- region_obligations : & mut self . region_obligations ,
266- rfc1592_obligations : & mut self . rfc1592_obligations
364+ selcx : selcx,
365+ region_obligations : & mut self . region_obligations ,
366+ rfc1592_obligations : & mut self . rfc1592_obligations ,
367+ deferred_obligations : & mut self . deferred_obligations
267368 } ) ;
268369 debug ! ( "select: outcome={:?}" , outcome) ;
269370
@@ -298,7 +399,8 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
298399struct FulfillProcessor < ' a , ' b : ' a , ' gcx : ' tcx , ' tcx : ' b > {
299400 selcx : & ' a mut SelectionContext < ' b , ' gcx , ' tcx > ,
300401 region_obligations : & ' a mut NodeMap < Vec < RegionObligation < ' tcx > > > ,
301- rfc1592_obligations : & ' a mut Vec < PredicateObligation < ' tcx > >
402+ rfc1592_obligations : & ' a mut Vec < PredicateObligation < ' tcx > > ,
403+ deferred_obligations : & ' a mut Vec < DeferredObligation < ' tcx > >
302404}
303405
304406impl < ' a , ' b , ' gcx , ' tcx > ObligationProcessor for FulfillProcessor < ' a , ' b , ' gcx , ' tcx > {
@@ -312,7 +414,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
312414 process_predicate ( self . selcx ,
313415 obligation,
314416 self . region_obligations ,
315- self . rfc1592_obligations )
417+ self . rfc1592_obligations ,
418+ self . deferred_obligations )
316419 . map ( |os| os. map ( |os| os. into_iter ( ) . map ( |o| PendingPredicateObligation {
317420 obligation : o,
318421 stalled_on : vec ! [ ]
@@ -354,7 +457,8 @@ fn process_predicate<'a, 'gcx, 'tcx>(
354457 selcx : & mut SelectionContext < ' a , ' gcx , ' tcx > ,
355458 pending_obligation : & mut PendingPredicateObligation < ' tcx > ,
356459 region_obligations : & mut NodeMap < Vec < RegionObligation < ' tcx > > > ,
357- rfc1592_obligations : & mut Vec < PredicateObligation < ' tcx > > )
460+ rfc1592_obligations : & mut Vec < PredicateObligation < ' tcx > > ,
461+ deferred_obligations : & mut Vec < DeferredObligation < ' tcx > > )
358462 -> Result < Option < Vec < PredicateObligation < ' tcx > > > ,
359463 FulfillmentErrorCode < ' tcx > >
360464{
@@ -422,7 +526,22 @@ fn process_predicate<'a, 'gcx, 'tcx>(
422526 Err ( selection_err) => {
423527 info ! ( "selecting trait `{:?}` at depth {} yielded Err" ,
424528 data, obligation. recursion_depth) ;
425- Err ( CodeSelectionError ( selection_err) )
529+
530+ let defer = DeferredObligation :: from_select_error ( selcx. tcx ( ) ,
531+ & trait_obligation,
532+ & selection_err) ;
533+ if let Some ( deferred_obligation) = defer {
534+ if let Some ( nested) = deferred_obligation. try_select ( selcx. tcx ( ) ) {
535+ Ok ( Some ( nested) )
536+ } else {
537+ // Pretend that the obligation succeeded,
538+ // but record it for later.
539+ deferred_obligations. push ( deferred_obligation) ;
540+ Ok ( Some ( vec ! [ ] ) )
541+ }
542+ } else {
543+ Err ( CodeSelectionError ( selection_err) )
544+ }
426545 }
427546 }
428547 }
@@ -629,6 +748,12 @@ impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> {
629748 // already has the required read edges, so we don't need
630749 // to add any more edges here.
631750 if data. is_global ( ) {
751+ // Don't cache predicates which were fulfilled
752+ // by deferring them for later fulfillment.
753+ if DeferredObligation :: must_defer ( tcx, data) {
754+ return ;
755+ }
756+
632757 if let Some ( data) = tcx. lift_to_global ( data) {
633758 if self . set . insert ( data. clone ( ) ) {
634759 debug ! ( "add_if_global: global predicate `{:?}` added" , data) ;
0 commit comments