@@ -17,7 +17,7 @@ use self::EvaluationResult::*;
1717
1818use super :: coherence:: { self , Conflict } ;
1919use super :: DerivedObligationCause ;
20- use super :: IntercrateMode ;
20+ use super :: { IntercrateMode , TraitQueryMode } ;
2121use super :: project;
2222use super :: project:: { normalize_with_depth, Normalized , ProjectionCacheKey } ;
2323use super :: { PredicateObligation , TraitObligation , ObligationCause } ;
@@ -87,7 +87,12 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
8787 /// Controls whether or not to filter out negative impls when selecting.
8888 /// This is used in librustdoc to distinguish between the lack of an impl
8989 /// 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 ,
9196}
9297
9398#[ derive( Clone , Debug ) ]
@@ -440,6 +445,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
440445 intercrate : None ,
441446 intercrate_ambiguity_causes : None ,
442447 allow_negative_impls : false ,
448+ query_mode : TraitQueryMode :: Standard ,
443449 }
444450 }
445451
@@ -452,6 +458,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
452458 intercrate : Some ( mode) ,
453459 intercrate_ambiguity_causes : None ,
454460 allow_negative_impls : false ,
461+ query_mode : TraitQueryMode :: Standard ,
455462 }
456463 }
457464
@@ -464,6 +471,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
464471 intercrate : None ,
465472 intercrate_ambiguity_causes : None ,
466473 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,
467488 }
468489 }
469490
@@ -548,17 +569,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
548569
549570 let stack = self . push_stack ( TraitObligationStackList :: empty ( ) , obligation) ;
550571
572+ // `select` is currently only called in standard query mode
573+ assert ! ( self . query_mode == TraitQueryMode :: Standard ) ;
574+
551575 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" ) ,
554578 Err ( e) => { return Err ( e) ; } ,
555579 Ok ( None ) => { return Ok ( None ) ; } ,
556580 Ok ( Some ( candidate) ) => candidate
557581 } ;
558582
559583 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" ) ,
562586 Err ( e) => Err ( e) ,
563587 Ok ( candidate) => Ok ( Some ( candidate) )
564588 }
@@ -582,10 +606,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
582606 debug ! ( "predicate_may_hold_fatal({:?})" ,
583607 obligation) ;
584608
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 ( )
589616 }
590617
591618 /// Evaluates whether the obligation `obligation` can be satisfied and returns
@@ -1024,7 +1051,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10241051 // not update) the cache.
10251052 let recursion_limit = * self . infcx . tcx . sess . recursion_limit . get ( ) ;
10261053 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+ }
10281062 }
10291063
10301064 // Check the cache. Note that we skolemize the trait-ref
0 commit comments