3030 * An object whose value a fact constrains, such as {@code x == y}, or that an alias or unknown function takes, is one
3131 * symbol with all its ghost functions, so its facts are never split. A constant, such as an enum constant read in code,
3232 * is a fixed value, so facts that only compare values with it share no symbol through it; it stays one when a function
33- * or alias takes it or a value one takes is compared with it , as equal objects have equal ghost values. Nothing changes
34- * when every fact or none is relevant
33+ * or alias takes it or a chain of comparisons relates it to a value one takes , as equal objects have equal ghost
34+ * values. Nothing changes when every fact or none is relevant
3535 */
3636public class VCRelevantFacts implements VCSimplificationPass {
3737
@@ -111,15 +111,17 @@ private VCImplication rebuild(VCImplication row, Iterator<List<Expression>> all,
111111 return result ;
112112 }
113113
114- // The constants no function or alias takes and that are compared with no value one takes
114+ // The constants no function or alias takes and that no chain of comparisons relates to a value one takes
115115 private Set <String > valueConstants (Expression expected , List <Expression > facts ) {
116116 Set <String > objects = new HashSet <>();
117117 addArguments (expected , objects );
118118 facts .forEach (fact -> addArguments (fact , objects ));
119+ List <Expression > all = new ArrayList <>(facts );
120+ all .add (expected );
121+ while (all .stream ().anyMatch (expression -> addComparedWithObjects (expression , objects )))
122+ ;
119123 Set <String > valueConstants = new HashSet <>(constants );
120124 valueConstants .removeAll (objects );
121- removeComparedWithObjects (expected , objects , valueConstants );
122- facts .forEach (fact -> removeComparedWithObjects (fact , objects , valueConstants ));
123125 return valueConstants ;
124126 }
125127
@@ -131,15 +133,18 @@ else if (expression instanceof AliasInvocation alias)
131133 expression .getChildren ().forEach (child -> addArguments (child , objects ));
132134 }
133135
134- private static void removeComparedWithObjects (Expression expression , Set <String > objects ,
135- Set <String > valueConstants ) {
136+ // Adds to objects the variables a comparison relates to one of them; true when it added any
137+ private static boolean addComparedWithObjects (Expression expression , Set <String > objects ) {
138+ boolean added = false ;
136139 if (expression instanceof BinaryExpression binary
137140 && ("==" .equals (binary .getOperator ()) || "!=" .equals (binary .getOperator ()))) {
138141 List <String > compared = variablesOf (binary );
139142 if (compared .stream ().anyMatch (objects ::contains ))
140- valueConstants . removeAll (compared );
143+ added = objects . addAll (compared );
141144 }
142- expression .getChildren ().forEach (child -> removeComparedWithObjects (child , objects , valueConstants ));
145+ for (Expression child : expression .getChildren ())
146+ added |= addComparedWithObjects (child , objects );
147+ return added ;
143148 }
144149
145150 // The symbols an expression constrains: f(x) for a ghost function over an object, or the object itself when values
0 commit comments