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 /// Go over the list of pending obligations and try to evaluate them.
76 ///
77 /// For each result:
78 /// Ok: remove the obligation from the list
79 /// Ambiguous: leave the obligation in the list to be evaluated later
80 /// Err: remove the obligation from the list and return an error
81 ///
82 /// Returns a list of errors from obligations that evaluated to Err.
83 #[must_use]
84 fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
85
86 fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
87
88 /// Evaluate all pending obligations, return error if they can't be evaluated.
89 ///
90 /// For each result:
91 /// Ok: remove the obligation from the list
92 /// Ambiguous: remove the obligation from the list and return an error
93 /// Err: remove the obligation from the list and return an error
94 ///
95 /// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
96 #[must_use]
97 fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
98 let errors = self.select_where_possible(infcx);
99 if !errors.is_empty() {
100 return errors;
101 }
102
103 self.collect_remaining_errors(infcx)
104 }
105
106 fn has_pending_obligations(&self) -> bool;
107
108 fn pending_obligations(&self) -> PredicateObligations<'tcx>;
109
110 /// Among all pending obligations, collect those are stalled on a inference variable which has
111 /// changed since the last call to `select_where_possible`. Those obligations are marked as
112 /// successful and returned.
113 fn drain_stalled_obligations_for_coroutines(
114 &mut self,
115 infcx: &InferCtxt<'tcx>,
116 ) -> PredicateObligations<'tcx>;
117}
118
119pub trait FromSolverError<'tcx, E>: Debug + 'tcx {
120 fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
121}