6 query::NoSolution, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
7 SelectionError, TraitEngine,
11 use super::{search_graph, Certainty, EvalCtxt};
13 /// A trait engine using the new trait solver.
15 /// This is mostly identical to how `evaluate_all` works inside of the
16 /// solver, except that the requirements are slightly different.
18 /// Unlike `evaluate_all` it is possible to add new obligations later on
19 /// and we also have to track diagnostics information by using `Obligation`
20 /// instead of `Goal`.
22 /// It is also likely that we want to use slightly different datastructures
23 /// here as this will have to deal with far more root goals than `evaluate_all`.
24 pub struct FulfillmentCtxt<'tcx> {
25 obligations: Vec<PredicateObligation<'tcx>>,
28 impl<'tcx> FulfillmentCtxt<'tcx> {
29 pub fn new() -> FulfillmentCtxt<'tcx> {
30 FulfillmentCtxt { obligations: Vec::new() }
34 impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
35 fn register_predicate_obligation(
37 _infcx: &InferCtxt<'tcx>,
38 obligation: PredicateObligation<'tcx>,
40 self.obligations.push(obligation);
43 fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
44 let errors = self.select_where_possible(infcx);
45 if !errors.is_empty() {
51 .map(|obligation| FulfillmentError {
52 obligation: obligation.clone(),
53 code: FulfillmentErrorCode::CodeAmbiguity,
54 root_obligation: obligation,
59 fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
60 let mut errors = Vec::new();
62 if !infcx.tcx.recursion_limit().value_within_limit(i) {
63 unimplemented!("overflowed on pending obligations: {:?}", self.obligations);
66 let mut has_changed = false;
67 for obligation in mem::take(&mut self.obligations) {
68 let goal = obligation.clone().into();
69 let search_graph = &mut search_graph::SearchGraph::new(infcx.tcx);
70 let mut ecx = EvalCtxt::new_outside_solver(infcx, search_graph);
71 let (changed, certainty) = match ecx.evaluate_goal(goal) {
74 errors.push(FulfillmentError {
75 obligation: obligation.clone(),
76 code: FulfillmentErrorCode::CodeSelectionError(
77 SelectionError::Unimplemented,
79 root_obligation: obligation,
85 has_changed |= changed;
88 Certainty::Maybe(_) => self.obligations.push(obligation),
100 fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
101 self.obligations.clone()