rustc_trait_selection/traits/query/
evaluate_obligation.rs1use rustc_infer::traits::solve::Goal;
2use rustc_macros::extension;
3use rustc_middle::{span_bug, ty};
4use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
5
6use crate::infer::InferCtxt;
7use crate::infer::canonical::OriginalQueryValues;
8use crate::solve::SolverDelegate;
9use crate::traits::{
10 EvaluationResult, ObligationCtxt, OverflowError, PredicateObligation, SelectionContext,
11};
12
13#[extension(pub trait InferCtxtExt<'tcx>)]
14impl<'tcx> InferCtxt<'tcx> {
15 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
18 self.evaluate_obligation_no_overflow(obligation).may_apply()
19 }
20
21 fn predicate_may_hold_opaque_types_jank(&self, obligation: &PredicateObligation<'tcx>) -> bool {
24 if self.next_trait_solver() {
25 self.goal_may_hold_opaque_types_jank(Goal::new(
26 self.tcx,
27 obligation.param_env,
28 obligation.predicate,
29 ))
30 } else {
31 self.predicate_may_hold(obligation)
32 }
33 }
34
35 fn goal_may_hold_opaque_types_jank(&self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> bool {
38 assert!(self.next_trait_solver());
39 <&SolverDelegate<'tcx>>::from(self).root_goal_may_hold_opaque_types_jank(goal)
40 }
41
42 fn predicate_must_hold_considering_regions(
70 &self,
71 obligation: &PredicateObligation<'tcx>,
72 ) -> bool {
73 self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
74 }
75
76 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
82 self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
83 }
84
85 fn evaluate_obligation(
87 &self,
88 obligation: &PredicateObligation<'tcx>,
89 ) -> Result<EvaluationResult, OverflowError> {
90 let mut _orig_values = OriginalQueryValues::default();
91
92 let param_env = obligation.param_env;
93
94 if self.next_trait_solver() {
95 self.probe(|snapshot| {
96 let ocx = ObligationCtxt::new(self);
97 ocx.register_obligation(obligation.clone());
98 let mut result = EvaluationResult::EvaluatedToOk;
99 for error in ocx.evaluate_obligations_error_on_ambiguity() {
100 if error.is_true_error() {
101 return Ok(EvaluationResult::EvaluatedToErr);
102 } else {
103 result = result.max(EvaluationResult::EvaluatedToAmbig);
104 }
105 }
106 if self.opaque_types_added_in_snapshot(snapshot) {
107 result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes);
108 } else if self.region_constraints_added_in_snapshot(snapshot) {
109 result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
110 }
111 Ok(result)
112 })
113 } else {
114 let c_pred =
115 self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values);
116 self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred)
117 }
118 }
119
120 fn evaluate_obligation_no_overflow(
124 &self,
125 obligation: &PredicateObligation<'tcx>,
126 ) -> EvaluationResult {
127 match self.evaluate_obligation(obligation) {
131 Ok(result) => result,
132 Err(OverflowError::Canonical) => {
133 let mut selcx = SelectionContext::new(self);
134 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r {
135 OverflowError::Canonical => {
136 span_bug!(
137 obligation.cause.span,
138 "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
139 obligation,
140 r,
141 )
142 }
143 OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
144 })
145 }
146 Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
147 }
148 }
149}