3 use crate::infer::canonical::OriginalQueryValues;
4 use crate::infer::InferCtxt;
5 use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
7 pub trait InferCtxtExt<'tcx> {
8 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
10 fn predicate_must_hold_considering_regions(
12 obligation: &PredicateObligation<'tcx>,
15 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
17 fn evaluate_obligation(
19 obligation: &PredicateObligation<'tcx>,
20 ) -> Result<EvaluationResult, OverflowError>;
22 // Helper function that canonicalizes and runs the query. If an
23 // overflow results, we re-run it in the local context so we can
24 // report a nice error.
26 fn evaluate_obligation_no_overflow(
28 obligation: &PredicateObligation<'tcx>,
29 ) -> EvaluationResult;
32 impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
33 /// Evaluates whether the predicate can be satisfied (by any means)
34 /// in the given `ParamEnv`.
35 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
36 self.evaluate_obligation_no_overflow(obligation).may_apply()
39 /// Evaluates whether the predicate can be satisfied in the given
40 /// `ParamEnv`, and returns `false` if not certain. However, this is
41 /// not entirely accurate if inference variables are involved.
43 /// This version may conservatively fail when outlives obligations
45 fn predicate_must_hold_considering_regions(
47 obligation: &PredicateObligation<'tcx>,
49 self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
52 /// Evaluates whether the predicate can be satisfied in the given
53 /// `ParamEnv`, and returns `false` if not certain. However, this is
54 /// not entirely accurate if inference variables are involved.
56 /// This version ignores all outlives constraints.
57 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
58 self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
61 /// Evaluate a given predicate, capturing overflow and propagating it back.
62 fn evaluate_obligation(
64 obligation: &PredicateObligation<'tcx>,
65 ) -> Result<EvaluationResult, OverflowError> {
66 let mut _orig_values = OriginalQueryValues::default();
68 let param_env = match obligation.predicate.kind().skip_binder() {
69 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
70 // we ignore the value set to it.
71 let mut _constness = pred.constness;
74 .with_constness(_constness.and(obligation.param_env.constness()))
76 // constness has no effect on the given predicate.
77 _ => obligation.param_env.without_const(),
81 .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
82 // Run canonical query. If overflow occurs, rerun from scratch but this time
83 // in standard trait query mode so that overflow is handled appropriately
84 // within `SelectionContext`.
85 self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
88 // Helper function that canonicalizes and runs the query. If an
89 // overflow results, we re-run it in the local context so we can
90 // report a nice error.
91 fn evaluate_obligation_no_overflow(
93 obligation: &PredicateObligation<'tcx>,
94 ) -> EvaluationResult {
95 match self.evaluate_obligation(obligation) {
97 Err(OverflowError::Canonical) => {
98 let mut selcx = SelectionContext::new(&self);
99 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r {
100 OverflowError::Canonical => {
102 obligation.cause.span,
103 "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
108 OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
109 OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
112 Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
113 Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,