Skip to content

Commit c1bcf2d

Browse files
committed
Fix overeager cycle detection in dyn impl clause generation
The same trait can appear multiple times in the super trait graph without forming a cycle (see the test).
1 parent 220953b commit c1bcf2d

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

chalk-solve/src/clauses/dyn_ty.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ pub fn super_traits<I: Interner>(
133133
) {
134134
let interner = db.interner();
135135
let trait_id = trait_ref.skip_binders().trait_id;
136+
// Avoid cycles
137+
if !seen_traits.insert(trait_id) {
138+
return;
139+
}
136140
trait_refs.push(trait_ref.clone());
137141
let trait_datum = db.trait_datum(trait_id);
138142
let super_trait_refs = trait_datum
@@ -153,10 +157,6 @@ pub fn super_traits<I: Interner>(
153157
{
154158
return None;
155159
}
156-
// Avoid cycles
157-
if !seen_traits.insert(tr.trait_id) {
158-
return None;
159-
}
160160
Some(tr.clone())
161161
}
162162
WhereClause::AliasEq(_) => None,
@@ -175,6 +175,7 @@ pub fn super_traits<I: Interner>(
175175
let q_super_trait_ref = actual_binders.fuse_binders(interner);
176176
go(db, q_super_trait_ref, seen_traits, trait_refs);
177177
}
178+
seen_traits.remove(&trait_id);
178179
}
179180

180181
Binders::new(trait_datum.binders.binders.clone(), trait_refs)

tests/test/existential_types.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,38 @@ fn dyn_super_trait_cycle() {
181181
}
182182
}
183183

184+
#[test]
185+
fn dyn_super_trait_not_a_cycle() {
186+
test! {
187+
program {
188+
trait Thing<T> {}
189+
trait Foo where Self: Thing<B> {}
190+
trait Bar where Self: Foo, Self: Thing<A> {}
191+
192+
struct A {}
193+
struct B {}
194+
}
195+
196+
goal {
197+
dyn Bar: Foo
198+
} yields {
199+
"Unique"
200+
}
201+
202+
goal {
203+
dyn Bar: Thing<A>
204+
} yields {
205+
"Unique"
206+
}
207+
208+
goal {
209+
dyn Bar: Thing<B>
210+
} yields {
211+
"Unique"
212+
}
213+
}
214+
}
215+
184216
#[test]
185217
fn dyn_super_trait_higher_ranked() {
186218
test! {

0 commit comments

Comments
 (0)