Skip to content

Commit 656146d

Browse files
committed
Address review comments
1 parent cdd8852 commit 656146d

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

chalk-solve/src/clauses/syntactic_eq.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,68 @@ impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
5858
}
5959
}
6060

61+
/// Convert a program clause to rem
62+
///
63+
/// Consider this (nonsense) example:
64+
///
65+
/// ```notrust
66+
/// forall<X> {
67+
/// Implemented(<X as Iterator>::Item>: Debug) :-
68+
/// Implemented(X: Debug)
69+
/// }
70+
/// ```
71+
///
72+
/// we would lower this into:
73+
///
74+
/// ```notrust
75+
/// forall<X, Y> {
76+
/// Implemented(Y: Debug) :-
77+
/// AliasEq(<X as Iterator>::Item>, Y),
78+
/// Implemented(X: Debug)
79+
/// }
80+
/// ```
6181
fn fold_program_clause(
6282
&mut self,
6383
clause: &ProgramClause<I>,
6484
outer_binder: DebruijnIndex,
6585
) -> Fallible<ProgramClause<I>> {
6686
let interner = self.interner;
87+
assert!(self.new_params.is_empty());
88+
assert!(self.new_goals.is_empty());
6789

6890
let ProgramClauseData(binders) = clause.data(interner);
6991

7092
let implication = binders.skip_binders();
7193
let mut binders: Vec<_> = binders.binders.as_slice(interner).into();
7294

95+
// Adjust the outer binder to account for the binder in the program clause
7396
let outer_binder = outer_binder.shifted_in();
7497

98+
// First lower the "consequence" -- in our example that is
99+
//
100+
// ```
101+
// Implemented(<X as Iterator>::Item: Debug)
102+
// ```
103+
//
104+
// then save out the `new_params` and `new_goals` vectors to store any new variables created as a result.
105+
// In this case, that would be the `Y` parameter and `AliasEq(<X as Iterator>::Item, Y)` goals.
106+
//
107+
// Note that these new parameters will have indices that come after the existing parameters,
108+
// so any references to existing parameters like `X` in the "conditions" are still valid even if we insert new parameters.
75109
self.binders_len = binders.len();
110+
76111
let consequence = implication.consequence.fold_with(self, outer_binder)?;
77-
// Immediately move `new_params` out of of the folder struct so it's safe
78-
// to call `.fold_with` again
79-
let new_params = replace(&mut self.new_params, vec![]);
80-
let new_goals = replace(&mut self.new_goals, vec![]);
112+
let mut new_params = replace(&mut self.new_params, vec![]);
113+
let mut new_goals = replace(&mut self.new_goals, vec![]);
114+
115+
// Now fold the conditions (in our example, Implemented(X: Debug).
116+
// The resulting list might be expanded to include new AliasEq goals.
81117

82118
let mut conditions = implication.conditions.fold_with(self, outer_binder)?;
119+
120+
new_params.extend(replace(&mut self.new_params, vec![]));
121+
new_goals.extend(replace(&mut self.new_goals, vec![]));
122+
83123
let constraints = implication.constraints.fold_with(self, outer_binder)?;
84124

85125
binders.extend(new_params.into_iter());
@@ -102,7 +142,8 @@ impl<'i, I: Interner> Folder<'i, I> for SynEqFolder<'i, I> {
102142
}
103143

104144
fn fold_goal(&mut self, goal: &Goal<I>, outer_binder: DebruijnIndex) -> Fallible<Goal<I>> {
105-
assert!(self.new_params.is_empty(), true);
145+
assert!(self.new_params.is_empty());
146+
assert!(self.new_goals.is_empty());
106147

107148
let interner = self.interner;
108149
match goal.data(interner) {

0 commit comments

Comments
 (0)