@@ -15,6 +15,18 @@ pub trait IsCoinductive<I: Interner> {
1515}
1616
1717impl < 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.
1830 fn is_coinductive ( & self , db : & dyn RustIrDatabase < I > ) -> bool {
1931 let interner = db. interner ( ) ;
2032 match self . data ( interner) {
@@ -26,10 +38,33 @@ impl<I: Interner> IsCoinductive<I> for Goal<I> {
2638 WhereClause :: AliasEq ( ..) => false ,
2739 } ,
2840 GoalData :: DomainGoal ( DomainGoal :: WellFormed ( WellFormed :: Trait ( ..) ) ) => true ,
29- GoalData :: Quantified ( QuantifierKind :: ForAll , goal) => {
30- goal. skip_binders ( ) . is_coinductive ( db)
31- }
32- _ => false ,
41+ GoalData :: DomainGoal ( _) => false ,
42+
43+ // Goals like `forall<..> { G }` or `... => G` we will consider to
44+ // be coinductive if G is coinductive, although in practice I think
45+ // it would be ok to simply consider them coinductive all the time.
46+ GoalData :: Quantified ( _, goal) => goal. skip_binders ( ) . is_coinductive ( db) ,
47+ GoalData :: Implies ( _, goal) => goal. is_coinductive ( db) ,
48+
49+ // The "All(...)" quantifier is considered coinductive. This could
50+ // be somewhat surprising as you might have `All(Gc, Gi)` where `Gc`
51+ // is coinductive and `Gi` is inductive. This however is really no
52+ // different than defining a fresh coinductive goal like
53+ //
54+ // ```notrust
55+ // Gx :- Gc, Gi
56+ // ```
57+ //
58+ // and requiring `Gx` in place of `All(Gc, Gi)`, and that would be
59+ // perfectly reasonable.
60+ GoalData :: All ( ..) => true ,
61+
62+ // For simplicity, just assume these remaining types of goals must
63+ // be inductive, since there is no pressing reason to consider them
64+ // coinductive.
65+ GoalData :: Not ( _) => false ,
66+ GoalData :: EqGoal ( _) => false ,
67+ GoalData :: CannotProve ( _) => false ,
3368 }
3469 }
3570}
0 commit comments