Skip to content

Commit df7e0b1

Browse files
authored
Merge pull request #120 from nikomatsakis/fewer-engine-traits
Fewer engine traits
2 parents b953f83 + 0a6aad9 commit df7e0b1

File tree

9 files changed

+173
-203
lines changed

9 files changed

+173
-203
lines changed

chalk-engine/src/context/mod.rs

+52-71
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ crate mod prelude;
88

99
/// The "context" in which the SLG solver operates.
1010
pub trait Context: Sized + Clone + Debug + ContextOps<Self> + AggregateOps<Self> {
11-
type CanonicalExClause: CanonicalExClause<Self>;
11+
type CanonicalExClause: Debug;
1212

1313
/// A map between universes. These are produced when
1414
/// u-canonicalizing something; they map canonical results back to
@@ -41,33 +41,39 @@ pub trait Context: Sized + Clone + Debug + ContextOps<Self> + AggregateOps<Self>
4141
/// completely opaque to the SLG solver; it is produced by
4242
/// `make_solution`.
4343
type Solution;
44+
45+
/// Extracts the inner normalized substitution.
46+
fn inference_normalized_subst(canon_ex_clause: &Self::CanonicalExClause)
47+
-> &Self::InferenceNormalizedSubst;
48+
}
49+
50+
pub trait ExClauseContext<C: Context>: Sized + Debug {
51+
/// Represents a substitution from the "canonical variables" found
52+
/// in a canonical goal to specific values.
53+
type Substitution: Debug;
54+
55+
/// Represents a region constraint that will be propagated back
56+
/// (but not verified).
57+
type RegionConstraint: Debug;
58+
59+
/// Represents a goal along with an environment.
60+
type GoalInEnvironment: Debug + Clone + Eq + Hash;
4461
}
4562

