Skip to content

Commit 65de8b8

Browse files
authored
Merge pull request #211 from nikomatsakis/queryify
decompose chalk logic for query-ification and re-use
2 parents b446010 + ba3ce01 commit 65de8b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2177
-1783
lines changed

.dir-locals.el

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
((rust-mode (rust-format-on-save . t)))

Cargo.lock

Lines changed: 26 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ edition = "2018"
1313
bench = []
1414

1515
[dependencies]
16+
derive-new = "0.5.6"
1617
diff = "0.1.11"
1718
docopt = "1.0.0"
1819
failure = "0.1"
1920
itertools = "0.7.8"
2021
lalrpop-intern = "0.15.1"
21-
petgraph = "0.4.13"
2222
rustyline = "1.0"
2323
salsa = "0.10.0"
2424
serde = "1.0"
@@ -45,4 +45,12 @@ path = "chalk-macros"
4545
version = "0.9.0"
4646
path = "chalk-engine"
4747

48+
[dependencies.chalk-rust-ir]
49+
version = "0.1.0"
50+
path = "chalk-rust-ir"
51+
52+
[dependencies.chalk-rules]
53+
version = "0.1.0"
54+
path = "chalk-rules"
55+
4856
[workspace]

chalk-engine/src/context.rs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,45 @@ pub trait Context: Clone + Debug {
125125
environment: &Self::Environment,
126126
goal: Self::Goal,
127127
) -> Self::GoalInEnvironment;
128+
129+
/// Extracts the inner normalized substitution from a canonical ex-clause.
130+
fn inference_normalized_subst_from_ex_clause(
131+
canon_ex_clause: &Self::CanonicalExClause,
132+
) -> &Self::InferenceNormalizedSubst;
133+
134+
/// Extracts the inner normalized substitution from a canonical constraint subst.
135+
fn inference_normalized_subst_from_subst(
136+
canon_ex_clause: &Self::CanonicalConstrainedSubst,
137+
) -> &Self::InferenceNormalizedSubst;
138+
139+
/// True if this solution has no region constraints.
140+
fn empty_constraints(ccs: &Self::CanonicalConstrainedSubst) -> bool;
141+
142+
fn canonical(u_canon: &Self::UCanonicalGoalInEnvironment) -> &Self::CanonicalGoalInEnvironment;
143+
144+
fn is_trivial_substitution(
145+
u_canon: &Self::UCanonicalGoalInEnvironment,
146+
canonical_subst: &Self::CanonicalConstrainedSubst,
147+
) -> bool;
148+
149+
fn num_universes(_: &Self::UCanonicalGoalInEnvironment) -> usize;
150+
151+
/// Convert a goal G *from* the canonical universes *into* our
152+
/// local universes. This will yield a goal G' that is the same
153+
/// but for the universes of universally quantified names.
154+
fn map_goal_from_canonical(
155+
_: &Self::UniverseMap,
156+
value: &Self::CanonicalGoalInEnvironment,
157+
) -> Self::CanonicalGoalInEnvironment;
158+
159+
/// Convert a substitution *from* the canonical universes *into*
160+
/// our local universes. This will yield a substitution S' that is
161+
/// the same but for the universes of universally quantified
162+
/// names.
163+
fn map_subst_from_canonical(
164+
_: &Self::UniverseMap,
165+
value: &Self::CanonicalConstrainedSubst,
166+
) -> Self::CanonicalConstrainedSubst;
128167
}
129168

