Skip to content

Commit 011cbd3

Browse files
committed
alias eq goals
1 parent e361b5c commit 011cbd3

File tree

3 files changed

+66
-62
lines changed

3 files changed

+66
-62
lines changed

chalk-solve/src/clauses/builder.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ impl<'me, I: Interner> ClauseBuilder<'me, I> {
8080
let clause = if self.binders.len() == 0 {
8181
ProgramClauseData::Implies(clause).intern(interner)
8282
} else {
83-
ProgramClauseData::ForAll(Binders::new(ParameterKinds::from(interner, self.binders.clone()), clause)).intern(interner)
83+
ProgramClauseData::ForAll(Binders::new(
84+
ParameterKinds::from(interner, self.binders.clone()),
85+
clause,
86+
))
87+
.intern(interner)
8488
};
8589

8690
self.clauses.push(syn_eq_lower(interner, &clause));

chalk-solve/src/clauses/program_clauses.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {
735735

736736
// add new type parameter U
737737
builder.push_bound_ty(|builder, ty| {
738+
let alias = AliasTy::Projection(projection.clone());
738739
// `Normalize(<T as Foo>::Assoc -> U)`
739740
let normalize = Normalize {
740741
alias: AliasTy::Projection(projection.clone()),
@@ -743,8 +744,8 @@ impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {
743744

744745
// `AliasEq(<T as Foo>::Assoc = U)`
745746
let projection_eq = AliasEq {
746-
alias: AliasTy::Projection(projection),
747-
ty,
747+
alias: alias.clone(),
748+
ty: ty.clone(),
748749
};
749750

750751
// Projection equality rule from above.
@@ -753,7 +754,7 @@ impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {
753754
// AliasEq(<T as Foo>::Assoc = U) :-
754755
// Normalize(<T as Foo>::Assoc -> U).
755756
// }
756-
builder.push_clause(projection_eq, Some(normalize));
757+
builder.push_clause(projection_eq.clone(), Some(normalize));
757758
});
758759
});
759760
}

chalk-solve/src/clauses/syntactic_eq.rs

+57-58
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,34 @@ use std::{iter, mem::replace};
22

33
use chalk_engine::fallible::Fallible;
44
use chalk_ir::{
5+
cast::Cast,
56
fold::{shift::Shift, Fold, Folder, SuperFold},
67
interner::Interner,
7-
Binders, BoundVar, DebruijnIndex, EqGoal, Goal, GoalData, Goals, Parameter, ProgramClause,
8-
ProgramClauseData, ProgramClauseImplication, QuantifierKind, Ty, TyData, ParameterKind, ApplicationTy, TypeName,
9-
ParameterKinds,
8+
AliasEq, Binders, BoundVar, DebruijnIndex, Goal, GoalData, Goals, ParameterKind,
9+
ParameterKinds, ProgramClause, ProgramClauseData, ProgramClauseImplication, QuantifierKind, Ty,
10+
TyData,
1011
};
1112

1213
pub fn syn_eq_lower<I: Interner>(interner: &I, clause: &ProgramClause<I>) -> ProgramClause<I> {
1314
let mut folder = SynEqFolder {
1415
interner,
1516
new_params: vec![],
17+
new_goals: vec![],
1618
binders_len: 0,
1719
};
1820

19-
clause.fold_with(&mut folder, DebruijnIndex::INNERMOST).unwrap()
21+
clause
22+
.fold_with(&mut folder, DebruijnIndex::INNERMOST)
23+
.unwrap()
2024
}
2125

2226
struct SynEqFolder<'i, I: Interner> {
2327
interner: &'i I,
24-
new_params: Vec<Parameter<I>>,
28+
new_params: Vec<ParameterKind<()>>,
29+
new_goals: Vec<Goal<I>>,
2530
binders_len: usize,
2631
}
2732

28-
impl<'i, I: Interner> SynEqFolder<'i, I>
29-
where
30-
I: 'i,
31-
{
32-
fn to_eq_goals(&self, new_params: Vec<Parameter<I>>, old_len: usize) -> impl Iterator<Item = Goal<I>> + 'i {
33-
let interner = self.interner;
34-
new_params.into_iter().enumerate().map(move |(i, p)| {
35-
let var = BoundVar {
36-
debruijn: DebruijnIndex::INNERMOST,
37-
index: i + old_len,
38-
};
39-
GoalData::EqGoal(EqGoal {
40-
a: p.replace_bound(var, interner),
41-
b: p,
42-
})
43-
.intern(interner)
44-
})
45-
}
46-
}
47-
4833
impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
4934
fn as_dyn(&mut self) -> &mut dyn Folder<'i, I> {
5035
self
@@ -54,14 +39,23 @@ impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
5439
let interner = self.interner;
5540
let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.binders_len);
5641

