Remove unhandled subtypes (#1098)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 14 Sep 2017 19:12:22 +0000 (14:12 -0500)
committerGitHub <noreply@github.com>
Thu, 14 Sep 2017 19:12:22 +0000 (14:12 -0500)
* Remove unhandled subtypes, which consequently makes typing rules uniformly stricter based on weakening the subtype relation. Ensure coercions in the smt2 and cvc parser for Real decimal constants whose type is Integer. Ensure type annotations are computed during preRewrite to ensure rewriting (which does not preserve types) does not impact term construction for parametric datatypes. This fixes issue #1048 (we now give an type exception).

* Update unit test for parametric datatypes to reflect new subtyping relation.

* Remove deprecated test.

* Make array construction for lambdas work with new subtype relations to handle lambdas like (lambda ((x Int) (y Int)) (ite (= x 0) 0.5 0.0)).

16 files changed:
src/expr/type_node.cpp
src/parser/cvc/Cvc.g
src/parser/smt2/Smt2.g
src/theory/builtin/theory_builtin_rewriter.cpp
src/theory/builtin/theory_builtin_rewriter.h
src/theory/datatypes/datatypes_rewriter.h
src/theory/datatypes/theory_datatypes_type_rules.h
test/regress/regress0/Makefile.am
test/regress/regress0/datatypes/tuple-no-clash.cvc
test/regress/regress0/issue1048-arrays-int-real.smt2 [new file with mode: 0644]
test/regress/regress0/quantifiers/Makefile.am
test/regress/regress0/quantifiers/macro-subtype-param.smt2
test/regress/regress0/quantifiers/subtype-param-unk.smt2
test/regress/regress0/quantifiers/subtype-param.smt2
test/regress/regress0/sets/sets-tuple-poly.cvc
test/unit/util/datatype_black.h

index a4ab2f3b7d6b1a36b6a95c3942aa6f49c26e2c55..c06691d08e5148c0609e306263588178c45b4fbd 100644 (file)
@@ -106,50 +106,11 @@ bool TypeNode::isSubtypeOf(TypeNode t) const {
       return false;
     }
   }
-  if(isTuple() && t.isTuple()) {
-    const Datatype& dt1 = getDatatype();
-    const Datatype& dt2 = t.getDatatype();
-    if( dt1[0].getNumArgs()!=dt2[0].getNumArgs() ){
-      return false;
-    }
-    // r1's fields must be subtypes of r2's, in order
-    for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){
-      if( !dt1[0][i].getRangeType().isSubtypeOf( dt2[0][i].getRangeType() ) ){
-        return false;
-      }
-    }
-    return true;
-  }else if( t.isRecord() && t.isRecord() ){
-    //records are not subtypes of each other in current implementation
-  }
-  if(isFunction()) {
-    // A function is a subtype of another if the args are the same type, and
-    // the return type is a subtype of the other's.  This is enough for now
-    // (and it's necessary for model generation, since a Real-valued function
-    // might return a constant Int and thus the model value is typed differently).
-    return t.isFunction() && getArgTypes() == t.getArgTypes() && getRangeType().isSubtypeOf(t.getRangeType());
-  }
-  if(isParametricDatatype() && t.isParametricDatatype()) {
-    Assert(getKind() == kind::PARAMETRIC_DATATYPE);
-    Assert(t.getKind() == kind::PARAMETRIC_DATATYPE);
-    if((*this)[0] != t[0] || getNumChildren() != t.getNumChildren()) {
-      return false;
-    }
-    for(size_t i = 1; i < getNumChildren(); ++i) {
-      if(!((*this)[i].isSubtypeOf(t[i]))) {
-        return false;
-      }
-    }
-    return true;
-  }
   if(isSet() && t.isSet()) {
     return getSetElementType().isSubtypeOf(t.getSetElementType());
   }
-  if(isArray() && t.isArray()) {
-    //reverse for index type
-    return t.getArrayIndexType().isSubtypeOf(getArrayIndexType()) && 
-           getArrayConstituentType().isSubtypeOf(t.getArrayConstituentType());
-  }
+  // this should only return true for types T1, T2 where we handle equalities between T1 and T2
+  // (more cases go here, if we want to support such cases)
   return false;
 }
 
