@@ -3,7 +3,7 @@ use rustc_data_structures::obligation_forest::ProcessResult;
3
3
use rustc_data_structures:: obligation_forest:: { DoCompleted , Error , ForestObligation } ;
4
4
use rustc_data_structures:: obligation_forest:: { ObligationForest , ObligationProcessor } ;
5
5
use rustc_errors:: ErrorReported ;
6
- use rustc_infer:: traits:: { TraitEngine , TraitEngineExt as _} ;
6
+ use rustc_infer:: traits:: { PolyTraitObligation , TraitEngine , TraitEngineExt as _} ;
7
7
use rustc_middle:: mir:: interpret:: ErrorHandled ;
8
8
use rustc_middle:: ty:: error:: ExpectedFound ;
9
9
use rustc_middle:: ty:: { self , Binder , Const , ToPredicate , Ty , TypeFoldable } ;
@@ -20,6 +20,7 @@ use super::{FulfillmentError, FulfillmentErrorCode};
20
20
use super :: { ObligationCause , PredicateObligation } ;
21
21
22
22
use crate :: traits:: error_reporting:: InferCtxtExt as _;
23
+ use crate :: traits:: project:: PolyProjectionObligation ;
23
24
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
24
25
25
26
impl < ' tcx > ForestObligation for PendingPredicateObligation < ' tcx > {
@@ -318,65 +319,50 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
318
319
let infcx = self . selcx . infcx ( ) ;
319
320
320
321
match obligation. predicate . kint ( infcx. tcx ) {
321
- ty:: PredicateKint :: ForAll ( binder) => {
322
- let ( pred, _) = infcx. replace_bound_vars_with_placeholders ( binder) ;
323
- ProcessResult :: Changed ( mk_pending ( vec ! [
324
- obligation. with( pred. to_predicate( infcx. tcx) ) ,
325
- ] ) )
326
- }
327
- ty:: PredicateKint :: Trait ( ref data, _) => {
328
- let trait_obligation = obligation. with ( Binder :: dummy ( * data) ) ;
329
-
330
- if obligation. predicate . is_global ( ) {
331
- // no type variables present, can use evaluation for better caching.
332
- // FIXME: consider caching errors too.
333
- if infcx. predicate_must_hold_considering_regions ( & obligation) {
334
- debug ! (
335
- "selecting trait `{:?}` at depth {} evaluated to holds" ,
336
- data, obligation. recursion_depth
337
- ) ;
338
- return ProcessResult :: Changed ( vec ! [ ] ) ;
339
- }
322
+ ty:: PredicateKint :: ForAll ( binder) => match binder. skip_binder ( ) {
323
+ // Evaluation will discard candidates using the leak check.
324
+ // This means we need to pass it the bound version of our
325
+ // predicate.
326
+ rustc_middle:: ty:: PredicateKint :: Trait ( trait_ref, _constness) => {
327
+ let trait_obligation = obligation. with ( Binder :: bind ( * trait_ref) ) ;
328
+
329
+ self . process_trait_obligation (
330
+ obligation,
331
+ trait_obligation,
332
+ & mut pending_obligation. stalled_on ,
333
+ )
340
334
}
335
+ rustc_middle:: ty:: PredicateKint :: Projection ( projection) => {
336
+ let project_obligation = obligation. with ( Binder :: bind ( * projection) ) ;
341
337
342
- match self . selcx . select ( & trait_obligation) {
343
- Ok ( Some ( impl_source) ) => {
344
- debug ! (
345
- "selecting trait `{:?}` at depth {} yielded Ok(Some)" ,
346
- data, obligation. recursion_depth
347
- ) ;
348
- ProcessResult :: Changed ( mk_pending ( impl_source. nested_obligations ( ) ) )
349
- }
350
- Ok ( None ) => {
351
- debug ! (
352
- "selecting trait `{:?}` at depth {} yielded Ok(None)" ,
353
- data, obligation. recursion_depth
354
- ) ;
355
-
356
- // This is a bit subtle: for the most part, the
357
- // only reason we can fail to make progress on
358
- // trait selection is because we don't have enough
359
- // information about the types in the trait.
360
- pending_obligation. stalled_on =
361
- trait_ref_infer_vars ( self . selcx , data. trait_ref ) ;
362
-
363
- debug ! (
364
- "process_predicate: pending obligation {:?} now stalled on {:?}" ,
365
- infcx. resolve_vars_if_possible( obligation) ,
366
- pending_obligation. stalled_on
367
- ) ;
368
-
369
- ProcessResult :: Unchanged
370
- }
371
- Err ( selection_err) => {
372
- info ! (
373
- "selecting trait `{:?}` at depth {} yielded Err" ,
374
- data, obligation. recursion_depth
375
- ) ;
376
-
377
- ProcessResult :: Error ( CodeSelectionError ( selection_err) )
378
- }
338
+ self . process_projection_obligation (
339
+ project_obligation,
340
+ & mut pending_obligation. stalled_on ,
341
+ )
379
342
}
343
+ rustc_middle:: ty:: PredicateKint :: RegionOutlives ( _)
344
+ | rustc_middle:: ty:: PredicateKint :: TypeOutlives ( _)
345
+ | rustc_middle:: ty:: PredicateKint :: WellFormed ( _)
346
+ | rustc_middle:: ty:: PredicateKint :: ObjectSafe ( _)
347
+ | rustc_middle:: ty:: PredicateKint :: ClosureKind ( ..)
348
+ | rustc_middle:: ty:: PredicateKint :: Subtype ( _)
349
+ | rustc_middle:: ty:: PredicateKint :: ConstEvaluatable ( ..)
350
+ | rustc_middle:: ty:: PredicateKint :: ConstEquate ( ..)
351
+ | rustc_middle:: ty:: PredicateKint :: ForAll ( _) => {
352
+ let ( pred, _) = infcx. replace_bound_vars_with_placeholders ( binder) ;
353
+ ProcessResult :: Changed ( mk_pending ( vec ! [
354
+ obligation. with( pred. to_predicate( infcx. tcx) ) ,
355
+ ] ) )
356
+ }
357
+ } ,
358
+ ty:: PredicateKint :: Trait ( ref data, _) => {
359
+ let trait_obligation = obligation. with ( Binder :: dummy ( * data) ) ;
360
+
361
+ self . process_trait_obligation (
362
+ obligation,
363
+ trait_obligation,
364
+ & mut pending_obligation. stalled_on ,
365
+ )
380
366
}
381
367
382
368
& ty:: PredicateKint :: RegionOutlives ( data) => {
@@ -399,17 +385,11 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
399
385
400
386
ty:: PredicateKint :: Projection ( ref data) => {
401
387
let project_obligation = obligation. with ( Binder :: dummy ( * data) ) ;
402
- match project:: poly_project_and_unify_type ( self . selcx , & project_obligation) {
403
- Ok ( None ) => {
404
- pending_obligation. stalled_on = trait_ref_infer_vars (
405
- self . selcx ,
406
- data. projection_ty . trait_ref ( infcx. tcx ) ,
407
- ) ;
408
- ProcessResult :: Unchanged
409
- }
410
- Ok ( Some ( os) ) => ProcessResult :: Changed ( mk_pending ( os) ) ,
411
- Err ( e) => ProcessResult :: Error ( CodeProjectionError ( e) ) ,
412
- }
388
+
389
+ self . process_projection_obligation (
390
+ project_obligation,
391
+ & mut pending_obligation. stalled_on ,
392
+ )
413
393
}
414
394
415
395
& ty:: PredicateKint :: ObjectSafe ( trait_def_id) => {
@@ -569,14 +549,96 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
569
549
}
570
550
}
571
551
552
+ impl < ' a , ' b , ' tcx > FulfillProcessor < ' a , ' b , ' tcx > {
553
+ fn process_trait_obligation (
554
+ & mut self ,
555
+ obligation : & PredicateObligation < ' tcx > ,
556
+ trait_obligation : PolyTraitObligation < ' tcx > ,
557
+ stalled_on : & mut Vec < TyOrConstInferVar < ' tcx > > ,
558
+ ) -> ProcessResult < PendingPredicateObligation < ' tcx > , FulfillmentErrorCode < ' tcx > > {
559
+ let infcx = self . selcx . infcx ( ) ;
560
+ if obligation. predicate . is_global ( ) {
561
+ // no type variables present, can use evaluation for better caching.
562
+ // FIXME: consider caching errors too.
563
+ if infcx. predicate_must_hold_considering_regions ( obligation) {
564
+ debug ! (
565
+ "selecting trait `{:?}` at depth {} evaluated to holds" ,
566
+ obligation. predicate, obligation. recursion_depth
567
+ ) ;
568
+ return ProcessResult :: Changed ( vec ! [ ] ) ;
569
+ }
570
+ }
571
+
572
+ match self . selcx . select ( & trait_obligation) {
573
+ Ok ( Some ( impl_source) ) => {
574
+ debug ! (
575
+ "selecting trait `{:?}` at depth {} yielded Ok(Some)" ,
576
+ trait_obligation. predicate, obligation. recursion_depth
577
+ ) ;
578
+ ProcessResult :: Changed ( mk_pending ( impl_source. nested_obligations ( ) ) )
579
+ }
580
+ Ok ( None ) => {
581
+ debug ! (
582
+ "selecting trait `{:?}` at depth {} yielded Ok(None)" ,
583
+ trait_obligation. predicate, obligation. recursion_depth
584
+ ) ;
585
+
586
+ // This is a bit subtle: for the most part, the
587
+ // only reason we can fail to make progress on
588
+ // trait selection is because we don't have enough
589
+ // information about the types in the trait.
590
+ * stalled_on = trait_ref_infer_vars (
591
+ self . selcx ,
592
+ trait_obligation. predicate . map_bound ( |pred| pred. trait_ref ) ,
593
+ ) ;
594
+
595
+ debug ! (
596
+ "process_predicate: pending obligation {:?} now stalled on {:?}" ,
597
+ infcx. resolve_vars_if_possible( obligation) ,
598
+ stalled_on
599
+ ) ;
600
+
601
+ ProcessResult :: Unchanged
602
+ }
603
+ Err ( selection_err) => {
604
+ info ! (
605
+ "selecting trait `{:?}` at depth {} yielded Err" ,
606
+ trait_obligation. predicate, obligation. recursion_depth
607
+ ) ;
608
+
609
+ ProcessResult :: Error ( CodeSelectionError ( selection_err) )
610
+ }
611
+ }
612
+ }
613
+
614
+ fn process_projection_obligation (
615
+ & mut self ,
616
+ project_obligation : PolyProjectionObligation < ' tcx > ,
617
+ stalled_on : & mut Vec < TyOrConstInferVar < ' tcx > > ,
618
+ ) -> ProcessResult < PendingPredicateObligation < ' tcx > , FulfillmentErrorCode < ' tcx > > {
619
+ match project:: poly_project_and_unify_type ( self . selcx , & project_obligation) {
620
+ Ok ( None ) => {
621
+ * stalled_on = trait_ref_infer_vars (
622
+ self . selcx ,
623
+ project_obligation. predicate . to_poly_trait_ref ( self . selcx . tcx ( ) ) ,
624
+ ) ;
625
+ ProcessResult :: Unchanged
626
+ }
627
+ Ok ( Some ( os) ) => ProcessResult :: Changed ( mk_pending ( os) ) ,
628
+ Err ( e) => ProcessResult :: Error ( CodeProjectionError ( e) ) ,
629
+ }
630
+ }
631
+ }
632
+
572
633
/// Returns the set of inference variables contained in a trait ref.
573
634
fn trait_ref_infer_vars < ' a , ' tcx > (
574
635
selcx : & mut SelectionContext < ' a , ' tcx > ,
575
- trait_ref : ty:: TraitRef < ' tcx > ,
636
+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
576
637
) -> Vec < TyOrConstInferVar < ' tcx > > {
577
638
selcx
578
639
. infcx ( )
579
640
. resolve_vars_if_possible ( & trait_ref)
641
+ . skip_binder ( )
580
642
. substs
581
643
. iter ( )
582
644
// FIXME(eddyb) try using `skip_current_subtree` to skip everything that
0 commit comments