2 use rustc_session::config::TraitSolver;
4 use crate::infer::canonical::OriginalQueryValues;
5 use crate::infer::InferCtxt;
6 use crate::solve::{Certainty, Goal, InferCtxtEvalExt, MaybeCause};
7 use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
9 pub trait InferCtxtExt<'tcx> {
10 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
12 fn predicate_must_hold_considering_regions(
14 obligation: &PredicateObligation<'tcx>,
17 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
19 fn evaluate_obligation(
21 obligation: &PredicateObligation<'tcx>,
22 ) -> Result<EvaluationResult, OverflowError>;
24 // Helper function that canonicalizes and runs the query. If an
25 // overflow results, we re-run it in the local context so we can
26 // report a nice error.
28 fn evaluate_obligation_no_overflow(
30 obligation: &PredicateObligation<'tcx>,
31 ) -> EvaluationResult;
34 impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
35 /// Evaluates whether the predicate can be satisfied (by any means)
36 /// in the given `ParamEnv`.
37 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
38 self.evaluate_obligation_no_overflow(obligation).may_apply()
41 /// Evaluates whether the predicate can be satisfied in the given
42 /// `ParamEnv`, and returns `false` if not certain. However, this is
43 /// not entirely accurate if inference variables are involved.
45 /// This version may conservatively fail when outlives obligations
47 fn predicate_must_hold_considering_regions(
49 obligation: &PredicateObligation<'tcx>,
51 self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
54 /// Evaluates whether the predicate can be satisfied in the given
55 /// `ParamEnv`, and returns `false` if not certain. However, this is
56 /// not entirely accurate if inference variables are involved.
58 /// This version ignores all outlives constraints.
59 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
60 self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
63 /// Evaluate a given predicate, capturing overflow and propagating it back.
64 fn evaluate_obligation(
66 obligation: &PredicateObligation<'tcx>,
67 ) -> Result<EvaluationResult, OverflowError> {
68 let mut _orig_values = OriginalQueryValues::default();
70 let param_env = match obligation.predicate.kind().skip_binder() {
71 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
72 // we ignore the value set to it.
73 let mut _constness = pred.constness;
76 .with_constness(_constness.and(obligation.param_env.constness()))
78 // constness has no effect on the given predicate.
79 _ => obligation.param_env.without_const(),
82 if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
83 let c_pred = self.canonicalize_query_keep_static(
84 param_env.and(obligation.predicate),
87 self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
89 self.probe(|snapshot| {
90 if let Ok((_, certainty)) =
91 self.evaluate_root_goal(Goal::new(self.tcx, param_env, obligation.predicate))
95 if self.opaque_types_added_in_snapshot(snapshot) {
96 Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
97 } else if self.region_constraints_added_in_snapshot(snapshot).is_some()
99 Ok(EvaluationResult::EvaluatedToOkModuloRegions)
101 Ok(EvaluationResult::EvaluatedToOk)
104 Certainty::Maybe(MaybeCause::Ambiguity) => {
105 Ok(EvaluationResult::EvaluatedToAmbig)
107 Certainty::Maybe(MaybeCause::Overflow) => Err(OverflowError::Canonical),
110 Ok(EvaluationResult::EvaluatedToErr)
116 // Helper function that canonicalizes and runs the query. If an
117 // overflow results, we re-run it in the local context so we can
118 // report a nice error.
119 fn evaluate_obligation_no_overflow(
121 obligation: &PredicateObligation<'tcx>,
122 ) -> EvaluationResult {
123 // Run canonical query. If overflow occurs, rerun from scratch but this time
124 // in standard trait query mode so that overflow is handled appropriately
125 // within `SelectionContext`.
126 match self.evaluate_obligation(obligation) {
127 Ok(result) => result,
128 Err(OverflowError::Canonical) => {
129 let mut selcx = SelectionContext::new(&self);
130 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r {
131 OverflowError::Canonical => {
133 obligation.cause.span,
134 "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
139 OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
140 OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
143 Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
144 Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,