@@ -160,39 +121,9 @@ bool TypeNode::isComparableTo(TypeNode t) const {
   if(isSubtypeOf(NodeManager::currentNM()->realType())) {
     return t.isSubtypeOf(NodeManager::currentNM()->realType());
   }
-  if(isTuple() && t.isTuple()) {
-    const Datatype& dt1 = getDatatype();
-    const Datatype& dt2 = t.getDatatype();
-    if( dt1[0].getNumArgs()!=dt2[0].getNumArgs() ){
-      return false;
-    }
-    // r1's fields must be subtypes of r2's, in order
-    for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){
-      if( !dt1[0][i].getRangeType().isComparableTo( dt2[0][i].getRangeType() ) ){
-        return false;
-      }
-    }
-    return true;
-  //}else if( isRecord() && t.isRecord() ){
-    //record types are incomparable in current implementation
-  } else if(isParametricDatatype() && t.isParametricDatatype()) {
-    Assert(getKind() == kind::PARAMETRIC_DATATYPE);
-    Assert(t.getKind() == kind::PARAMETRIC_DATATYPE);
-    if((*this)[0] != t[0] || getNumChildren() != t.getNumChildren()) {
-      return false;
-    }
-    for(size_t i = 1; i < getNumChildren(); ++i) {
-      if(!((*this)[i].isComparableTo(t[i]))) {
-        return false;
-      }
-    }
-    return true;
-  } else if(isSet() && t.isSet()) {
+  if(isSet() && t.isSet()) {
     return getSetElementType().isComparableTo(t.getSetElementType());
   }
-  if(isArray() && t.isArray()) {
-    return getArrayIndexType().isComparableTo(t.getArrayIndexType()) && getArrayConstituentType().isComparableTo(t.getArrayConstituentType());
-  }
   return false;
 }
 
@@ -361,9 +292,11 @@ TypeNode TypeNode::commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast) {
   case kind::CONSTRUCTOR_TYPE:
   case kind::SELECTOR_TYPE:
   case kind::TESTER_TYPE:
-    return TypeNode();
   case kind::FUNCTION_TYPE:
-    return TypeNode(); // Not sure if this is right
+  case kind::ARRAY_TYPE:
+  case kind::DATATYPE_TYPE:
+  case kind::PARAMETRIC_DATATYPE:
+    return TypeNode();
   case kind::SET_TYPE: {
     // take the least common subtype of element types
     TypeNode elementType;
@@ -373,54 +306,9 @@ TypeNode TypeNode::commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast) {
       return TypeNode();
     }
   }
-  case kind::ARRAY_TYPE: {
-    TypeNode indexType, elementType;
-    if(t1.isArray() &&
-       ! (indexType = commonTypeNode(t0[0], t1[0], !isLeast)).isNull() && 
-       ! (elementType = commonTypeNode(t0[1], t1[1], isLeast)).isNull() ) {
-      return NodeManager::currentNM()->mkArrayType(indexType, elementType);
-    } else {
-      return TypeNode();
-    }
-  }
   case kind::SEXPR_TYPE:
     Unimplemented("haven't implemented leastCommonType for symbolic expressions yet");
     return TypeNode();
-  case kind::DATATYPE_TYPE:
-    if( t0.isTuple() && t1.isTuple() ){
-      const Datatype& dt1 = t0.getDatatype();
-      const Datatype& dt2 = t1.getDatatype();
-      if( dt1[0].getNumArgs()==dt2[0].getNumArgs() ){
-        std::vector< TypeNode > lc_types;
-        for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){
-          TypeNode tc = commonTypeNode( TypeNode::fromType( dt1[0][i].getRangeType() ), TypeNode::fromType( dt2[0][i].getRangeType() ), isLeast );
-          if( tc.isNull() ){
-            return tc;
-          }else{
-            lc_types.push_back( tc );
-          }
-        }
-        return NodeManager::currentNM()->mkTupleType( lc_types );
-      }
-    }
-    //else if( t0.isRecord() && t1.isRecord() ){
-      //record types are not related in current implementation
-    //}
-    // otherwise no common ancestor
-    return TypeNode();
-  case kind::PARAMETRIC_DATATYPE: {
-    if(!t1.isParametricDatatype()) {
-      return TypeNode();
-    }
-    if(t0[0] != t1[0] || t0.getNumChildren() != t1.getNumChildren()) {
-      return TypeNode();
-    }
-    vector<Type> v;
-    for(size_t i = 1; i < t0.getNumChildren(); ++i) {
-      v.push_back(commonTypeNode(t0[i], t1[i], isLeast).toType());
-    }
-    return TypeNode::fromType(t0[0].getDatatype().getDatatypeType(v));
-  }
   default:
     Unimplemented("don't have a commonType for types `%s' and `%s'", t0.toString().c_str(), t1.toString().c_str());
     return TypeNode();