130169
pub trait ContextOps<C: Context>: Sized + Clone + Debug + AggregateOps<C> {
@@ -155,43 +194,6 @@ pub trait ContextOps<C: Context>: Sized + Clone + Debug + AggregateOps<C> {
155194
canonical_ex_clause: &C::CanonicalExClause,
156195
op: impl WithInstantiatedExClause<C, Output = R>,
157196
) -> R;
158-
159-
/// Extracts the inner normalized substitution from a canonical ex-clause.
160-
fn inference_normalized_subst_from_ex_clause(
161-
canon_ex_clause: &C::CanonicalExClause,
162-
) -> &C::InferenceNormalizedSubst;
163-
164-
/// Extracts the inner normalized substitution from a canonical constraint subst.
165-
fn inference_normalized_subst_from_subst(
166-
canon_ex_clause: &C::CanonicalConstrainedSubst,
167-
) -> &C::InferenceNormalizedSubst;
168-
169-
/// True if this solution has no region constraints.
170-
fn empty_constraints(ccs: &C::CanonicalConstrainedSubst) -> bool;
171-
172-
fn canonical(u_canon: &C::UCanonicalGoalInEnvironment) -> &C::CanonicalGoalInEnvironment;
173-
fn is_trivial_substitution(
174-
u_canon: &C::UCanonicalGoalInEnvironment,
175-
canonical_subst: &C::CanonicalConstrainedSubst,
176-
) -> bool;
177-
fn num_universes(_: &C::UCanonicalGoalInEnvironment) -> usize;
178-
179-
/// Convert a goal G *from* the canonical universes *into* our
180-
/// local universes. This will yield a goal G' that is the same
181-
/// but for the universes of universally quantified names.
182-
fn map_goal_from_canonical(
183-
_: &C::UniverseMap,
184-
value: &C::CanonicalGoalInEnvironment,
185-
) -> C::CanonicalGoalInEnvironment;
186-
187-
/// Convert a substitution *from* the canonical universes *into*
188-
/// our local universes. This will yield a substitution S' that is
189-
/// the same but for the universes of universally quantified
190-
/// names.
191-
fn map_subst_from_canonical(
192-
_: &C::UniverseMap,
193-
value: &C::CanonicalConstrainedSubst,
194-
) -> C::CanonicalConstrainedSubst;
195197
}
196198

197199
/// Callback trait for `instantiate_ucanonical_goal`. Unlike the other

chalk-engine/src/forest.rs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ use crate::table::{Answer, AnswerIndex};
66
use crate::tables::Tables;
77
use crate::{DepthFirstNumber, SimplifiedAnswer, TableIndex};
88

