From c5f482822567302b5b4329a384dc9b8b523c818b Mon Sep 17 00:00:00 2001
From: Ary Borenszweig <aborenszweig@manas.com.ar>
Date: Fri, 24 Jan 2014 11:15:15 -0300
Subject: [PATCH] Better restriction check for generic types

---
 spec/compiler/codegen/is_a_spec.cr                  | 10 ++++++++++
 spec/compiler/type_inference/def_overload_spec.cr   | 13 +++++++++++++
 src/compiler/crystal/type_inference/restrictions.cr |  4 ++--
 src/compiler/crystal/type_inference/type_merge.cr   |  2 +-
 4 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/spec/compiler/codegen/is_a_spec.cr b/spec/compiler/codegen/is_a_spec.cr
index f0e1db89c3..0e848c62b5 100755
--- a/spec/compiler/codegen/is_a_spec.cr
+++ b/spec/compiler/codegen/is_a_spec.cr
@@ -287,4 +287,14 @@ describe "Codegen: is_a?" do
       2.is_a?(A)
       ").to_b.should be_false
   end
+
+  it "gives false if generic type doesn't match exactly" do
+    run("
+      class Foo(T)
+      end
+
+      foo = Foo(Int32 | Float64).new
+      foo.is_a?(Foo(Int32)) ? 1 : 2
+      ").to_i.should eq(2)
+  end
 end
diff --git a/spec/compiler/type_inference/def_overload_spec.cr b/spec/compiler/type_inference/def_overload_spec.cr
index bfd154a384..4769b8c71e 100755
--- a/spec/compiler/type_inference/def_overload_spec.cr
+++ b/spec/compiler/type_inference/def_overload_spec.cr
@@ -519,4 +519,17 @@ describe "Type inference: def overload" do
       1
       ") { int32 }
   end
+
+  it "errors if generic type doesn't match" do
+    assert_error "
+      class Foo(T)
+      end
+
+      def foo(x : Foo(Int32))
+      end
+
+      foo Foo(Int32 | Float64).new
+      ",
+      "no overload matches"
+  end
 end
diff --git a/src/compiler/crystal/type_inference/restrictions.cr b/src/compiler/crystal/type_inference/restrictions.cr
index 7c55d30bef..7f0e7b4358 100644
--- a/src/compiler/crystal/type_inference/restrictions.cr
+++ b/src/compiler/crystal/type_inference/restrictions.cr
@@ -236,7 +236,7 @@ module Crystal
       type_vars.each do |name, type_var|
         other_type_var = other.type_vars[i]
         restricted = type_var.type.restrict other_type_var, owner, type_lookup, free_vars
-        return nil unless restricted
+        return nil unless restricted == type_var.type
         i += 1
       end
 
@@ -249,7 +249,7 @@ module Crystal
       type_vars.each do |name, type_var|
         other_type_var = other.type_vars[name]
         restricted = type_var.type.restrict(other_type_var.type, owner, type_lookup, free_vars)
-        return nil unless restricted
+        return nil unless restricted == type_var.type
       end
 
       self
diff --git a/src/compiler/crystal/type_inference/type_merge.cr b/src/compiler/crystal/type_inference/type_merge.cr
index 1eb3a19272..7138d37dc8 100644
--- a/src/compiler/crystal/type_inference/type_merge.cr
+++ b/src/compiler/crystal/type_inference/type_merge.cr
@@ -2,7 +2,7 @@ require "../program"
 
 module Crystal
   class Program
-    def type_merge(types : Array(Type))
+    def type_merge(types : Array(Type?))
       combined_union_of compact_types(types)
     end
 
-- 
GitLab