index 6cc5c29a40e04dc18fa054a7dcfdd24c4df58cda..d0324cc45ccf50e7d15637f35227b6cd9505fde4 100644 (file)
@@ -2104,7 +2104,12 @@ simpleTerm[CVC4::Expr& f]
     /* syntactic predicate: never match INTEGER.DIGIT as an integer and a dot!
      * This is a rational constant!  Otherwise the parser interprets it as a tuple
      * selector! */
-  | DECIMAL_LITERAL { f = MK_CONST(AntlrInput::tokenToRational($DECIMAL_LITERAL)); }
+  | DECIMAL_LITERAL { 
+      f = MK_CONST(AntlrInput::tokenToRational($DECIMAL_LITERAL));
+      if(f.getType().isInteger()) {
+        f = MK_EXPR(kind::TO_REAL, f);
+      } 
+    }
   | INTEGER_LITERAL { f = MK_CONST(AntlrInput::tokenToInteger($INTEGER_LITERAL)); }
     /* bitvector literals */
   | HEX_LITERAL
index 86c0b31265e58a61460916bd536e9c2e8d46710e..92f6b36d8188553a4508ed070067a76a5631f405 100644 (file)
@@ -2254,7 +2254,12 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
   | DECIMAL_LITERAL
     { // FIXME: This doesn't work because an SMT rational is not a
       // valid GMP rational string
-      expr = MK_CONST( AntlrInput::tokenToRational($DECIMAL_LITERAL) ); }
+      expr = MK_CONST( AntlrInput::tokenToRational($DECIMAL_LITERAL) ); 
+      if(expr.getType().isInteger()) {
+        //must cast to Real to ensure correct type is passed to parametric type constructors
+        expr = MK_EXPR(kind::TO_REAL, expr);
+      }  
+    }
 
   | LPAREN_TOK INDEX_TOK 
     ( bvLit=SIMPLE_SYMBOL size=INTEGER_LITERAL 
index 57249e181629e6f985f2f8fe28de798057eb80db..4948216e56fb2d618b68655b5933b5aea6ce682e 100644 (file)
@@ -150,7 +150,7 @@ Node TheoryBuiltinRewriter::getLambdaForArrayRepresentation( TNode a, TNode bvl
   }
 }
 
-Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqConst ){
+Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec( TNode n, bool reqConst, TypeNode retType ){
   Assert( n.getKind()==kind::LAMBDA );
   Trace("builtin-rewrite-debug") << "Get array representation for : " << n << std::endl;
 
@@ -165,7 +165,6 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqCo
   }
 
   Trace("builtin-rewrite-debug2") << "  process body..." << std::endl;
-  TypeNode retType;
   std::vector< Node > conds;
   std::vector< Node > vals;
   Node curr = n[1];
@@ -214,7 +213,7 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqCo
     if( !curr_index.isNull() ){
       if( !rec_bvl.isNull() ){
         curr_val = NodeManager::currentNM()->mkNode( kind::LAMBDA, rec_bvl, curr_val );
-        curr_val = getArrayRepresentationForLambda( curr_val, reqConst );
+        curr_val = getArrayRepresentationForLambdaRec( curr_val, reqConst, retType );
         if( curr_val.isNull() ){
           Trace("builtin-rewrite-debug2") << "  ...non-constant value." << std::endl;
           return Node::null();
@@ -228,18 +227,22 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqCo
     conds.push_back( curr_index );
     vals.push_back( curr_val );
     TypeNode vtype = curr_val.getType();
-    retType = retType.isNull() ? vtype : TypeNode::leastCommonTypeNode( retType, vtype );
     //recurse
     curr = next;
   }
   if( !rec_bvl.isNull() ){
     curr = NodeManager::currentNM()->mkNode( kind::LAMBDA, rec_bvl, curr );
-    curr = getArrayRepresentationForLambda( curr );
+    curr = getArrayRepresentationForLambdaRec( curr, reqConst, retType );
   }
   if( !curr.isNull() && curr.isConst() ){
-    TypeNode ctype = curr.getType();
-    retType = retType.isNull() ? ctype : TypeNode::leastCommonTypeNode( retType, ctype );
-    TypeNode array_type = NodeManager::currentNM()->mkArrayType( first_arg.getType(), retType );
+    // compute the return type
+    TypeNode array_type = retType;
+    for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+      unsigned index = (n[0].getNumChildren()-1)-i;
+      array_type = NodeManager::currentNM()->mkArrayType( n[0][index].getType(), array_type );
+    }
+    Trace("builtin-rewrite-debug2") << "  make array store all " << curr.getType() << " annotated : " << array_type << std::endl;
+    Assert( curr.getType().isSubtypeOf( array_type.getArrayConstituentType() ) );
     curr = NodeManager::currentNM()->mkConst(ArrayStoreAll(((ArrayType)array_type.toType()), curr.toExpr()));
     Trace("builtin-rewrite-debug2") << "  build array..." << std::endl;
     // can only build if default value is constant (since array store all must be constant)
@@ -257,6 +260,13 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqCo
   }
 }
 
+Node TheoryBuiltinRewriter::getArrayRepresentationForLambda( TNode n, bool reqConst ){
+  Assert( n.getKind()==kind::LAMBDA );
+  // must carry the overall return type to deal with cases like (lambda ((x Int)(y Int)) (ite (= x _) 0.5 0.0)),
+  //  where the inner construction for the else case about should be (arraystoreall (Array Int Real) 0.0)
+  return getArrayRepresentationForLambdaRec( n, reqConst, n[1].getType() );
+}
+
 }/* CVC4::theory::builtin namespace */
 }/* CVC4::theory namespace */
 }/* CVC4 namespace */
index d9ae5b447b40ab3306c29f7ed1b5f5391a84a928..3667cf1592faf3da43a5514441a8cf4580488d53 100644 (file)
@@ -59,6 +59,8 @@ private:
   /** recursive helper for getLambdaForArrayRepresentation */
   static Node getLambdaForArrayRepresentationRec( TNode a, TNode bvl, unsigned bvlIndex, 
                                                   std::unordered_map< TNode, Node, TNodeHashFunction >& visited );
