Skip to content

Commit 556d668

Browse files
committed
change wf's input type collector to use visit
1 parent b65c184 commit 556d668

File tree

3 files changed

+95
-107
lines changed

3 files changed

+95
-107
lines changed

chalk-ir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,7 @@ pub struct Normalize<I: Interner> {
11231123
/// Proves **equality** between a projection `T::Foo` and a type
11241124
/// `U`. Equality can be proven via normalization, but we can also
11251125
/// prove that `T::Foo = V::Foo` if `T = V` without normalizing.
1126-
#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit)]
1126+
#[derive(Clone, PartialEq, Eq, Hash, Fold)]
11271127
pub struct AliasEq<I: Interner> {
11281128
pub alias: AliasTy<I>,
11291129
pub ty: Ty<I>,

chalk-ir/src/visit.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::fmt::Debug;
33

44
use crate::{
5-
BoundVar, DebruijnIndex, Goal, InferenceVar, Interner, Lifetime, LifetimeData,
5+
AliasEq, BoundVar, DebruijnIndex, Goal, InferenceVar, Interner, Lifetime, LifetimeData,
66
PlaceholderIndex, ProgramClause, Ty, TyData,
77
};
88

@@ -157,6 +157,14 @@ where
157157
}
158158
}
159159

160+
fn visit_alias_eq(
161+
&mut self,
162+
alias_eq: &AliasEq<I>,
163+
outer_binder: DebruijnIndex,
164+
) -> Self::Result {
165+
alias_eq.super_visit_with(self.as_dyn(), outer_binder)
166+
}
167+
160168
/// As with `visit_free_placeholder_ty`, but for lifetimes.
161169
fn visit_free_placeholder_lifetime(
162170
&mut self,
@@ -364,3 +372,31 @@ impl<I: Interner> Visit<I> for ProgramClause<I> {
364372
visitor.visit_program_clause(self, outer_binder)
365373
}
366374
}
375+
376+
impl<I: Interner> Visit<I> for AliasEq<I> {
377+
fn visit_with<'i, R: VisitResult>(
378+
&self,
379+
visitor: &mut dyn Visitor<'i, I, Result = R>,
380+
outer_binder: DebruijnIndex,
381+
) -> R
382+
where
383+
I: 'i,
384+
{
385+
visitor.visit_alias_eq(self, outer_binder)
386+
}
387+
}
388+
389+
impl<I: Interner> SuperVisit<I> for AliasEq<I> {
390+
fn super_visit_with<'i, R: VisitResult>(
391+
&self,
392+
visitor: &mut dyn Visitor<'i, I, Result = R>,
393+
outer_binder: DebruijnIndex,
394+
) -> R
395+
where
396+
I: 'i,
397+
{
398+
R::new()
399+
.and_then(|| self.alias.visit_with(visitor, outer_binder))
400+
.and_then(|| self.ty.visit_with(visitor, outer_binder))
401+
}
402+
}

chalk-solve/src/wf.rs

Lines changed: 57 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::split::Split;
77
use crate::RustIrDatabase;
88
use chalk_ir::cast::*;
99
use chalk_ir::fold::shift::Shift;
10-
use chalk_ir::interner::{HasInterner, Interner};
10+
use chalk_ir::interner::Interner;
11+
use chalk_ir::visit::{Visit, Visitor};
1112
use chalk_ir::*;
1213
use chalk_rust_ir::*;
1314

@@ -41,69 +42,63 @@ pub struct WfSolver<'db, I: Interner> {
4142
solver_choice: SolverChoice,
4243
}
4344

44-
/// A trait for retrieving all types appearing in some Chalk construction.
45-
///
46-
/// FIXME: why is this not a `Folder`?
47-
trait FoldInputTypes: HasInterner {
48-
fn fold(&self, interner: &Self::Interner, accumulator: &mut Vec<Ty<Self::Interner>>);
45+
struct InputTypeCollector<'i, I: Interner> {
46+
types: Vec<Ty<I>>,
47+
interner: &'i I,
4948
}
5049

