@@ -17,7 +17,7 @@ use self::EvaluationResult::*;
17
17
18
18
use super :: coherence:: { self , Conflict } ;
19
19
use super :: DerivedObligationCause ;
20
- use super :: IntercrateMode ;
20
+ use super :: { IntercrateMode , TraitQueryMode } ;
21
21
use super :: project;
22
22
use super :: project:: { normalize_with_depth, Normalized , ProjectionCacheKey } ;
23
23
use super :: { PredicateObligation , TraitObligation , ObligationCause } ;
@@ -87,7 +87,12 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
87
87
/// Controls whether or not to filter out negative impls when selecting.
88
88
/// This is used in librustdoc to distinguish between the lack of an impl
89
89
/// and a negative impl
90
- allow_negative_impls : bool
90
+ allow_negative_impls : bool ,
91
+
92
+ /// The mode that trait queries run in, which informs our error handling
93
+ /// policy. In essence, canonicalized queries need their errors propagated
94
+ /// rather than immediately reported because we do not have accurate spans.
95
+ query_mode : TraitQueryMode ,
91
96
}
92
97
93
98
#[ derive( Clone , Debug ) ]
@@ -440,6 +445,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
440
445
intercrate : None ,
441
446
intercrate_ambiguity_causes : None ,
442
447
allow_negative_impls : false ,
448
+ query_mode : TraitQueryMode :: Standard ,
443
449
}
444
450
}
445
451
@@ -452,6 +458,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
452
458
intercrate : Some ( mode) ,
453
459
intercrate_ambiguity_causes : None ,
454
460
allow_negative_impls : false ,
461
+ query_mode : TraitQueryMode :: Standard ,
455
462
}
456
463
}
457
464
@@ -464,6 +471,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
464
471
intercrate : None ,
465
472
intercrate_ambiguity_causes : None ,
466
473
allow_negative_impls,
474
+ query_mode : TraitQueryMode :: Standard ,
475
+ }
476
+ }
477
+
478
+ pub fn with_query_mode ( infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
479
+ query_mode : TraitQueryMode ) -> SelectionContext < ' cx , ' gcx , ' tcx > {
480
+ debug ! ( "with_query_mode({:?})" , query_mode) ;
481
+ SelectionContext {
482
+ infcx,
483
+ freshener : infcx. freshener ( ) ,
484
+ intercrate : None ,
485
+ intercrate_ambiguity_causes : None ,
486
+ allow_negative_impls : false ,
487
+ query_mode,
467
488
}
468
489
}
469
490
@@ -548,17 +569,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
548
569
549
570
let stack = self . push_stack ( TraitObligationStackList :: empty ( ) , obligation) ;
550
571
572
+ // `select` is currently only called in standard query mode
573
+ assert ! ( self . query_mode == TraitQueryMode :: Standard ) ;
574
+
551
575
let candidate = match self . candidate_from_obligation ( & stack) {
552
- Err ( SelectionError :: Overflow ( o ) ) =>
553
- self . infcx ( ) . report_overflow_error ( & o , true ) ,
576
+ Err ( SelectionError :: Overflow ( _ ) ) =>
577
+ bug ! ( "Overflow should be caught earlier in standard query mode" ) ,
554
578
Err ( e) => { return Err ( e) ; } ,
555
579
Ok ( None ) => { return Ok ( None ) ; } ,
556
580
Ok ( Some ( candidate) ) => candidate
557
581
} ;
558
582
559
583
match self . confirm_candidate ( obligation, candidate) {
560
- Err ( SelectionError :: Overflow ( o ) ) =>
561
- self . infcx ( ) . report_overflow_error ( & o , true ) ,
584
+ Err ( SelectionError :: Overflow ( _ ) ) =>
585
+ bug ! ( "Overflow should be caught earlier in standard query mode" ) ,
562
586
Err ( e) => Err ( e) ,
563
587
Ok ( candidate) => Ok ( Some ( candidate) )
564
588
}
@@ -582,10 +606,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
582
606
debug ! ( "predicate_may_hold_fatal({:?})" ,
583
607
obligation) ;
584
608
585
- match self . evaluate_obligation_recursively ( obligation) {
586
- Ok ( result) => result. may_apply ( ) ,
587
- Err ( OverflowError ( o) ) => self . infcx ( ) . report_overflow_error ( & o, true )
588
- }
609
+ // This fatal query is a stopgap that should only be used in standard mode,
610
+ // where we do not expect overflow to be propagated.
611
+ assert ! ( self . query_mode == TraitQueryMode :: Standard ) ;
612
+
613
+ self . evaluate_obligation_recursively ( obligation)
614
+ . expect ( "Overflow should be caught earlier in standard query mode" )
615
+ . may_apply ( )
589
616
}
590
617
591
618
/// Evaluates whether the obligation `obligation` can be satisfied and returns
@@ -1024,7 +1051,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1024
1051
// not update) the cache.
1025
1052
let recursion_limit = * self . infcx . tcx . sess . recursion_limit . get ( ) ;
1026
1053
if stack. obligation . recursion_depth >= recursion_limit {
1027
- return Err ( Overflow ( stack. obligation . clone ( ) ) ) ;
1054
+ match self . query_mode {
1055
+ TraitQueryMode :: Standard => {
1056
+ self . infcx ( ) . report_overflow_error ( & stack. obligation , true ) ;
1057
+ } ,
1058
+ TraitQueryMode :: Canonical => {
1059
+ return Err ( Overflow ( stack. obligation . clone ( ) ) ) ;
1060
+ } ,
1061
+ }
1028
1062
}
1029
1063
1030
1064
// Check the cache. Note that we skolemize the trait-ref
0 commit comments