Skip to content

Commit 748d596

Browse files
committed
Use substitutions and suggestions in Solution
This commit is a major refactoring with a few goals: - Move `Solution` to a Unique/Ambiguous model, with the ambiguous case encompassing multiple forms of guidance for type inference (including "suggestions" intended to be applied as fallback). - Remove the notion of goal refinement, and instead use substitutions for communicating solutions. - Draw a more clear line between the generic Chalk engine (which "only knows Prolog", i.e. doesn't know anything special about Rust) and lowering. Put differently, everything specific to Rust should now be encoded in the lowering, rather than though special cases in the Chalk engine. This work is somewhat incomplete: the commit removes the normalization fallback, which was one major special case, but doesn't yet replace it. A follow up PR will introduce negation and use it in lowering to recover this fallback. - Consolidate the solver code so that the "strategies" for solving leaf goals are more clear and all co-located. - Introduce some of the heuristics that rustc performs for inference, e.g. preferring `where` clauses for influencing inference. We do this in a way that decouples the heuristics from the rest of the solver; the `favor_over` method, in particular, contains the relevant logic.
1 parent 8b0bc97 commit 748d596

25 files changed

+1162
-1349
lines changed

src/bin/repl.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::sync::Arc;
1111

1212
use chalk::ir;
1313
use chalk::lower::*;
14-
use chalk::solve::prove::Prove;
1514
use chalk::solve::solver::Solver;
1615

1716
use rustyline::error::ReadlineError;
@@ -121,9 +120,9 @@ fn goal(text: &str, prog: &Program) -> Result<()> {
121120
let goal = chalk_parse::parse_goal(text)?.lower(&*prog.ir)?;
122121
let overflow_depth = 10;
123122
let mut solver = Solver::new(&prog.env, overflow_depth);
124-
match Prove::new(&mut solver, goal).solve() {
125-
Ok(v) => println!("{:#?}", v),
126-
Err(e) => println!("{}", e),
123+
match solver.solve_goal(*goal) {
124+
Ok(v) => println!("{}\n", v),
125+
Err(e) => println!("No possible solution: {}\n", e),
127126
}
128127
Ok(())
129128
}

src/cast.rs

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use ir::*;
2-
use solve::Solution;
32

43
pub trait Cast<T>: Sized {
54
fn cast(self) -> T;
@@ -23,59 +22,62 @@ macro_rules! reflexive_impl {
2322
}
2423

2524
reflexive_impl!(TraitRef);
26-
reflexive_impl!(WhereClause);
27-
reflexive_impl!(WhereClauseGoal);
25+
reflexive_impl!(LeafGoal);
26+
reflexive_impl!(DomainGoal);
2827

29-
impl Cast<WhereClause> for TraitRef {
30-
fn cast(self) -> WhereClause {
31-
WhereClause::Implemented(self)
28+
impl Cast<DomainGoal> for TraitRef {
29+
fn cast(self) -> DomainGoal {
30+
DomainGoal::Implemented(self)
3231
}
3332
}
3433

35-
impl Cast<WhereClauseGoal> for TraitRef {
36-
fn cast(self) -> WhereClauseGoal {
37-
WhereClauseGoal::Implemented(self)
34+
impl Cast<LeafGoal> for TraitRef {
35+
fn cast(self) -> LeafGoal {
36+
LeafGoal::DomainGoal(self.cast())
3837
}
3938
}
4039

41-
impl Cast<WhereClause> for Normalize {
42-
fn cast(self) -> WhereClause {
43-
WhereClause::Normalize(self)
40+
impl Cast<DomainGoal> for Normalize {
41+
fn cast(self) -> DomainGoal {
42+
DomainGoal::Normalize(self)
4443
}
4544
}
4645

47-
impl Cast<WhereClauseGoal> for Normalize {
48-
fn cast(self) -> WhereClauseGoal {
49-
WhereClauseGoal::Normalize(self)
46+
impl Cast<LeafGoal> for Normalize {
47+
fn cast(self) -> LeafGoal {
48+
LeafGoal::DomainGoal(self.cast())
5049
}
5150
}
5251

53-
impl Cast<WhereClauseGoal> for WellFormed {
54-
fn cast(self) -> WhereClauseGoal {
55-
WhereClauseGoal::WellFormed(self)
52+
impl Cast<DomainGoal> for WellFormed {
53+
fn cast(self) -> DomainGoal {
54+
DomainGoal::WellFormed(self)
55+
}
56+
}
57+
58+
impl Cast<LeafGoal> for WellFormed {
59+
fn cast(self) -> LeafGoal {
60+
LeafGoal::DomainGoal(self.cast())
5661
}
5762
}
5863

5964
impl Cast<Goal> for WellFormed {
6065
fn cast(self) -> Goal {
61-
let wcg: WhereClauseGoal = self.cast();
66+
let wcg: LeafGoal = self.cast();
6267
wcg.cast()
6368
}
6469
}
6570

6671
impl Cast<Goal> for Normalize {
6772
fn cast(self) -> Goal {
68-
let wcg: WhereClauseGoal = self.cast();
73+
let wcg: LeafGoal = self.cast();
6974
wcg.cast()
7075
}
7176
}
7277

73-
impl Cast<WhereClauseGoal> for WhereClause {
74-
fn cast(self) -> WhereClauseGoal {
75-
match self {
76-
WhereClause::Implemented(a) => a.cast(),
77-
WhereClause::Normalize(a) => a.cast(),
78-
}
78+
impl Cast<LeafGoal> for DomainGoal {
79+
fn cast(self) -> LeafGoal {
80+
LeafGoal::DomainGoal(self)
7981
}
8082
}
8183

@@ -85,27 +87,21 @@ impl Cast<Goal> for TraitRef {
8587
}
8688
}
8789

88-
impl Cast<Goal> for WhereClause {
90+
impl Cast<Goal> for DomainGoal {
8991
fn cast(self) -> Goal {
9092
Goal::Leaf(self.cast())
9193
}
9294
}
9395

94-
impl Cast<Goal> for WhereClauseGoal {
96+
impl Cast<Goal> for LeafGoal {
9597
fn cast(self) -> Goal {
9698
Goal::Leaf(self)
9799
}
98100
}
99101

100-
impl Cast<WhereClauseGoal> for Unify<Ty> {
101-
fn cast(self) -> WhereClauseGoal {
102-
WhereClauseGoal::UnifyTys(self)
103-
}
104-
}
105-
106-
impl Cast<WhereClauseGoal> for Unify<Lifetime> {
107-
fn cast(self) -> WhereClauseGoal {
108-
WhereClauseGoal::UnifyLifetimes(self)
102+
impl Cast<LeafGoal> for EqGoal {
103+
fn cast(self) -> LeafGoal {
104+
LeafGoal::EqGoal(self)
109105
}
110106
}
111107

@@ -126,10 +122,8 @@ macro_rules! map_impl {
126122
}
127123

128124
map_impl!(impl[T: Cast<U>, U] Cast<Option<U>> for Option<T>);
129-
map_impl!(impl[T: Cast<U>, U] Cast<Query<U>> for Query<T>);
130-
map_impl!(impl[T: Cast<U>, U] Cast<Solution<U>> for Solution<T>);
125+
map_impl!(impl[T: Cast<U>, U] Cast<Canonical<U>> for Canonical<T>);
131126
map_impl!(impl[T: Cast<U>, U] Cast<InEnvironment<U>> for InEnvironment<T>);
132-
map_impl!(impl[T: Cast<U>, U] Cast<Constrained<U>> for Constrained<T>);
133127
map_impl!(impl[T: Cast<U>, U, E] Cast<Result<U, E>> for Result<T, E>);
134128

135129
impl<T, U> Cast<Vec<U>> for Vec<T>

src/fold/mod.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use errors::*;
22
use ir::*;
33
use std::fmt::Debug;
44
use std::sync::Arc;
5+
use std::collections::BTreeMap;
56

67
mod instantiate;
78
mod shifted;
@@ -139,6 +140,23 @@ impl Fold for Lifetime {
139140
}
140141
}
141142

143+
impl Fold for Substitution {
144+
type Result = Substitution;
145+
fn fold_with(&self, folder: &mut Folder, binders: usize) -> Result<Self::Result> {
146+
let mut tys = BTreeMap::new();
147+
let mut lifetimes = BTreeMap::new();
148+
149+
for (var, ty) in &self.tys {
150+
tys.insert(*var, ty.fold_with(folder, binders)?);
151+
}
152+
for (var, lt) in &self.lifetimes {
153+
lifetimes.insert(*var, lt.fold_with(folder, binders)?);
154+
}
155+
156+
Ok(Substitution { tys, lifetimes })
157+
}
158+
}
159+
142160
macro_rules! copy_fold {
143161
($t:ty) => {
144162
impl Fold for $t {
@@ -178,10 +196,9 @@ macro_rules! enum_fold {
178196
}
179197

180198
enum_fold!(ParameterKind[T,L] { Ty(a), Lifetime(a) } where T: Fold, L: Fold);
181-
enum_fold!(WhereClause[] { Implemented(a), Normalize(a) });
199+
enum_fold!(DomainGoal[] { Implemented(a), Normalize(a), WellFormed(a) });
182200
enum_fold!(WellFormed[] { Ty(a), TraitRef(a) });
183-
enum_fold!(WhereClauseGoal[] { Implemented(a), Normalize(a), UnifyTys(a),
184-
UnifyLifetimes(a), WellFormed(a) });
201+
enum_fold!(LeafGoal[] { EqGoal(a), DomainGoal(a) });
185202
enum_fold!(Constraint[] { LifetimeEq(a, b) });
186203
enum_fold!(Goal[] { Quantified(qkind, subgoal), Implies(wc, subgoal), And(g1, g2), Leaf(wc) });
187204

@@ -206,6 +223,6 @@ struct_fold!(AssociatedTyValue { associated_ty_id, value });
206223
struct_fold!(AssociatedTyValueBound { ty, where_clauses });
207224
struct_fold!(Environment { universe, clauses });
208225
struct_fold!(InEnvironment[F] { environment, goal } where F: Fold);
209-
struct_fold!(Unify[T] { a, b } where T: Fold);
210-
struct_fold!(Constrained[F] { value, constraints } where F: Fold);
226+
struct_fold!(EqGoal { a, b });
211227
struct_fold!(ProgramClauseImplication { consequence, conditions });
228+
struct_fold!(ConstrainedSubst { subst, constraints });

src/ir/debug.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -145,35 +145,27 @@ impl Debug for Normalize {
145145
}
146146
}
147147

148-
impl Debug for WhereClause {
148+
impl Debug for DomainGoal {
149149
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
150150
match *self {
151-
WhereClause::Normalize(ref n) => write!(fmt, "{:?}", n),
152-
WhereClause::Implemented(ref n) => {
151+
DomainGoal::Normalize(ref n) => write!(fmt, "{:?}", n),
152+
DomainGoal::Implemented(ref n) => {
153153
write!(fmt,
154154
"{:?}: {:?}{:?}",
155155
n.parameters[0],
156156
n.trait_id,
157157
Angle(&n.parameters[1..]))
158158
}
159+
DomainGoal::WellFormed(ref n) => write!(fmt, "{:?}", n),
159160
}
160161
}
161162
}
162163

163-
impl Debug for WhereClauseGoal {
164+
impl Debug for LeafGoal {
164165
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
165166
match *self {
166-
WhereClauseGoal::Normalize(ref n) => write!(fmt, "{:?}", n),
167-
WhereClauseGoal::Implemented(ref n) => {
168-
write!(fmt,
169-
"{:?}: {:?}{:?}",
170-
n.parameters[0],
171-
n.trait_id,
172-
Angle(&n.parameters[1..]))
173-
}
174-
WhereClauseGoal::UnifyTys(ref n) => write!(fmt, "{:?}", n),
175-
WhereClauseGoal::UnifyLifetimes(ref n) => write!(fmt, "{:?}", n),
176-
WhereClauseGoal::WellFormed(ref n) => write!(fmt, "{:?}", n),
167+
LeafGoal::EqGoal(ref eq) => write!(fmt, "{:?}", eq),
168+
LeafGoal::DomainGoal(ref dom) => write!(fmt, "{:?}", dom),
177169
}
178170
}
179171
}
@@ -188,7 +180,7 @@ impl Debug for WellFormed {
188180
}
189181
}
190182

191-
impl<T: Debug> Debug for Unify<T> {
183+
impl Debug for EqGoal {
192184
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
193185
write!(fmt, "({:?} = {:?})", self.a, self.b)
194186
}

0 commit comments

Comments
 (0)