]> git.lizzy.rs Git - rust.git/blob - src/librustc/traits/query/evaluate_obligation.rs
Rollup merge of #50257 - estebank:fix-49560, r=nikomatsakis
[rust.git] / src / librustc / traits / query / evaluate_obligation.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use infer::InferCtxt;
12 use infer::canonical::{Canonical, Canonicalize};
13 use traits::{EvaluationResult, PredicateObligation, SelectionContext,
14              TraitQueryMode, OverflowError};
15 use traits::query::CanonicalPredicateGoal;
16 use ty::{ParamEnvAnd, Predicate, TyCtxt};
17
18 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
19     /// Evaluates whether the predicate can be satisfied (by any means)
20     /// in the given `ParamEnv`.
21     pub fn predicate_may_hold(
22         &self,
23         obligation: &PredicateObligation<'tcx>,
24     ) -> bool {
25         self.evaluate_obligation(obligation).may_apply()
26     }
27
28     /// Evaluates whether the predicate can be satisfied in the given
29     /// `ParamEnv`, and returns `false` if not certain. However, this is
30     /// not entirely accurate if inference variables are involved.
31     pub fn predicate_must_hold(
32         &self,
33         obligation: &PredicateObligation<'tcx>,
34     ) -> bool {
35         self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
36     }
37
38     // Helper function that canonicalizes and runs the query, as well as handles
39     // overflow.
40     fn evaluate_obligation(
41         &self,
42         obligation: &PredicateObligation<'tcx>,
43     ) -> EvaluationResult {
44         let (c_pred, _) =
45             self.canonicalize_query(&obligation.param_env.and(obligation.predicate));
46         // Run canonical query. If overflow occurs, rerun from scratch but this time
47         // in standard trait query mode so that overflow is handled appropriately
48         // within `SelectionContext`.
49         match self.tcx.global_tcx().evaluate_obligation(c_pred) {
50             Ok(result) => result,
51             Err(OverflowError) => {
52                 let mut selcx =
53                     SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
54                 selcx.evaluate_obligation_recursively(obligation)
55                      .expect("Overflow should be caught earlier in standard query mode")
56             }
57         }
58     }
59 }
60
61 impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ParamEnvAnd<'tcx, Predicate<'tcx>> {
62     type Canonicalized = CanonicalPredicateGoal<'gcx>;
63
64     fn intern(
65         _gcx: TyCtxt<'_, 'gcx, 'gcx>,
66         value: Canonical<'gcx, Self::Lifted>,
67     ) -> Self::Canonicalized {
68         value
69     }
70 }