@@ -15,6 +15,18 @@ pub trait IsCoinductive<I: Interner> {
15
15
}
16
16
17
17
impl < I : Interner > IsCoinductive < I > for Goal < I > {
18
+ /// A "coinductive" goal `G` is a goal where `G :- G` should be considered
19
+ /// true. When we are doing trait solving, if we encounter a cycle of goals
20
+ /// where solving `G1` requires `G2..Gn` and solving `Gn` requires `G1`,
21
+ /// then our behavior depends on whether each goal `Gi` in that cycle is
22
+ /// coinductive.
23
+ ///
24
+ /// If all the goals are coinductive, then `G1` is considered provable,
25
+ /// presuming that all the other subgoals for `G2..Gn` within can be fully
26
+ /// proven.
27
+ ///
28
+ /// If any goal `Gi` in the cycle is inductive, however, then the cycle is
29
+ /// considered unprovable.
18
30
fn is_coinductive ( & self , db : & dyn RustIrDatabase < I > ) -> bool {
19
31
let interner = db. interner ( ) ;
20
32
match self . data ( interner) {
@@ -28,10 +40,33 @@ impl<I: Interner> IsCoinductive<I> for Goal<I> {
28
40
WhereClause :: TypeOutlives ( ..) => false ,
29
41
} ,
30
42
GoalData :: DomainGoal ( DomainGoal :: WellFormed ( WellFormed :: Trait ( ..) ) ) => true ,
31
- GoalData :: Quantified ( QuantifierKind :: ForAll , goal) => {
32
- goal. skip_binders ( ) . is_coinductive ( db)
33
- }
34
- _ => false ,
43
+ GoalData :: DomainGoal ( _) => false ,
44
+
45
+ // Goals like `forall<..> { G }` or `... => G` we will consider to
46
+ // be coinductive if G is coinductive, although in practice I think
47
+ // it would be ok to simply consider them coinductive all the time.
48
+ GoalData :: Quantified ( _, goal) => goal. skip_binders ( ) . is_coinductive ( db) ,
49
+ GoalData :: Implies ( _, goal) => goal. is_coinductive ( db) ,
50
+
51
+ // The "All(...)" quantifier is considered coinductive. This could
52
+ // be somewhat surprising as you might have `All(Gc, Gi)` where `Gc`
53
+ // is coinductive and `Gi` is inductive. This however is really no
54
+ // different than defining a fresh coinductive goal like
55
+ //
56
+ // ```notrust
57
+ // Gx :- Gc, Gi
58
+ // ```
59
+ //
60
+ // and requiring `Gx` in place of `All(Gc, Gi)`, and that would be
61
+ // perfectly reasonable.
62
+ GoalData :: All ( ..) => true ,
63
+
64
+ // For simplicity, just assume these remaining types of goals must
65
+ // be inductive, since there is no pressing reason to consider them
66
+ // coinductive.
67
+ GoalData :: Not ( _) => false ,
68
+ GoalData :: EqGoal ( _) => false ,
69
+ GoalData :: CannotProve => false ,
35
70
}
36
71
}
37
72
}
0 commit comments