+  /** recursive helper for getArrayRepresentationForLambda */
+  static Node getArrayRepresentationForLambdaRec( TNode n, bool reqConst, TypeNode retType );
 public:
   /** 
    * Given an array constant a, returns a lambda expression that it corresponds to, with bound variable list bvl. 
index 025fe0349f528c3e2d62c612514841cc8945c0ff..49e8a6888254d263f79b3f2506c7d041d3f1c986 100644 (file)
@@ -36,29 +36,11 @@ public:
     Trace("datatypes-rewrite-debug") << "post-rewriting " << in << std::endl;
 
     if(in.getKind() == kind::APPLY_CONSTRUCTOR ){
+      /*
       TypeNode tn = in.getType();
       Type t = tn.toType();
       DatatypeType dt = DatatypeType(t);
-      //check for parametric datatype constructors
-      // to ensure a normal form, all parameteric datatype constructors must have a type ascription
-      if( dt.isParametric() ){
-        if( in.getOperator().getKind()!=kind::APPLY_TYPE_ASCRIPTION ){
-          Trace("datatypes-rewrite-debug") << "Ascribing type to parametric datatype constructor " << in << std::endl;
-          Node op = in.getOperator();
-          //get the constructor object
-          const DatatypeConstructor& dtc = Datatype::datatypeOf(op.toExpr())[Datatype::indexOf(op.toExpr())];
-          //create ascribed constructor type
-          Node tc = NodeManager::currentNM()->mkConst(AscriptionType(dtc.getSpecializedConstructorType(t)));
-          Node op_new = NodeManager::currentNM()->mkNode( kind::APPLY_TYPE_ASCRIPTION, tc, op );
-          //make new node
-          std::vector< Node > children;
-          children.push_back( op_new );
-          children.insert( children.end(), in.begin(), in.end() );
-          Node inr = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, children );
-          Trace("datatypes-rewrite-debug") << "Created " << inr << std::endl;
-          return RewriteResponse(REWRITE_DONE, inr);
-        }
-      }
+      // enable this rewrite if we support subtypes of tuples
       if( tn.isTuple() ){
         Node nn = normalizeTupleConstructorApp( in );
         if( nn!=in ){
@@ -66,6 +48,7 @@ public:
           return RewriteResponse(REWRITE_AGAIN_FULL, nn);
         }
       }
+      */
       if( in.isConst() ){
         Trace("datatypes-rewrite-debug") << "Normalizing constant " << in << std::endl;
         Node inn = normalizeConstant( in );
@@ -241,6 +224,33 @@ public:
 
   static RewriteResponse preRewrite(TNode in) {
     Trace("datatypes-rewrite-debug") << "pre-rewriting " << in << std::endl;
+    //must prewrite to apply type ascriptions since rewriting does not preserve types
+    if(in.getKind() == kind::APPLY_CONSTRUCTOR ){
+      TypeNode tn = in.getType();
+      Type t = tn.toType();
+      DatatypeType dt = DatatypeType(t);
+      
+      //check for parametric datatype constructors
+      // to ensure a normal form, all parameteric datatype constructors must have a type ascription
+      if( dt.isParametric() ){
+        if( in.getOperator().getKind()!=kind::APPLY_TYPE_ASCRIPTION ){
+          Trace("datatypes-rewrite-debug") << "Ascribing type to parametric datatype constructor " << in << std::endl;
+          Node op = in.getOperator();
+          //get the constructor object
+          const DatatypeConstructor& dtc = Datatype::datatypeOf(op.toExpr())[Datatype::indexOf(op.toExpr())];
+          //create ascribed constructor type
+          Node tc = NodeManager::currentNM()->mkConst(AscriptionType(dtc.getSpecializedConstructorType(t)));
+          Node op_new = NodeManager::currentNM()->mkNode( kind::APPLY_TYPE_ASCRIPTION, tc, op );
+          //make new node
+          std::vector< Node > children;
+          children.push_back( op_new );
+          children.insert( children.end(), in.begin(), in.end() );
+          Node inr = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, children );
+          Trace("datatypes-rewrite-debug") << "Created " << inr << std::endl;
+          return RewriteResponse(REWRITE_DONE, inr);
+        }
+      }
+    }
     return RewriteResponse(REWRITE_DONE, in);
   }
 
