@@ -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) {
@@ -27,9 +39,29 @@ impl<I: Interner> IsCoinductive<I> for Goal<I> {
27
39
} ,
28
40
GoalData :: DomainGoal ( DomainGoal :: WellFormed ( WellFormed :: Trait ( ..) ) ) => true ,
29
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.
30
46
GoalData :: Quantified ( _, goal) => goal. skip_binders ( ) . is_coinductive ( db) ,
31
- GoalData :: All ( ..) => true ,
32
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.
33
65
GoalData :: Not ( _) => false ,
34
66
GoalData :: EqGoal ( _) => false ,
35
67
GoalData :: CannotProve ( _) => false ,
0 commit comments