]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | use rustc_middle::ty; |
2 | ||
9fa01778 | 3 | use crate::infer::canonical::OriginalQueryValues; |
dfeec247 | 4 | use crate::infer::InferCtxt; |
e1599b0c | 5 | use crate::traits::{ |
dfeec247 | 6 | EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode, |
e1599b0c | 7 | }; |
83c7162d | 8 | |
ba9703b0 XL |
9 | pub 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 | 34 | impl<'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 | } |