42+
let new_ty = TyData::BoundVar(bound_var).intern(interner);
43+
// fold ty's contents first
5744
let folded = ty.super_fold_with(self, outer_binder)?;
5845
match folded.data(interner) {
59-
TyData::Apply(ApplicationTy { name: TypeName::AssociatedType(_), .. }) => {
60-
self.new_params.push(ParameterKind::Ty(ty.clone()).intern(interner));
46+
TyData::Alias(alias) => {
47+
self.new_params.push(ParameterKind::Ty(()));
48+
self.new_goals.push(
49+
AliasEq {
50+
alias: alias.clone(),
51+
ty: new_ty.clone(),
52+
}
53+
.cast(interner),
54+
);
6155
self.binders_len += 1;
62-
Ok(TyData::BoundVar(bound_var).intern(interner))
56+
Ok(new_ty)
6357
}
64-
_ => ty.super_fold_with(self, outer_binder),
58+
_ => Ok(folded),
6559
}
6660
}
6761

@@ -73,42 +67,46 @@ impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
7367
let interner = self.interner;
7468

7569
let ((binders, implication), in_binders) = match clause.data(interner) {
76-
ProgramClauseData::ForAll(for_all) => {
77-
(for_all.clone().into(), true)
78-
}
70+
ProgramClauseData::ForAll(for_all) => (for_all.clone().into(), true),
7971
// introduce a dummy binder and shift implication through it
80-
ProgramClauseData::Implies(implication) => ((ParameterKinds::new(interner), implication.shifted_in(interner)), false),
72+
ProgramClauseData::Implies(implication) => (
73+
(
74+
ParameterKinds::new(interner),
75+
implication.shifted_in(interner),
76+
),
77+
false,
78+
),
8179
};
8280
let mut binders: Vec<_> = binders.as_slice(interner).clone().into();
83-
81+
8482
let outer_binder = outer_binder.shifted_in();
8583

8684
self.binders_len = binders.len();
8785
let consequence = implication.consequence.fold_with(self, outer_binder)?;
8886
// Immediately move `new_params` out of of the folder struct so it's safe
8987
// to call `.fold_with` again
9088
let new_params = replace(&mut self.new_params, vec![]);
91-
89+
let new_goals = replace(&mut self.new_goals, vec![]);
90+
9291
let mut conditions = implication.conditions.fold_with(self, outer_binder)?;
9392
if new_params.is_empty() && !in_binders {
9493
// shift the clause out since we didn't use the dummy binder
95-
return Ok(ProgramClauseData::Implies(ProgramClauseImplication {
96-
consequence,
97-
conditions,
98-
priority: implication.priority,
99-
}.shifted_out(interner)?)
94+
return Ok(ProgramClauseData::Implies(
95+
ProgramClauseImplication {
96+
consequence,
97+
conditions,
98+
priority: implication.priority,
99+
}
100+
.shifted_out(interner)?,
101+
)
100102
.intern(interner));
101103
}
102104

103-
let old_len = binders.len();
104-
binders.extend(new_params.iter().map(|p| p.data(interner).anonymize()));
105+
binders.extend(new_params.into_iter());
105106

106107
conditions = Goals::from(
107108
interner,
108-
conditions
109-
.iter(interner)
110-
.cloned()
111-
.chain(self.to_eq_goals(new_params, old_len)),
109+
conditions.iter(interner).cloned().chain(new_goals),
112110
);
113111

114112
Ok(ProgramClauseData::ForAll(Binders::new(
@@ -134,29 +132,30 @@ impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
134132
self.binders_len = 0;
135133
// shifted in because we introduce a new binder
136134
let outer_binder = outer_binder.shifted_in();
137-
let domain_goal =
138-
GoalData::DomainGoal(domain_goal.shifted_in(interner).fold_with(self, outer_binder)?).intern(interner);
135+
let domain_goal = GoalData::DomainGoal(
136+
domain_goal
137+
.shifted_in(interner)
138+
.fold_with(self, outer_binder)?,
139+
)
140+
.intern(interner);
139141
let new_params = replace(&mut self.new_params, vec![]);
142+
let new_goals = replace(&mut self.new_goals, vec![]);
140143

141-
let binders: Vec<_> = new_params
142-
.iter()
143-
.map(|p| p.data(interner).anonymize())
144-
.collect();
145-
146-
if binders.is_empty() {
144+
if new_params.is_empty() {
147145
return Ok(goal.clone());
148146
}
149147

150148
let goal = GoalData::All(Goals::from(
151149
interner,
152-
iter::once(domain_goal).chain(self.to_eq_goals(new_params, 0)),
150+
iter::once(domain_goal).chain(new_goals),
153151
))
154152
.intern(interner);
155153

156-
Ok(
157-
GoalData::Quantified(QuantifierKind::Exists, Binders::new(ParameterKinds::from(interner, binders), goal))
158-
.intern(interner),
154+
Ok(GoalData::Quantified(
155+
QuantifierKind::Exists,
156+
Binders::new(ParameterKinds::from(interner, new_params), goal),
159157
)
158+
.intern(interner))
160159
}
161160

162161
fn interner(&self) -> &'i I {

0 commit comments

Comments
 (0)