9-
pub struct Forest<C: Context, CO: ContextOps<C>> {
10-
#[allow(dead_code)]
11-
pub(crate) context: CO,
9+
pub struct Forest<C: Context> {
10+
context: C,
1211
pub(crate) tables: Tables<C>,
1312
pub(crate) stack: Stack,
1413

1514
dfn: DepthFirstNumber,
1615
}
1716

18-
impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
19-
pub fn new(context: CO) -> Self {
17+
impl<C: Context> Forest<C> {
18+
pub fn new(context: C) -> Self {
2019
Forest {
2120
context,
2221
tables: Tables::new(),
@@ -25,6 +24,16 @@ impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
2524
}
2625
}
2726

27+
/// Gives access to `self.context`. In fact, the SLG solver
28+
/// doesn't ever use `self.context` for anything, and only cares
29+
/// about the associated types and methods defined on it. But the
30+
/// creator of the forest can use the context field to store
31+
/// configuration info (e.g., in chalk, we store the max size of a
32+
/// term in here).
33+
pub fn context(&self) -> &C {
34+
&self.context
35+
}
36+
2837
// Gets the next depth-first number. This number never decreases.
2938
pub(super) fn next_dfn(&mut self) -> DepthFirstNumber {
3039
self.dfn.next()
@@ -37,15 +46,16 @@ impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
3746
/// terminate.
3847
pub fn force_answers(
3948
&mut self,
49+
context: &impl ContextOps<C>,
4050
goal: C::UCanonicalGoalInEnvironment,
4151
num_answers: usize,
4252
) -> Vec<Answer<C>> {
43-
let table = self.get_or_create_table_for_ucanonical_goal(goal);
53+
let table = self.get_or_create_table_for_ucanonical_goal(context, goal);
4454
let mut answers = Vec::with_capacity(num_answers);
4555
for i in 0..num_answers {
4656
let i = AnswerIndex::from(i);
4757
loop {
48-
match self.ensure_root_answer(table, i) {
58+
match self.ensure_root_answer(context, table, i) {
4959
Ok(()) => break,
5060
Err(RootSearchFail::QuantumExceeded) => continue,
5161
Err(RootSearchFail::NoMoreSolutions) => return answers,
@@ -64,12 +74,14 @@ impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
6474
/// invocations. Invoking `next` fewer times is preferable =)
6575
fn iter_answers<'f>(
6676
&'f mut self,
77+
context: &'f impl ContextOps<C>,
6778
goal: &C::UCanonicalGoalInEnvironment,
6879
) -> impl AnswerStream<C> + 'f {
69-
let table = self.get_or_create_table_for_ucanonical_goal(goal.clone());
80+
let table = self.get_or_create_table_for_ucanonical_goal(context, goal.clone());
7081
let answer = AnswerIndex::ZERO;
7182
ForestSolver {
7283
forest: self,
84+
context,
7385
table,
7486
answer,
7587
}
@@ -78,10 +90,12 @@ impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
7890
/// Solves a given goal, producing the solution. This will do only
7991
/// as much work towards `goal` as it has to (and that works is
8092
/// cached for future attempts).
81-
pub fn solve(&mut self, goal: &C::UCanonicalGoalInEnvironment) -> Option<C::Solution> {
82-
self.context
83-
.clone()
84-
.make_solution(CO::canonical(&goal), self.iter_answers(goal))
93+
pub fn solve(
94+
&mut self,
95+
context: &impl ContextOps<C>,
96+
goal: &C::UCanonicalGoalInEnvironment,
97+
) -> Option<C::Solution> {
98+
context.make_solution(C::canonical(&goal), self.iter_answers(context, goal))
8599
}
86100

87101
/// True if all the tables on the stack starting from `depth` and
@@ -118,25 +132,34 @@ impl<C: Context, CO: ContextOps<C>> Forest<C, CO> {
118132
}
119133

120134
/// Useful for testing.
121-
pub fn num_cached_answers_for_goal(&mut self, goal: &C::UCanonicalGoalInEnvironment) -> usize {
122-
let table = self.get_or_create_table_for_ucanonical_goal(goal.clone());
135+
pub fn num_cached_answers_for_goal(
136+
&mut self,
137+
context: &impl ContextOps<C>,
138+
goal: &C::UCanonicalGoalInEnvironment,
139+
) -> usize {
140+
let table = self.get_or_create_table_for_ucanonical_goal(context, goal.clone());
123141
self.tables[table].num_cached_answers()
124142
}
125143
}
126144

127-
struct ForestSolver<'forest, C: Context + 'forest, CO: ContextOps<C> + 'forest> {
128-
forest: &'forest mut Forest<C, CO>,
145+
struct ForestSolver<'me, C: Context + 'me, CO: ContextOps<C> + 'me> {
146+
forest: &'me mut Forest<C>,
147+
context: &'me CO,
129148
table: TableIndex,
130149
answer: AnswerIndex,
131150
}
132151

133-
impl<'forest, C, CO: ContextOps<C>> AnswerStream<C> for ForestSolver<'forest, C, CO>
152+
impl<'me, C, CO> AnswerStream<C> for ForestSolver<'me, C, CO>
134153
where
135154
C: Context,
155+
CO: ContextOps<C>,
136156
{
137157
fn peek_answer(&mut self) -> Option<SimplifiedAnswer<C>> {
138158
loop {
139-
match self.forest.ensure_root_answer(self.table, self.answer) {
159+
match self
160+
.forest
161+
.ensure_root_answer(self.context, self.table, self.answer)
162+
{
140163
Ok(()) => {
141164
let answer = self.forest.answer(self.table, self.answer);
142165

0 commit comments

Comments
 (0)