chalk_engine/
context.rs

1//! Defines traits used to embed the chalk-engine in another crate.
2//!
3//! chalk and rustc both define types which implement the traits in this
4//! module. This allows each user of chalk-engine to define their own
5//! `DomainGoal` type, add arena lifetime parameters, and more. See
6//! [`Context`] trait for a list of types.
7
8use crate::CompleteAnswer;
9use chalk_ir::interner::Interner;
10use chalk_ir::Substitution;
11use std::fmt::Debug;
12
13pub enum AnswerResult<I: Interner> {
14    /// The next available answer.
15    Answer(CompleteAnswer<I>),
16
17    /// No answer could be returned because there are no more solutions.
18    NoMoreSolutions,
19
20    /// No answer could be returned because the goal has floundered.
21    Floundered,
22
23    // No answer could be returned *yet*, because we exceeded our
24    // quantum (`should_continue` returned false).
25    QuantumExceeded,
26}
27
28impl<I: Interner> AnswerResult<I> {
29    pub fn is_answer(&self) -> bool {
30        matches!(self, Self::Answer(_))
31    }
32
33    pub fn answer(self) -> CompleteAnswer<I> {
34        match self {
35            Self::Answer(answer) => answer,
36            _ => panic!("Not an answer."),
37        }
38    }
39
40    pub fn is_no_more_solutions(&self) -> bool {
41        matches!(self, Self::NoMoreSolutions)
42    }
43
44    pub fn is_quantum_exceeded(&self) -> bool {
45        matches!(self, Self::QuantumExceeded)
46    }
47}
48
49impl<I: Interner> Debug for AnswerResult<I> {
50    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        match self {
52            AnswerResult::Answer(answer) => write!(fmt, "{:?}", answer),
53            AnswerResult::Floundered => write!(fmt, "Floundered"),
54            AnswerResult::NoMoreSolutions => write!(fmt, "None"),
55            AnswerResult::QuantumExceeded => write!(fmt, "QuantumExceeded"),
56        }
57    }
58}
59
60pub trait AnswerStream<I: Interner> {
61    /// Gets the next answer for a given goal, but doesn't increment the answer index.
62    /// Calling this or `next_answer` again will give the same answer.
63    fn peek_answer(&mut self, should_continue: impl Fn() -> bool) -> AnswerResult<I>;
64
65    /// Gets the next answer for a given goal, incrementing the answer index.
66    /// Calling this or `peek_answer` again will give the next answer.
67    fn next_answer(&mut self, should_continue: impl Fn() -> bool) -> AnswerResult<I>;
68
69    /// Invokes `test` with each possible future answer, returning true immediately
70    /// if we find any answer for which `test` returns true.
71    fn any_future_answer(&self, test: impl Fn(&Substitution<I>) -> bool) -> bool;
72}