From b8da1b1481081bcdc1571ea69ce4321caaf3d0e3 Mon Sep 17 00:00:00 2001
From: Etienne Kneuss <ekneuss@gmail.com>
Date: Wed, 19 Aug 2015 16:03:07 +0200
Subject: [PATCH] Fix canBeSubtypeOf

---
 src/main/scala/leon/purescala/TypeOps.scala   | 33 +++-------
 .../leon/test/purescala/TypeOpsSuite.scala    | 63 +++++++++++++++++++
 2 files changed, 73 insertions(+), 23 deletions(-)
 create mode 100644 src/test/scala/leon/test/purescala/TypeOpsSuite.scala

diff --git a/src/main/scala/leon/purescala/TypeOps.scala b/src/main/scala/leon/purescala/TypeOps.scala
index 05317ca8f..0eac83d63 100644
--- a/src/main/scala/leon/purescala/TypeOps.scala
+++ b/src/main/scala/leon/purescala/TypeOps.scala
@@ -24,9 +24,9 @@ object TypeOps {
 
   def canBeSubtypeOf(
     tpe: TypeTree,
-    freeParams: Seq[TypeParameter], 
+    freeParams: Seq[TypeParameter],
     stpe: TypeTree,
-    lhsFixed: Boolean = false, 
+    lhsFixed: Boolean = false,
     rhsFixed: Boolean = false
   ): Option[Map[TypeParameter, TypeTree]] = {
 
@@ -55,23 +55,14 @@ object TypeOps {
       }
     } else {
       (tpe, stpe) match {
-        case (t, tp1: TypeParameter) =>
-          if ((freeParams contains tp1) && (!rhsFixed) && !(typeParamsOf(t) contains tp1)) {
-            Some(Map(tp1 -> t))
-          } else if (tp1 == t) {
-            Some(Map())
-          } else {
-            None
-          }
+        case (t1, t2) if t1 == t2 =>
+          Some(Map())
 
-        case (tp1: TypeParameter, t) =>
-          if ((freeParams contains tp1) && (!lhsFixed) && !(typeParamsOf(t) contains tp1)) {
-            Some(Map(tp1 -> t))
-          } else if (tp1 == t) {
-            Some(Map())
-          } else {
-            None
-          }
+        case (t, tp1: TypeParameter) if (freeParams contains tp1) && (!rhsFixed) && !(typeParamsOf(t) contains tp1) =>
+          Some(Map(tp1 -> t))
+
+        case (tp1: TypeParameter, t) if (freeParams contains tp1) && (!lhsFixed) && !(typeParamsOf(t) contains tp1) =>
+          Some(Map(tp1 -> t))
 
         case (ct1: ClassType, ct2: ClassType) =>
           val rt1 = ct1.root
@@ -103,11 +94,7 @@ object TypeOps {
           }
 
         case (t1, t2) =>
-          if (t1 == t2) {
-            Some(Map())
-          } else {
-            None
-          }
+          None
       }
     }
   }
diff --git a/src/test/scala/leon/test/purescala/TypeOpsSuite.scala b/src/test/scala/leon/test/purescala/TypeOpsSuite.scala
new file mode 100644
index 000000000..af9edfec0
--- /dev/null
+++ b/src/test/scala/leon/test/purescala/TypeOpsSuite.scala
@@ -0,0 +1,63 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.test.purescala
+
+import leon.test._
+import leon.purescala.Common._
+import leon.purescala.Expressions._
+import leon.purescala.Definitions._
+import leon.purescala.Types._
+import leon.purescala.ExprOps._
+import leon.purescala.TypeOps._
+
+class TypeOpsSuite extends LeonTestSuite with helpers.WithLikelyEq with helpers.ExpressionsDSL {
+
+  test("canBeSubtypeOf 1") { ctx =>
+    val tp    = TypeParameter.fresh("T")
+    val tpD   = new TypeParameterDef(tp)
+
+    val tp2   = TypeParameter.fresh("A")
+    val tp3   = TypeParameter.fresh("B")
+    val tp4   = TypeParameter.fresh("C")
+
+    val listD = AbstractClassDef(FreshIdentifier("List"), Seq(tpD), None)
+    val listT = listD.typed
+
+    val nilD  = CaseClassDef(FreshIdentifier("Nil"),  Seq(tpD), Some(listT), false)
+    val nilT  = nilD.typed
+
+    val consD = CaseClassDef(FreshIdentifier("Cons"), Seq(tpD), Some(listT), false)
+    val consT = consD.typed
+
+    // Simple tests for fixed types
+    assert(canBeSubtypeOf(tp,       Seq(), tp).isDefined,    "Same types can be subtypes")
+    assert(canBeSubtypeOf(listT,    Seq(), listT).isDefined, "Different types are not subtypes")
+
+    assert(canBeSubtypeOf(tp2,          Seq(), tp3).isEmpty,         "Different types are not subtypes")
+    assert(canBeSubtypeOf(BooleanType,  Seq(), tp3).isEmpty,         "Different types are not subtypes")
+    assert(canBeSubtypeOf(tp2,          Seq(), BooleanType).isEmpty, "Different types are not subtypes")
+    assert(canBeSubtypeOf(IntegerType,  Seq(), Int32Type).isEmpty,   "Different types are not subtypes")
+
+    assert(canBeSubtypeOf(nilT,         Seq(), listT).isDefined,   "Subtypes are subtypes")
+    assert(canBeSubtypeOf(consT,        Seq(), listT).isDefined,   "Subtypes are subtypes")
+
+    assert(canBeSubtypeOf(listT,        Seq(), nilT).isEmpty,    "Supertypes are not subtypes")
+    assert(canBeSubtypeOf(listT,        Seq(), consT).isEmpty,   "Supertypes are not subtypes")
+
+    // Type parameters
+    assert(canBeSubtypeOf(tp,           Seq(tp),  tp2).isDefined,    "T <: A with T free")
+    assert(canBeSubtypeOf(tp,           Seq(tp2), tp2).isDefined,    "T <: A with A free")
+
+    assert(canBeSubtypeOf(listT,        Seq(tp),  listD.typed(Seq(tp2))).isDefined,    "List[T] <: List[A] with T free")
+    assert(canBeSubtypeOf(listT,        Seq(tp2), listD.typed(Seq(tp2))).isDefined,    "List[T] <: List[A] with A free")
+
+    // Type parameters with fixed sides
+    assert(canBeSubtypeOf(tp,           Seq(tp),  tp2, lhsFixed = true).isEmpty,    "T </: A with T free when lhs is fixed")
+    assert(canBeSubtypeOf(tp,           Seq(tp),  tp2, rhsFixed = true).isDefined,  "T <: A with T free but rhs is fixed")
+    assert(canBeSubtypeOf(tp,           Seq(tp2), tp2, lhsFixed = true).isDefined,  "T <: A with A free when lhs is fixed")
+    assert(canBeSubtypeOf(tp,           Seq(tp2), tp2, rhsFixed = true).isEmpty,    "T </: A with A free but lhs is fixed")
+
+    assert(canBeSubtypeOf(listT,        Seq(tp),  listD.typed(Seq(tp2)), rhsFixed = true).isDefined,    "List[T] <: List[A] with T free and rhs fixed")
+  }
+
+}
-- 
GitLab