&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
&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 =
// FIXME(eddyb) ignoring `obligations` might cause false positives.
drop(obligations);
- let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
- cause.clone(),
- param_env,
- trait_ref.to_predicate(),
- ));
+ debug!(
+ "invoking predicate_may_hold: {:?}",
+ trait_ref,
+ );
+ let may_apply = match infcx.evaluate_obligation(
+ &traits::Obligation::new(
+ cause.clone(),
+ param_env,
+ trait_ref.to_predicate(),
+ ),
+ ) {
+ Ok(eval_result) => eval_result.may_apply(),
+ Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
+ };
if !may_apply {
return
}