3 use super::{Certainty, InferCtxtEvalExt};
7 query::NoSolution, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
8 SelectionError, TraitEngine,
12 /// A trait engine using the new trait solver.
14 /// This is mostly identical to how `evaluate_all` works inside of the
15 /// solver, except that the requirements are slightly different.
17 /// Unlike `evaluate_all` it is possible to add new obligations later on
18 /// and we also have to track diagnostics information by using `Obligation`
19 /// instead of `Goal`.
21 /// It is also likely that we want to use slightly different datastructures
22 /// here as this will have to deal with far more root goals than `evaluate_all`.
23 pub struct FulfillmentCtxt<'tcx> {
24 obligations: Vec<PredicateObligation<'tcx>>,
27 impl<'tcx> FulfillmentCtxt<'tcx> {
28 pub fn new() -> FulfillmentCtxt<'tcx> {
29 FulfillmentCtxt { obligations: Vec::new() }
33 impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
34 fn register_predicate_obligation(
36 _infcx: &InferCtxt<'tcx>,
37 obligation: PredicateObligation<'tcx>,
39 self.obligations.push(obligation);
42 fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
43 let errors = self.select_where_possible(infcx);
44 if !errors.is_empty() {
50 .map(|obligation| FulfillmentError {
51 obligation: obligation.clone(),
52 code: FulfillmentErrorCode::CodeAmbiguity,
53 root_obligation: obligation,
58 fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
59 let mut errors = Vec::new();
61 if !infcx.tcx.recursion_limit().value_within_limit(i) {
62 unimplemented!("overflowed on pending obligations: {:?}", self.obligations);
65 let mut has_changed = false;
66 for obligation in mem::take(&mut self.obligations) {
67 let goal = obligation.clone().into();
68 let (changed, certainty) = match infcx.evaluate_root_goal(goal) {
71 errors.push(FulfillmentError {
72 obligation: obligation.clone(),
73 code: FulfillmentErrorCode::CodeSelectionError(
74 SelectionError::Unimplemented,
76 root_obligation: obligation,
82 has_changed |= changed;
85 Certainty::Maybe(_) => self.obligations.push(obligation),
97 fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
98 self.obligations.clone()