51-
impl<T: FoldInputTypes> FoldInputTypes for [T] {
52-
fn fold(&self, interner: &T::Interner, accumulator: &mut Vec<Ty<T::Interner>>) {
53-
for f in self {
54-
f.fold(interner, accumulator);
50+
impl<'i, I: Interner> InputTypeCollector<'i, I> {
51+
fn new(interner: &'i I) -> Self {
52+
Self {
53+
types: Vec::new(),
54+
interner,
5555
}
5656
}
5757
}
5858

59-
impl<T: FoldInputTypes> FoldInputTypes for Vec<T> {
60-
fn fold(&self, interner: &T::Interner, accumulator: &mut Vec<Ty<T::Interner>>) {
61-
for f in self {
62-
f.fold(interner, accumulator);
63-
}
64-
}
65-
}
59+
impl<'i, 't, I: Interner> Visitor<'i, I> for InputTypeCollector<'i, I> {
60+
type Result = ();
6661

67-
impl<I: Interner> FoldInputTypes for Parameter<I> {
68-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
69-
if let ParameterKind::Ty(ty) = self.data(interner) {
70-
ty.fold(interner, accumulator)
71-
}
62+
fn as_dyn(&mut self) -> &mut dyn Visitor<'i, I, Result = Self::Result> {
63+
self
7264
}
73-
}
7465

75-
impl<I: Interner> FoldInputTypes for Substitution<I> {
76-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
77-
self.parameters(interner).fold(interner, accumulator)
66+
fn interner(&self) -> &'i I {
67+
self.interner
7868
}
79-
}
8069

81-
impl<I: Interner> FoldInputTypes for QuantifiedWhereClauses<I> {
82-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
83-
self.as_slice(interner).fold(interner, accumulator)
70+
fn visit_alias_eq(&mut self, alias_eq: &AliasEq<I>, outer_binder: DebruijnIndex) {
71+
TyData::Alias(alias_eq.alias.clone())
72+
.intern(self.interner)
73+
.visit_with(self, outer_binder);
74+
alias_eq.ty.visit_with(self, outer_binder);
8475
}
85-
}
8676

87-
impl<I: Interner> FoldInputTypes for Ty<I> {
88-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
89-
match self.data(interner) {
90-
TyData::Apply(app) => {
91-
accumulator.push(self.clone());
92-
app.substitution.fold(interner, accumulator);
77+
fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) {
78+
let interner = self.interner();
79+
80+
let mut push_ty = || {
81+
self.types
82+
.push(ty.shifted_out_to(interner, outer_binder).unwrap())
83+
};
84+
match ty.data(interner) {
85+
TyData::Apply(apply) => {
86+
push_ty();
87+
apply.visit_with(self, outer_binder);
9388
}
9489

95-
TyData::Dyn(qwc) => {
96-
accumulator.push(self.clone());
97-
qwc.bounds.fold(interner, accumulator);
90+
TyData::Dyn(clauses) => {
91+
push_ty();
92+
clauses.visit_with(self, outer_binder);
9893
}
9994

10095
TyData::Alias(alias) => {
101-
accumulator.push(self.clone());
102-
alias.substitution.fold(interner, accumulator);
96+
push_ty();
97+
alias.visit_with(self, outer_binder);
10398
}
10499

105100
TyData::Placeholder(_) => {
106-
accumulator.push(self.clone());
101+
push_ty();
107102
}
108103

109104
// Type parameters do not carry any input types (so we can sort of assume they are
@@ -117,53 +112,12 @@ impl<I: Interner> FoldInputTypes for Ty<I> {
117112
TyData::Function(..) => (),
118113

119114
TyData::InferenceVar(..) => {
120-
panic!("unexpected inference variable in wf rules: {:?}", self)
115+
panic!("unexpected inference variable in wf rules: {:?}", ty)
121116
}
122117
}
123118
}
124119
}
125120

126-
impl<I: Interner> FoldInputTypes for TraitRef<I> {
127-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
128-
self.substitution.fold(interner, accumulator);
129-
}
130-
}
131-
132-
impl<I: Interner> FoldInputTypes for AliasEq<I> {
133-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
134-
TyData::Alias(self.alias.clone())
135-
.intern(interner)
136-
.fold(interner, accumulator);
137-
self.ty.fold(interner, accumulator);
138-
}
139-
}
140-
141-
impl<I: Interner> FoldInputTypes for WhereClause<I> {
142-
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
143-
match self {
144-
WhereClause::Implemented(tr) => tr.fold(interner, accumulator),
145-
WhereClause::AliasEq(p) => p.fold(interner, accumulator),
146-
}
147-
}
148-
}
149-
150-
impl<T: FoldInputTypes> FoldInputTypes for Binders<T> {
151-
fn fold(&self, interner: &T::Interner, accumulator: &mut Vec<Ty<T::Interner>>) {
152-
// FIXME: This aspect of how we've formulated implied bounds
153-
// seems to have an "eager normalization" problem, what about
154-
// where clauses like `for<T> { <Self as Foo<T>>::Bar }`?
155-
//
156-
// For now, the unwrap will panic.
157-
let mut types = vec![];
158-
self.value.fold(interner, &mut types);
159-
accumulator.extend(
160-
types
161-
.into_iter()
162-
.map(|ty| ty.shifted_out(interner).unwrap()),
163-
);
164-
}
165-
}
166-
167121
impl<'db, I> WfSolver<'db, I>
168122
where
169123
I: Interner,
@@ -207,18 +161,13 @@ where
207161
.map(|wc| wc.into_from_env_goal(interner)),
208162
|gb| {
209163
// WellFormed(Vec<T>), for each field type `Vec<T>` or type that appears in the where clauses
210-
let mut input_types = Vec::new();
164+
let mut type_collector = InputTypeCollector::new(gb.interner());
165+
211166
// ...in a field type...
212-
fields.fold(gb.interner(), &mut input_types);
167+
fields.visit_with(&mut type_collector, DebruijnIndex::INNERMOST);
213168
// ...in a where clause.
214-
where_clauses.fold(gb.interner(), &mut input_types);
215-
216-
gb.all(
217-
input_types
218-
.into_iter()
219-
.map(|ty| ty.well_formed().cast(interner))
220-
.chain(sized_constraint_goal.into_iter()),
221-
)
169+
where_clauses.visit_with(&mut type_collector, DebruijnIndex::INNERMOST);
170+
gb.all(type_collector.types.into_iter().map(|ty| ty.well_formed()).chain(sized_constraint_goal.into_iter()))
222171
},
223172
)
224173
});
@@ -308,13 +257,14 @@ fn impl_header_wf_goal<I: Interner>(
308257
// we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
309258
// We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
310259
// bound would be needed here).
311-
let mut input_types = Vec::new();
312-
where_clauses.fold(interner, &mut input_types);
260+
let mut type_collector = InputTypeCollector::new(interner);
261+
where_clauses.visit_with(&mut type_collector, DebruijnIndex::INNERMOST);
313262

314263
// Things to prove well-formed: input types of the where-clauses, projection types
315264
// appearing in the header, associated type values, and of course the trait ref.
316-
debug!("verify_trait_impl: input_types={:?}", input_types);
317-
let goals = input_types
265+
debug!("verify_trait_impl: input_types={:?}", type_collector.types);
266+
let goals = type_collector
267+
.types
318268
.into_iter()
319269
.map(|ty| ty.well_formed().cast(interner))
320270
.chain(Some((*trait_ref).clone().well_formed().cast(interner)));
@@ -350,10 +300,11 @@ fn impl_wf_environment<'i, I: Interner>(
350300
// // Inside here, we can rely on the fact that `K: Hash` holds
351301
// }
352302
// ```
353-
let mut header_input_types = Vec::new();
354-
trait_ref.fold(interner, &mut header_input_types);
303+
let mut type_collector = InputTypeCollector::new(interner);
304+
trait_ref.visit_with(&mut type_collector, DebruijnIndex::INNERMOST);
355305

356-
let types_wf = header_input_types
306+
let types_wf = type_collector
307+
.types
357308
.into_iter()
358309
.map(move |ty| ty.into_from_env_goal(interner).cast(interner));
359310

@@ -454,11 +405,12 @@ fn compute_assoc_ty_goal<I: Interner>(
454405
.cloned()
455406
.map(|qwc| qwc.into_from_env_goal(interner)),
456407
|gb| {
457-
let mut input_types = Vec::new();
458-
value_ty.fold(interner, &mut input_types);
408+
let mut type_collector = InputTypeCollector::new(interner);
409+
value_ty.visit_with(&mut type_collector, DebruijnIndex::INNERMOST);
459410

460411
// We require that `WellFormed(T)` for each type that appears in the value
461-
let wf_goals = input_types
412+
let wf_goals = type_collector
413+
.types
462414
.into_iter()
463415
.map(|ty| ty.well_formed())
464416
.casted(interner);

0 commit comments

Comments
 (0)