rustc_infer/traits/
engine.rs

1use std::fmt::Debug;
2
3use rustc_hir::def_id::DefId;
4use rustc_middle::ty::{self, Ty, Upcast};
5
6use super::{ObligationCause, PredicateObligation, PredicateObligations};
7use crate::infer::InferCtxt;
8use crate::traits::Obligation;
9
10/// A trait error with most of its information removed. This is the error
11/// returned by an `ObligationCtxt` by default, and suitable if you just
12/// want to see if a predicate holds, and don't particularly care about the
13/// error itself (except for if it's an ambiguity or true error).
14///
15/// use `ObligationCtxt::new_with_diagnostics` to get a `FulfillmentError`.
16#[derive(Clone, Debug)]
17pub enum ScrubbedTraitError<'tcx> {
18    /// A real error. This goal definitely does not hold.
19    TrueError,
20    /// An ambiguity. This goal may hold if further inference is done.
21    Ambiguity,
22    /// An old-solver-style cycle error, which will fatal. This is not
23    /// returned by the new solver.
24    Cycle(PredicateObligations<'tcx>),
25}
26
27impl<'tcx> ScrubbedTraitError<'tcx> {
28    pub fn is_true_error(&self) -> bool {
29        match self {
30            ScrubbedTraitError::TrueError => true,
31            ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
32        }
33    }
34}
35
36pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
37    /// Requires that `ty` must implement the trait with `def_id` in
38    /// the given environment. This trait must not have any type
39    /// parameters (except for `Self`).
40    fn register_bound(
41        &mut self,
42        infcx: &InferCtxt<'tcx>,
43        param_env: ty::ParamEnv<'tcx>,
44        ty: Ty<'tcx>,
45        def_id: DefId,
46        cause: ObligationCause<'tcx>,
47    ) {
48        let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
49        self.register_predicate_obligation(
50            infcx,
51            Obligation {
52                cause,
53                recursion_depth: 0,
54                param_env,
55                predicate: trait_ref.upcast(infcx.tcx),
56            },
57        );
58    }
59
60    fn register_predicate_obligation(
61        &mut self,
62        infcx: &InferCtxt<'tcx>,
63        obligation: PredicateObligation<'tcx>,
64    );
65
66    fn register_predicate_obligations(
67        &mut self,
68        infcx: &InferCtxt<'tcx>,
69        obligations: PredicateObligations<'tcx>,
70    ) {
71        for obligation in obligations {
72            self.register_predicate_obligation(infcx, obligation);
73        }
74    }
75
76    /// Go over the list of pending obligations and try to evaluate them.
77    ///
78    /// For each result:
79    /// Ok: remove the obligation from the list
80    /// Ambiguous: leave the obligation in the list to be evaluated later
81    /// Err: remove the obligation from the list and return an error
82    ///
83    /// Returns a list of errors from obligations that evaluated to Err.
84    #[must_use]
85    fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
86
87    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
88
89    /// Evaluate all pending obligations, return error if they can't be evaluated.
90    ///
91    /// For each result:
92    /// Ok: remove the obligation from the list
93    /// Ambiguous: remove the obligation from the list and return an error
94    /// Err: remove the obligation from the list and return an error
95    ///
96    /// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
97    #[must_use]
98    fn evaluate_obligations_error_on_ambiguity(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
99        let errors = self.try_evaluate_obligations(infcx);
100        if !errors.is_empty() {
101            return errors;
102        }
103
104        self.collect_remaining_errors(infcx)
105    }
106
107    fn has_pending_obligations(&self) -> bool;
108
109    fn pending_obligations(&self) -> PredicateObligations<'tcx>;
110
111    /// Among all pending obligations, collect those are stalled on a inference variable which has
112    /// changed since the last call to `try_evaluate_obligations`. Those obligations are marked as
113    /// successful and returned.
114    fn drain_stalled_obligations_for_coroutines(
115        &mut self,
116        infcx: &InferCtxt<'tcx>,
117    ) -> PredicateObligations<'tcx>;
118}
119
120pub trait FromSolverError<'tcx, E>: Debug + 'tcx {
121    fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
122}