]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / query / evaluate_obligation.rs
CommitLineData
a2a8927a
XL
1use rustc_middle::ty;
2
9fa01778 3use crate::infer::canonical::OriginalQueryValues;
dfeec247 4use crate::infer::InferCtxt;
e1599b0c 5use crate::traits::{
dfeec247 6 EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
e1599b0c 7};
83c7162d 8
ba9703b0
XL
9pub trait InferCtxtExt<'tcx> {
10 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
11
12 fn predicate_must_hold_considering_regions(
13 &self,
14 obligation: &PredicateObligation<'tcx>,
15 ) -> bool;
16
17 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
18
19 fn evaluate_obligation(
20 &self,
21 obligation: &PredicateObligation<'tcx>,
22 ) -> Result<EvaluationResult, OverflowError>;
23
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.
27 /*crate*/
28 fn evaluate_obligation_no_overflow(
29 &self,
30 obligation: &PredicateObligation<'tcx>,
31 ) -> EvaluationResult;
32}
33
2b03887a 34impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
83c7162d
XL
35 /// Evaluates whether the predicate can be satisfied (by any means)
36 /// in the given `ParamEnv`.
ba9703b0 37 fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
0bf4aa26 38 self.evaluate_obligation_no_overflow(obligation).may_apply()
83c7162d
XL
39 }
40
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.
0731742a
XL
44 ///
45 /// This version may conservatively fail when outlives obligations
46 /// are required.
ba9703b0 47 fn predicate_must_hold_considering_regions(
0731742a
XL
48 &self,
49 obligation: &PredicateObligation<'tcx>,
50 ) -> bool {
51 self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
52 }
53
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.
57 ///
58 /// This version ignores all outlives constraints.
ba9703b0 59 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
0731742a 60 self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
83c7162d
XL
61 }
62
0bf4aa26 63 /// Evaluate a given predicate, capturing overflow and propagating it back.
ba9703b0 64 fn evaluate_obligation(
83c7162d
XL
65 &self,
66 obligation: &PredicateObligation<'tcx>,
0bf4aa26
XL
67 ) -> Result<EvaluationResult, OverflowError> {
68 let mut _orig_values = OriginalQueryValues::default();
a2a8927a
XL
69
70 let param_env = match obligation.predicate.kind().skip_binder() {
71 ty::PredicateKind::Trait(pred) => {
72 // we ignore the value set to it.
73 let mut _constness = pred.constness;
74 obligation
75 .param_env
76 .with_constness(_constness.and(obligation.param_env.constness()))
77 }
78 // constness has no effect on the given predicate.
79 _ => obligation.param_env.without_const(),
80 };
81
82 let c_pred = self
83 .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
83c7162d
XL
84 // Run canonical query. If overflow occurs, rerun from scratch but this time
85 // in standard trait query mode so that overflow is handled appropriately
86 // within `SelectionContext`.
064997fb 87 self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
0bf4aa26
XL
88 }
89
90 // Helper function that canonicalizes and runs the query. If an
91 // overflow results, we re-run it in the local context so we can
92 // report a nice error.
ba9703b0 93 fn evaluate_obligation_no_overflow(
0bf4aa26
XL
94 &self,
95 obligation: &PredicateObligation<'tcx>,
96 ) -> EvaluationResult {
97 match self.evaluate_obligation(obligation) {
83c7162d 98 Ok(result) => result,
c295e0f8 99 Err(OverflowError::Canonical) => {
dfeec247 100 let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
c295e0f8
XL
101 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r {
102 OverflowError::Canonical => {
103 span_bug!(
104 obligation.cause.span,
105 "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
106 obligation,
107 r,
108 )
109 }
110 OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
5e7ed085 111 OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
dfeec247 112 })
83c7162d 113 }
c295e0f8 114 Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
5e7ed085 115 Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
83c7162d
XL
116 }
117 }
118}