]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
Auto merge of #75936 - sdroege:chunks-exact-construction-bounds-check, r=nagisa
[rust.git] / compiler / rustc_trait_selection / src / traits / query / evaluate_obligation.rs
1 use crate::infer::canonical::OriginalQueryValues;
2 use crate::infer::InferCtxt;
3 use crate::traits::{
4     EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
5 };
6
7 pub trait InferCtxtExt<'tcx> {
8     fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
9
10     fn predicate_must_hold_considering_regions(
11         &self,
12         obligation: &PredicateObligation<'tcx>,
13     ) -> bool;
14
15     fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
16
17     fn evaluate_obligation(
18         &self,
19         obligation: &PredicateObligation<'tcx>,
20     ) -> Result<EvaluationResult, OverflowError>;
21
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.
25     /*crate*/
26     fn evaluate_obligation_no_overflow(
27         &self,
28         obligation: &PredicateObligation<'tcx>,
29     ) -> EvaluationResult;
30 }
31
32 impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, '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()
37     }
38
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.
42     ///
43     /// This version may conservatively fail when outlives obligations
44     /// are required.
45     fn predicate_must_hold_considering_regions(
46         &self,
47         obligation: &PredicateObligation<'tcx>,
48     ) -> bool {
49         self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
50     }
51
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.
55     ///
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()
59     }
60
61     /// Evaluate a given predicate, capturing overflow and propagating it back.
62     fn evaluate_obligation(
63         &self,
64         obligation: &PredicateObligation<'tcx>,
65     ) -> Result<EvaluationResult, OverflowError> {
66         let mut _orig_values = OriginalQueryValues::default();
67         let c_pred = self
68             .canonicalize_query(&obligation.param_env.and(obligation.predicate), &mut _orig_values);
69         // Run canonical query. If overflow occurs, rerun from scratch but this time
70         // in standard trait query mode so that overflow is handled appropriately
71         // within `SelectionContext`.
72         self.tcx.evaluate_obligation(c_pred)
73     }
74
75     // Helper function that canonicalizes and runs the query. If an
76     // overflow results, we re-run it in the local context so we can
77     // report a nice error.
78     fn evaluate_obligation_no_overflow(
79         &self,
80         obligation: &PredicateObligation<'tcx>,
81     ) -> EvaluationResult {
82         match self.evaluate_obligation(obligation) {
83             Ok(result) => result,
84             Err(OverflowError) => {
85                 let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
86                 selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| {
87                     span_bug!(
88                         obligation.cause.span,
89                         "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
90                         obligation,
91                         r,
92                     )
93                 })
94             }
95         }
96     }
97 }