diff options
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/traits/project.rs | 2 | ||||
| -rw-r--r-- | src/librustc/traits/query/evaluate_obligation.rs | 32 | ||||
| -rw-r--r-- | src/librustc/traits/select.rs | 5 | ||||
| -rw-r--r-- | src/librustc/traits/structural_impls.rs | 2 |
4 files changed, 30 insertions, 11 deletions
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index e50f59cbc82..d5e887f2424 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -894,7 +894,7 @@ fn project_type<'cx, 'gcx, 'tcx>( let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); if obligation.recursion_depth >= recursion_limit { debug!("project: overflow!"); - selcx.infcx().report_overflow_error(&obligation, true); + return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); } let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 6bd92678362..f573b1ef45e 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -20,7 +20,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, ) -> bool { - self.evaluate_obligation(obligation).may_apply() + self.evaluate_obligation_no_overflow(obligation).may_apply() } /// Evaluates whether the predicate can be satisfied in the given @@ -30,28 +30,44 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, ) -> bool { - self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk + self.evaluate_obligation_no_overflow(obligation) == EvaluationResult::EvaluatedToOk } - // Helper function that canonicalizes and runs the query, as well as handles - // overflow. - fn evaluate_obligation( + /// Evaluate a given predicate, capturing overflow and propagating it back. + pub fn evaluate_obligation( &self, obligation: &PredicateObligation<'tcx>, - ) -> EvaluationResult { + ) -> Result<EvaluationResult, OverflowError> { let mut _orig_values = SmallVec::new(); let c_pred = self.canonicalize_query(&obligation.param_env.and(obligation.predicate), &mut _orig_values); // Run canonical query. If overflow occurs, rerun from scratch but this time // in standard trait query mode so that overflow is handled appropriately // within `SelectionContext`. - match self.tcx.global_tcx().evaluate_obligation(c_pred) { + self.tcx.global_tcx().evaluate_obligation(c_pred) + } + + // Helper function that canonicalizes and runs the query. If an + // overflow results, we re-run it in the local context so we can + // report a nice error. + fn evaluate_obligation_no_overflow( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> EvaluationResult { + match self.evaluate_obligation(obligation) { Ok(result) => result, Err(OverflowError) => { let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard); selcx.evaluate_obligation_recursively(obligation) - .expect("Overflow should be caught earlier in standard query mode") + .unwrap_or_else(|r| { + span_bug!( + obligation.cause.span, + "Overflow should be caught earlier in standard query mode: {:?}, {:?}", + obligation, + r, + ) + }) } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 232ef108537..706d038812e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1376,7 +1376,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { - if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { + if let Err(Overflow) = candidate { + // Don't cache overflow globally; we only produce this + // in certain modes. + } else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { if let Some(candidate) = tcx.lift_to_global(&candidate) { debug!( "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global", diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 10e930d1c92..6b0b1c35a7e 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> { super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure( err.into(), )), - super::Overflow => bug!(), // FIXME: ape ConstEvalFailure? + super::Overflow => Some(super::Overflow), } } } |