4663
/// The set of types belonging to an "inference context"; in rustc,
4764
/// these types are tied to the lifetime of the arena within which an
4865
/// inference context operates.
49-
pub trait InferenceContext<C: Context>: Sized + Debug {
66+
pub trait InferenceContext<C: Context>: ExClauseContext<C> {
5067
/// Represents a set of hypotheses that are assumed to be true.
51-
type Environment: Environment<C, Self>;
68+
type Environment: Debug + Clone;
5269

5370
/// Goals correspond to things we can prove.
54-
type Goal: Goal<C, Self>;
71+
type Goal: Clone + Debug + Eq;
5572

5673
/// A goal that can be targeted by a program clause. The SLG
5774
/// solver treats these opaquely; in contrast, it understands
5875
/// "meta" goals like `G1 && G2` and so forth natively.
59-
type DomainGoal: DomainGoal<C, Self>;
60-
61-
/// Represents a goal along with an environment.
62-
type GoalInEnvironment: GoalInEnvironment<C, Self>;
63-
64-
/// Represents a region constraint that will be propagated back
65-
/// (but not verified).
66-
type RegionConstraint: Debug;
67-
68-
/// Represents a substitution from the "canonical variables" found
69-
/// in a canonical goal to specific values.
70-
type Substitution: Debug;
76+
type DomainGoal: Debug;
7177

7278
/// A "higher-order" goal, quantified over some types and/or
7379
/// lifetimes. When you have a quantification, like `forall<T> { G
@@ -89,7 +95,34 @@ pub trait InferenceContext<C: Context>: Sized + Debug {
8995

9096
/// The successful result from unification: contains new subgoals
9197
/// and things that can be attached to an ex-clause.
92-
type UnificationResult: UnificationResult<C, Self>;
98+
type UnificationResult;
99+
100+
fn goal_in_environment(environment: &Self::Environment, goal: Self::Goal) -> Self::GoalInEnvironment;
101+
102+
/// Upcast this domain goal into a more general goal.
103+
fn into_goal(domain_goal: Self::DomainGoal) -> Self::Goal;
104+
105+
/// Create a "cannot prove" goal (see `HhGoal::CannotProve`).
106+
fn cannot_prove() -> Self::Goal;
107+
108+
/// Convert the context's goal type into the `HhGoal` type that
109+
/// the SLG solver understands. The expectation is that the
110+
/// context's goal type has the same set of variants, but with
111+
/// different names and a different setup. If you inspect
112+
/// `HhGoal`, you will see that this is a "shallow" or "lazy"
113+
/// conversion -- that is, we convert the outermost goal into an
114+
/// `HhGoal`, but the goals contained within are left as context
115+
/// goals.
116+
fn into_hh_goal(goal: Self::Goal) -> HhGoal<C, Self>;
117+
118+
/// Add the residual subgoals as new subgoals of the ex-clause.
119+
/// Also add region constraints.
120+
fn into_ex_clause(result: Self::UnificationResult, ex_clause: &mut ExClause<C, Self>);
121+
122+
// Used by: simplify
123+
fn add_clauses(env: &Self::Environment,
124+
clauses: impl IntoIterator<Item = Self::ProgramClause>)
125+
-> Self::Environment;
93126
}
94127

95128
pub trait ContextOps<C: Context> {
@@ -273,27 +306,6 @@ pub trait ResolventOps<C: Context, I: InferenceContext<C>> {
273306
) -> Fallible<ExClause<C, I>>;
274307
}
275308

276-
pub trait GoalInEnvironment<C: Context, I: InferenceContext<C>>:
277-
Debug + Clone + Eq + Ord + Hash
278-
{
279-
fn new(
280-
environment: &I::Environment,
281-
goal: I::Goal,
282-
) -> Self;
283-
284-
fn environment(&self) -> &I::Environment;
285-
}
286-
287-
pub trait Environment<C: Context, I: InferenceContext<C>>: Debug + Clone {
288-
// Used by: simplify
289-
fn add_clauses(&self, clauses: impl IntoIterator<Item = I::ProgramClause>) -> Self;
290-
}
291-
292-
pub trait CanonicalExClause<C: Context>: Debug {
293-
/// Extracts the inner normalized substitution.
294-
fn inference_normalized_subst(&self) -> &C::InferenceNormalizedSubst;
295-
}
296-
297309
pub trait CanonicalConstrainedSubst<C: Context>: Clone + Debug + Eq + Hash + Ord {
298310
/// True if this solution has no region constraints.
299311
fn empty_constraints(&self) -> bool;
@@ -302,26 +314,6 @@ pub trait CanonicalConstrainedSubst<C: Context>: Clone + Debug + Eq + Hash + Ord
302314
fn inference_normalized_subst(&self) -> &C::InferenceNormalizedSubst;
303315
}
304316

305-
pub trait DomainGoal<C: Context, I: InferenceContext<C>>: Debug {
306-
/// Upcast this domain goal into a more general goal.
307-
fn into_goal(self) -> I::Goal;
308-
}
309-
310-
pub trait Goal<C: Context, I: InferenceContext<C>>: Clone + Debug + Eq {
311-
/// Create a "cannot prove" goal (see `HhGoal::CannotProve`).
312-
fn cannot_prove() -> Self;
313-
314-
/// Convert the context's goal type into the `HhGoal` type that
315-
/// the SLG solver understands. The expectation is that the
316-
/// context's goal type has the same set of variants, but with
317-
/// different names and a different setup. If you inspect
318-
/// `HhGoal`, you will see that this is a "shallow" or "lazy"
319-
/// conversion -- that is, we convert the outermost goal into an
320-
/// `HhGoal`, but the goals contained within are left as context
321-
/// goals.
322-
fn into_hh_goal(self) -> HhGoal<C, I>;
323-
}
324-
325317
pub trait UniverseMap<C: Context>: Clone + Debug {
326318
/// Convert a goal G *from* the canonical universes *into* our
327319
/// local universes. This will yield a goal G' that is the same
@@ -341,23 +333,12 @@ pub trait UniverseMap<C: Context>: Clone + Debug {
341333
) -> C::CanonicalConstrainedSubst;
342334
}
343335

344-
/// Embodies the result of a unification operation: we presume that
345-
/// unification may produce new residual subgoals, which must be
346-
/// further proven, as well as region constraints.
347-
pub trait UnificationResult<C: Context, I: InferenceContext<C>> {
348-
/// Add the residual subgoals as new subgoals of the ex-clause.
349-
/// Also add region constraints.
350-
fn into_ex_clause(self, ex_clause: &mut ExClause<C, I>);
351-
}
352-
353336
pub trait AnswerStream<C: Context> {
354337
fn peek_answer(&mut self) -> Option<SimplifiedAnswer<C>>;
355338
fn next_answer(&mut self) -> Option<SimplifiedAnswer<C>>;
356339

357340
/// Invokes `test` with each possible future answer, returning true immediately
358341
/// if we find any answer for which `test` returns true.
359-
fn any_future_answer(
360-
&mut self,
361-
test: impl FnMut(&C::InferenceNormalizedSubst) -> bool,
362-
) -> bool;
342+
fn any_future_answer(&mut self, test: impl FnMut(&C::InferenceNormalizedSubst) -> bool)
343+
-> bool;
363344
}

chalk-engine/src/context/prelude.rs

-7
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,8 @@ crate use super::Context;
44
crate use super::ContextOps;
55
crate use super::ResolventOps;
66
crate use super::TruncateOps;
7-
crate use super::Environment;
87
crate use super::InferenceTable;
98
crate use super::InferenceContext;
10-
crate use super::UnificationResult;
11-
crate use super::GoalInEnvironment;
129
crate use super::UCanonicalGoalInEnvironment;
1310
crate use super::UniverseMap;
14-
crate use super::CanonicalExClause;
1511
crate use super::CanonicalConstrainedSubst;
16-
crate use super::Goal;
17-
crate use super::DomainGoal;
18-

chalk-engine/src/derived.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl<C: Context> Hash for DelayedLiteral<C> {
119119

120120
///////////////////////////////////////////////////////////////////////////
121121

122-
impl<C: Context, I: InferenceContext<C>> PartialEq for Literal<C, I> {
122+
impl<C: Context, I: ExClauseContext<C>> PartialEq for Literal<C, I> {
123123
fn eq(&self, other: &Literal<C, I>) -> bool {
124124
match (self, other) {
125125
(Literal::Positive(goal1), Literal::Positive(goal2))
@@ -130,10 +130,10 @@ impl<C: Context, I: InferenceContext<C>> PartialEq for Literal<C, I> {
130130
}
131131
}
132132

133-
impl<C: Context, I: InferenceContext<C>> Eq for Literal<C, I> {
133+
impl<C: Context, I: ExClauseContext<C>> Eq for Literal<C, I> {
134134
}
135135

136-
impl<C: Context, I: InferenceContext<C>> Hash for Literal<C, I> {
136+
impl<C: Context, I: ExClauseContext<C>> Hash for Literal<C, I> {
137137
fn hash<H: Hasher>(&self, state: &mut H) {
138138
mem::discriminant(self).hash(state);
139139
match self {

chalk-engine/src/lib.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,11 @@
5555
#![feature(in_band_lifetimes)]
5656
#![feature(macro_vis_matcher)]
5757
#![feature(step_trait)]
58-
#![feature(underscore_lifetimes)]
5958

6059
#[macro_use] extern crate chalk_macros;
6160
extern crate stacker;
6261

63-
use crate::context::{Context, InferenceContext};
62+
use crate::context::{Context, ExClauseContext};
6463
use std::collections::HashSet;
6564
use std::cmp::min;
6665
use std::usize;
@@ -105,20 +104,20 @@ struct DepthFirstNumber {
105104

106105
/// The paper describes these as `A :- D | G`.
107106
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
108-
pub struct ExClause<C: Context, I: InferenceContext<C>> {
107+
pub struct ExClause<C: Context, E: ExClauseContext<C>> {
109108
/// The substitution which, applied to the goal of our table,
110109
/// would yield A.
111-
pub subst: I::Substitution,
110+
pub subst: E::Substitution,
112111

113112
/// Delayed literals: things that we depend on negatively,
114113
/// but which have not yet been fully evaluated.
115114
pub delayed_literals: Vec<DelayedLiteral<C>>,
116115

117116
/// Region constraints we have accumulated.
118-
pub constraints: Vec<I::RegionConstraint>,
117+
pub constraints: Vec<E::RegionConstraint>,
119118

120119
/// Subgoals: literals that must be proven
121-
pub subgoals: Vec<Literal<C, I>>,
120+
pub subgoals: Vec<Literal<C, E>>,
122121
}
123122

124123
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -185,9 +184,9 @@ pub enum DelayedLiteral<C: Context> {
185184

186185
/// Either `A` or `~A`, where `A` is a `Env |- Goal`.
187186
#[derive(Clone, Debug)]
188-
pub enum Literal<C: Context, I: InferenceContext<C>> { // FIXME: pub b/c fold
189-
Positive(I::GoalInEnvironment),
190-
Negative(I::GoalInEnvironment),
187+
pub enum Literal<C: Context, E: ExClauseContext<C>> { // FIXME: pub b/c fold
188+
Positive(E::GoalInEnvironment),
189+
Negative(E::GoalInEnvironment),
191190
}
192191

193192
/// The `Minimums` structure is used to track the dependencies between

chalk-engine/src/logic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<C: Context> Forest<C> {
115115
}
116116

117117
self.tables[table].strands_mut().any(|strand| {
118-
test(strand.canonical_ex_clause.inference_normalized_subst())
118+
test(C::inference_normalized_subst(&strand.canonical_ex_clause))
119119
})
120120
}
121121

@@ -760,7 +760,7 @@ impl<C: Context> Forest<C> {
760760
goal: I::Goal,
761761
) {
762762
let table_ref = &mut self.tables[table];
763-
match goal.into_hh_goal() {
763+
match I::into_hh_goal(goal) {
764764
HhGoal::DomainGoal(domain_goal) => {
765765
let clauses = infer.program_clauses(&environment, &domain_goal);
766766
for clause in clauses {

chalk-engine/src/simplify.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -28,35 +28,35 @@ impl<C: Context> Forest<C> {
2828
match hh_goal {
2929
HhGoal::ForAll(subgoal) => {
3030
let subgoal = infer.instantiate_binders_universally(&subgoal);
31-
pending_goals.push((environment, subgoal.into_hh_goal()));
31+
pending_goals.push((environment, I::into_hh_goal(subgoal)));
3232
}
3333
HhGoal::Exists(subgoal) => {
3434
let subgoal = infer.instantiate_binders_existentially(&subgoal);
35-
pending_goals.push((environment, subgoal.into_hh_goal()))
35+
pending_goals.push((environment, I::into_hh_goal(subgoal)))
3636
}
3737
HhGoal::Implies(wc, subgoal) => {
38-
let new_environment = environment.add_clauses(wc);
39-
pending_goals.push((new_environment, subgoal.into_hh_goal()));
38+
let new_environment = I::add_clauses(&environment, wc);
39+
pending_goals.push((new_environment, I::into_hh_goal(subgoal)));
4040
}
4141
HhGoal::And(subgoal1, subgoal2) => {
42-
pending_goals.push((environment.clone(), subgoal1.into_hh_goal()));
43-
pending_goals.push((environment, subgoal2.into_hh_goal()));
42+
pending_goals.push((environment.clone(), I::into_hh_goal(subgoal1)));
43+
pending_goals.push((environment, I::into_hh_goal(subgoal2)));
4444
}
4545
HhGoal::Not(subgoal) => {
4646
ex_clause
4747
.subgoals
48-
.push(Literal::Negative(I::GoalInEnvironment::new(&environment, subgoal)));
48+
.push(Literal::Negative(I::goal_in_environment(&environment, subgoal)));
4949
}
5050
HhGoal::Unify(a, b) => {
51-
infer.unify_parameters(&environment, &a, &b)?
52-
.into_ex_clause(&mut ex_clause)
51+
I::into_ex_clause(infer.unify_parameters(&environment, &a, &b)?,
52+
&mut ex_clause)
5353
}
5454
HhGoal::DomainGoal(domain_goal) => {
5555
ex_clause
5656
.subgoals
57-
.push(Literal::Positive(I::GoalInEnvironment::new(
57+
.push(Literal::Positive(I::goal_in_environment(
5858
&environment,
59-
domain_goal.into_goal(),
59+
I::into_goal(domain_goal),
6060
)));
6161
}
6262
HhGoal::CannotProve => {
@@ -66,10 +66,10 @@ impl<C: Context> Forest<C> {
6666
// course, will always create a negative cycle and
6767
// hence a delayed literal that cannot be
6868
// resolved.
69-
let goal = I::Goal::cannot_prove();
69+
let goal = I::cannot_prove();
7070
ex_clause
7171
.subgoals
72-
.push(Literal::Negative(I::GoalInEnvironment::new(&environment, goal)));
72+
.push(Literal::Negative(I::goal_in_environment(&environment, goal)));
7373
}
7474
}
7575
}

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#![feature(macro_vis_matcher)]
1010
#![feature(specialization)]
1111
#![feature(step_trait)]
12-
#![feature(underscore_lifetimes)]
1312

1413
extern crate chalk_parse;
1514
#[macro_use]

0 commit comments

Comments
 (0)