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.
23    Cycle(PredicateObligations<'tcx>),
24}
25
26impl<'tcx> ScrubbedTraitError<'tcx> {
27    pub fn is_true_error(&self) -> bool {
28        match self {
29            ScrubbedTraitError::TrueError => true,
30            ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
31        }
32    }
33}
34
35pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
36    /// Requires that `ty` must implement the trait with `def_id` in
37    /// the given environment. This trait must not have any type
38    /// parameters (except for `Self`).
39    fn register_bound(
40        &mut self,
41        infcx: &InferCtxt<'tcx>,
42        param_env: ty::ParamEnv<'tcx>,
43        ty: Ty<'tcx>,
44        def_id: DefId,
45        cause: ObligationCause<'tcx>,
46    ) {
47        let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
48        self.register_predicate_obligation(
49            infcx,
50            Obligation {
51                cause,
52                recursion_depth: 0,
53                param_env,
54                predicate: trait_ref.upcast(infcx.tcx),
55            },
56        );
57    }
58
59    fn register_predicate_obligation(
60        &mut self,
61        infcx: &InferCtxt<'tcx>,
62        obligation: PredicateObligation<'tcx>,
63    );
64
65    fn register_predicate_obligations(
66        &mut self,
67        infcx: &InferCtxt<'tcx>,
68        obligations: PredicateObligations<'tcx>,
69    ) {
70        for obligation in obligations {
71            self.register_predicate_obligation(infcx, obligation);
72        }
73    }
74
75    #[must_use]
76    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
77
78    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
79
80    #[must_use]
81    fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
82        let errors = self.select_where_possible(infcx);
83        if !errors.is_empty() {
84            return errors;
85        }
86
87        self.collect_remaining_errors(infcx)
88    }
89
90    fn has_pending_obligations(&self) -> bool;
91
92    fn pending_obligations(&self) -> PredicateObligations<'tcx>;
93
94    /// Among all pending obligations, collect those are stalled on a inference variable which has
95    /// changed since the last call to `select_where_possible`. Those obligations are marked as
96    /// successful and returned.
97    fn drain_unstalled_obligations(
98        &mut self,
99        infcx: &InferCtxt<'tcx>,
100    ) -> PredicateObligations<'tcx>;
101}
102
103pub trait FromSolverError<'tcx, E>: Debug + 'tcx {
104    fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
105}