Fix sort inference for equality over finite types (#8897)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 22 Jun 2022 18:16:00 +0000 (13:16 -0500)
committerGitHub <noreply@github.com>
Wed, 22 Jun 2022 18:16:00 +0000 (13:16 -0500)
Sort inference for equality was not considering equality over some finite types, leading to potential solution soundness.

Fixes #8883.

src/theory/sort_inference.cpp
src/theory/sort_inference.h
test/regress/cli/CMakeLists.txt
test/regress/cli/regress0/datatypes/issue8883-sort-inf.smt2 [new file with mode: 0644]

index 52a333cc3ff6cb21421c97ce85c45a0ed036a184..91d8b2a152c3f82d11748ffcfb9385b0ef2826e7 100644 (file)
@@ -426,19 +426,16 @@ int SortInference::process( Node n, std::map< Node, Node >& var_bound, std::map<
     Trace("sort-inference-debug") << "...Process " << n << std::endl;
 
     int retType;
-    if( n.getKind()==kind::EQUAL && !n[0].getType().isBoolean() ){
+    // we only do this for non-finite types, as finite types have cardinality
+    // restrictions.
+    if (n.getKind() == kind::EQUAL
+        && !isCardinalityClassFinite(n[0].getType().getCardinalityClass(),
+                                     false))
+    {
       Trace("sort-inference-debug") << "For equality " << n << ", set equal types from : " << n[0].getType() << " " << n[1].getType() << std::endl;
-      //if original types are mixed (e.g. Int/Real), don't commit type equality in either direction
-      if( n[0].getType()!=n[1].getType() ){
-        //for now, assume the original types
-        for( unsigned i=0; i<2; i++ ){
-          int ct = getIdForType( n[i].getType() );
-          setEqual( child_types[i], ct );
-        }
-      }else{
-        //we only require that the left and right hand side must be equal
-        setEqual( child_types[0], child_types[1] );
-      }
+      Assert(n[0].getType() == n[1].getType());
+      // we only require that the left and right hand side must be equal
+      setEqual(child_types[0], child_types[1]);
       d_equality_types[n] = child_types[0];
       retType = getIdForType( n.getType() );
     }
@@ -689,7 +686,9 @@ Node SortInference::simplifyNode(
           tnnc = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
           Assert(!tnnc.isNull());
         }
-        else if (n.getKind() == kind::EQUAL && !n[0].getType().isBoolean()
+        else if (n.getKind() == kind::EQUAL
+                 && !isCardinalityClassFinite(
+                     n[0].getType().getCardinalityClass(), false)
                  && i == 0)
         {
           Assert(d_equality_types.find(n) != d_equality_types.end());
@@ -880,7 +879,8 @@ bool SortInference::isWellSorted( Node n ) {
   }
 }
 
-bool SortInference::isMonotonic( TypeNode tn ) {
+bool SortInference::isMonotonic(TypeNode tn) const
+{
   Assert(tn.isUninterpretedSort());
   return d_non_monotonic_sorts_orig.find( tn )==d_non_monotonic_sorts_orig.end();
 }
index 7fe0f588b0a8f4974e8423d2f8be3fb4bed98a05..00256e32f8aecc76c455217fb94ff08c036e8568 100644 (file)
@@ -149,7 +149,7 @@ private:
    */
   void computeMonotonicity(const std::vector<Node>& assertions);
   /** return true if tn was inferred to be monotonic */
-  bool isMonotonic(TypeNode tn);
+  bool isMonotonic(TypeNode tn) const;
   //get sort id for term n
   int getSortId( Node n );
   //get sort id for variable of quantified formula f
index c131860e7304ed2439f18193a2d5bac675e00727..45eb213b86ae41454557578292a957d19d392641 100644 (file)
@@ -541,6 +541,7 @@ set(regress_0_tests
   regress0/datatypes/issue2838.cvc.smt2
   regress0/datatypes/issue4393-cdt-model.smt2
   regress0/datatypes/issue5280-no-nrec.smt2
+  regress0/datatypes/issue8883-sort-inf.smt2
   regress0/datatypes/jsat-2.6.smt2
   regress0/datatypes/list-bool.smt2
   regress0/datatypes/list-update.smt2
diff --git a/test/regress/cli/regress0/datatypes/issue8883-sort-inf.smt2 b/test/regress/cli/regress0/datatypes/issue8883-sort-inf.smt2
new file mode 100644 (file)
index 0000000..678b0bd
--- /dev/null
@@ -0,0 +1,8 @@
+; COMMAND-LINE: --sort-inference
+; EXPECT: unsat
+(set-logic ALL)
+(declare-datatypes ((Data 1)) ((par (T) ((data)))))
+(declare-fun p2 () (Data Bool))
+(declare-fun p3 () (Data Bool))
+(assert (not (= p2 p3)))
+(check-sat)