@@ -251,10 +261,11 @@ public:
     Trace("datatypes-rewrite-debug") << "Check clash : " << n1 << " " << n2 << std::endl;
     if( n1.getKind() == kind::APPLY_CONSTRUCTOR && n2.getKind() == kind::APPLY_CONSTRUCTOR ) {
       if( n1.getOperator() != n2.getOperator()) {
-        if( n1.getNumChildren() != n2.getNumChildren() || !n1.getType().isTuple() || !n2.getType().isTuple() ){
-          Trace("datatypes-rewrite-debug") << "Clash operators : " << n1 << " " << n2 << " " << n1.getOperator() << " " << n2.getOperator() << std::endl;
-          return true;
-        }
+        //enable this check if we support subtypes with tuples
+        //if( n1.getNumChildren() != n2.getNumChildren() || !n1.getType().isTuple() || !n2.getType().isTuple() ){
+        Trace("datatypes-rewrite-debug") << "Clash operators : " << n1 << " " << n2 << " " << n1.getOperator() << " " << n2.getOperator() << std::endl;
+        return true;
+        //}
       }
       Assert( n1.getNumChildren() == n2.getNumChildren() );
       for( unsigned i=0; i<n1.getNumChildren(); i++ ) {
@@ -649,9 +660,11 @@ public:
   static Node normalizeConstant( Node n ){
     TypeNode tn = n.getType();
     if( tn.isDatatype() ){
-      if( tn.isTuple() ){
-        return normalizeTupleConstructorApp( n );
-      }else if( tn.isCodatatype() ){
+      // enable this if we support subtyping with tuples
+      //if( tn.isTuple() ){
+      //  return normalizeTupleConstructorApp( n );
+      //} 
+      if( tn.isCodatatype() ){
         return normalizeCodatatypeConstant( n );
       }else{
         std::vector< Node > children;
index e787ebc49e46846651af81b62ad383675d728c35..d6045404d8d422637ce1f49c9cc8758415028399 100644 (file)
@@ -101,6 +101,8 @@ struct DatatypeConstructorTypeRule {
         return false;
       }
     }
+    //if we support subtyping for tuples, enable this
+    /*
     //check whether it is in normal form?
     TypeNode tn = n.getType();
     if( tn.isTuple() ){
@@ -114,6 +116,7 @@ struct DatatypeConstructorTypeRule {
     }else if( tn.isCodatatype() ){
       //TODO?
     }
+    */
     return true;
   }
 }; /* struct DatatypeConstructorTypeRule */
index 17a2ea2efaeee9bca4954a9c48cbd7108853cd8f..1368dd0674fd706ec0e64f62674707fa8d2b09a0 100644 (file)
@@ -189,6 +189,7 @@ TESTS = $(SMT_TESTS) $(SMT2_TESTS) $(CVC_TESTS) $(TPTP_TESTS) $(BUG_TESTS)
 # we have a minimized version still getting tested
 # bug639 -- still fails, reopened bug
 # bug585 -- contains subrange type (not supported)
+# issue1048-arrays-int-real.smt2 -- different errors on debug and production
 DISABLED_TESTS = \
        bug512.smt2 \
        bug585.cvc
index 4d7345a540aa41b606627d9ed2d88d60050f1227..ecdc8198fc39eb9f4abec1a8bb29f4fea02f81d8 100644 (file)
@@ -6,6 +6,6 @@ y : REAL;
 z : REAL;
 
 ASSERT x = (y, z) OR x = (z, y);
-ASSERT x = (0,0) OR x = (1,1);
+ASSERT x = (0.0,0.0) OR x = (1.0,1.0);
 
 CHECKSAT;
diff --git a/test/regress/regress0/issue1048-arrays-int-real.smt2 b/test/regress/regress0/issue1048-arrays-int-real.smt2
new file mode 100644 (file)
index 0000000..6bbfe4c
--- /dev/null
@@ -0,0 +1,6 @@
+(set-logic QF_ALIRA)
+(declare-fun a () (Array Int Real))
+(declare-fun b () (Array Int Int))
+(assert (= a b))
+(assert (= (select a 0) 0.5))
+(check-sat)
index c5a81c960d571f36b7e348339ee94e4ede7ee9e6..cdf2ec9bcd07a98f0c39572334f322321c0047e4 100644 (file)
@@ -70,10 +70,7 @@ TESTS =      \
        agg-rew-test-cf.smt2 \
        rew-to-0211-dd.smt2 \
        rew-to-scala.smt2 \
-       macro-subtype-param.smt2 \
        macros-real-arg.smt2 \
-       subtype-param-unk.smt2 \
-       subtype-param.smt2 \
        anti-sk-simp.smt2 \
        pure_dt_cbqi.smt2 \
        florian-case-ax.smt2 \
@@ -108,6 +105,11 @@ TESTS =    \
 #              clock-10.smt2
 #
 
+# FIXME: I've disabled these since they give different error messages on production and debug
+#      macro-subtype-param.smt2 
+#      subtype-param-unk.smt2 
+#      subtype-param.smt2 
+
 EXTRA_DIST = $(TESTS) \
        bug291.smt2.expect
 
index f44d751957182bebf7fc60300222ab44c44daf40..97ff827a76e97e5b6813301e462dc97967ceef80 100644 (file)
@@ -1,5 +1,11 @@
 ; COMMAND-LINE: --macros-quant
-; EXPECT: unknown
+; EXPECT: (error "argument type is not a subtype of the function's argument type:
+; EXPECT: argument:  x
+; EXPECT: has type:  (List Int)
+; EXPECT: not subtype: (List Real)
+; EXPECT: in term : (R (as x (List Real)))")
+; EXIT: 1
+
 (set-logic ALL_SUPPORTED)
 
 (declare-datatypes ((List 1)) ((par (T) ((cons (hd T) (tl (List T))) (nil)))))
index e3008772d7336f51669894b96ac686c3279a98ca..f3ee6a86a2826ffc2057ff3ed17e32e428731eb3 100644 (file)
@@ -1,5 +1,11 @@
 ; COMMAND-LINE: --lang=smt2.5
-; EXPECT: unknown
+; EXPECT: (error "argument type is not a subtype of the function's argument type:
+; EXPECT: argument:  x
+; EXPECT: has type:  (List Int)
+; EXPECT: not subtype: (List Real)
+; EXPECT: in term : (R (as x (List Real)))")
+; EXIT: 1
+
 ; this will fail if type rule for APPLY_UF requires arguments to be subtypes
 (set-logic ALL_SUPPORTED)
 
index 42d7a5b6030844246e3602c1b629cb7d5dcb96bb..860c03b6f5ed30a028b1e62f4a52579d915aaed8 100644 (file)
@@ -1,5 +1,11 @@
 ; COMMAND-LINE: --lang=smt2.5
-; EXPECT: unsat
+; EXPECT: (error "argument type is not a subtype of the function's argument type:
+; EXPECT: argument:  x
+; EXPECT: has type:  (Array Int Int)
+; EXPECT: not subtype: (Array Int Real)
+; EXPECT: in term : (Q (as x (Array Int Real)))")
+; EXIT: 1
+
 (set-logic ALL_SUPPORTED)
 (set-info :status unsat)
 
index 64fb310bede9adb111fe8449f2ba0afca7de66bc..4cac9a24edd9428eed0b7a14d2614f47ddd50738 100644 (file)
@@ -7,7 +7,7 @@ b : SET OF [INT, REAL];
 
 x : [ REAL, REAL ];
 
-ASSERT NOT x = (0,0);
+ASSERT NOT x = (0.0,0.0);
 
 ASSERT (x.0, FLOOR(x.1)) IS_IN a;
 ASSERT (FLOOR(x.0), x.1) IS_IN b;
index 9f26312dc3eb91d3db837fb1cb2c5ca2c2514aba..15c380c317d1598c11994da71a418ebeae18832c 100644 (file)
@@ -363,60 +363,55 @@ public:
     TS_ASSERT_DIFFERS(pairIntInt, pairRealInt);
     TS_ASSERT_DIFFERS(pairIntReal, pairRealInt);
 
-    TS_ASSERT_EQUALS(pairRealReal.getBaseType(), pairRealReal);
-    TS_ASSERT_EQUALS(pairRealInt.getBaseType(), pairRealReal);
-    TS_ASSERT_EQUALS(pairIntReal.getBaseType(), pairRealReal);
-    TS_ASSERT_EQUALS(pairIntInt.getBaseType(), pairRealReal);
-
     TS_ASSERT(pairRealReal.isComparableTo(pairRealReal));
-    TS_ASSERT(pairIntReal.isComparableTo(pairRealReal));
-    TS_ASSERT(pairRealInt.isComparableTo(pairRealReal));
-    TS_ASSERT(pairIntInt.isComparableTo(pairRealReal));
-    TS_ASSERT(pairRealReal.isComparableTo(pairRealInt));
-    TS_ASSERT(pairIntReal.isComparableTo(pairRealInt));
+    TS_ASSERT(!pairIntReal.isComparableTo(pairRealReal));
+    TS_ASSERT(!pairRealInt.isComparableTo(pairRealReal));
+    TS_ASSERT(!pairIntInt.isComparableTo(pairRealReal));
+    TS_ASSERT(!pairRealReal.isComparableTo(pairRealInt));
+    TS_ASSERT(!pairIntReal.isComparableTo(pairRealInt));
     TS_ASSERT(pairRealInt.isComparableTo(pairRealInt));
-    TS_ASSERT(pairIntInt.isComparableTo(pairRealInt));
-    TS_ASSERT(pairRealReal.isComparableTo(pairIntReal));
+    TS_ASSERT(!pairIntInt.isComparableTo(pairRealInt));
+    TS_ASSERT(!pairRealReal.isComparableTo(pairIntReal));
     TS_ASSERT(pairIntReal.isComparableTo(pairIntReal));
-    TS_ASSERT(pairRealInt.isComparableTo(pairIntReal));
-    TS_ASSERT(pairIntInt.isComparableTo(pairIntReal));
-    TS_ASSERT(pairRealReal.isComparableTo(pairIntInt));
-    TS_ASSERT(pairIntReal.isComparableTo(pairIntInt));
-    TS_ASSERT(pairRealInt.isComparableTo(pairIntInt));
+    TS_ASSERT(!pairRealInt.isComparableTo(pairIntReal));
+    TS_ASSERT(!pairIntInt.isComparableTo(pairIntReal));
+    TS_ASSERT(!pairRealReal.isComparableTo(pairIntInt));
+    TS_ASSERT(!pairIntReal.isComparableTo(pairIntInt));
+    TS_ASSERT(!pairRealInt.isComparableTo(pairIntInt));
     TS_ASSERT(pairIntInt.isComparableTo(pairIntInt));
 
     TS_ASSERT(pairRealReal.isSubtypeOf(pairRealReal));
-    TS_ASSERT(pairIntReal.isSubtypeOf(pairRealReal));
-    TS_ASSERT(pairRealInt.isSubtypeOf(pairRealReal));
-    TS_ASSERT(pairIntInt.isSubtypeOf(pairRealReal));
+    TS_ASSERT(!pairIntReal.isSubtypeOf(pairRealReal));
+    TS_ASSERT(!pairRealInt.isSubtypeOf(pairRealReal));
+    TS_ASSERT(!pairIntInt.isSubtypeOf(pairRealReal));
     TS_ASSERT(!pairRealReal.isSubtypeOf(pairRealInt));
     TS_ASSERT(!pairIntReal.isSubtypeOf(pairRealInt));
     TS_ASSERT(pairRealInt.isSubtypeOf(pairRealInt));
-    TS_ASSERT(pairIntInt.isSubtypeOf(pairRealInt));
+    TS_ASSERT(!pairIntInt.isSubtypeOf(pairRealInt));
     TS_ASSERT(!pairRealReal.isSubtypeOf(pairIntReal));
     TS_ASSERT(pairIntReal.isSubtypeOf(pairIntReal));
     TS_ASSERT(!pairRealInt.isSubtypeOf(pairIntReal));
-    TS_ASSERT(pairIntInt.isSubtypeOf(pairIntReal));
+    TS_ASSERT(!pairIntInt.isSubtypeOf(pairIntReal));
     TS_ASSERT(!pairRealReal.isSubtypeOf(pairIntInt));
     TS_ASSERT(!pairIntReal.isSubtypeOf(pairIntInt));
     TS_ASSERT(!pairRealInt.isSubtypeOf(pairIntInt));
     TS_ASSERT(pairIntInt.isSubtypeOf(pairIntInt));
 
     TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairRealReal)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairRealReal)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairRealReal)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairRealReal)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairRealInt)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairRealInt)).toType(), pairRealReal);
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairRealReal)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairRealReal)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairRealReal)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairRealInt)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairRealInt)).isNull());
     TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairRealInt)).toType(), pairRealInt);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairRealInt)).toType(), pairRealInt);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairIntReal)).toType(), pairRealReal);
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairRealInt)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairIntReal)).isNull());
     TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairIntReal)).toType(), pairIntReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairIntReal)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairIntReal)).toType(), pairIntReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairIntInt)).toType(), pairRealReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairIntInt)).toType(), pairIntReal);
-    TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairIntInt)).toType(), pairRealInt);
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairIntReal)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairIntReal)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealReal), TypeNode::fromType(pairIntInt)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntReal), TypeNode::fromType(pairIntInt)).isNull());
+    TS_ASSERT(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairRealInt), TypeNode::fromType(pairIntInt)).isNull());
     TS_ASSERT_EQUALS(TypeNode::leastCommonTypeNode(TypeNode::fromType(pairIntInt), TypeNode::fromType(pairIntInt)).toType(), pairIntInt);
   }