diff --git a/CHANGELOG.md b/CHANGELOG.md index 794318838c7f4e54f5f46baafcc05889f25d0e12..b98949c4008148205ef297980a96aa80c75dd825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ +## Next + +* Fixed [#165](https://github.com/manastech/crystal/issues/165): restrictions with generic types didn't work for hierarchy types. + ## 0.3.3 (2014-07-14) * Allow implicit conversion to C types by defining a `to_unsafe` method. This removed the hardcoded rule for converting a `String` to `UInt8*` and also allows passing an `Array(T)` to an argument expecting `Pointer(T)`. -* Fixed `.is_a?(Class)` not working (#162) +* Fixed `.is_a?(Class)` not working ([#162](https://github.com/manastech/crystal/issues/162)) * Attributes are now associated to AST nodes in the semantic pass, not during parsing. This allows macros to generate attributes that will be attached to subsequent expressions. * **(breaking change)** Make ENV#[] raise on missing key, and added ENV#[]? * **(breaking change)** Macro defs are now written like `macro def name(args) : ReturnType` instead of `def name(args) : ReturnType`, which was a bit confusing. diff --git a/spec/compiler/codegen/def_spec.cr b/spec/compiler/codegen/def_spec.cr index 99692c048f27592ce77c90fc0184e8131c36d4c9..963dab311658b8fa99ce469cc50eb3dacddca94e 100755 --- a/spec/compiler/codegen/def_spec.cr +++ b/spec/compiler/codegen/def_spec.cr @@ -463,4 +463,35 @@ describe "Code gen: def" do foo(node) ").to_i.should eq(1) end + + it "dispatches on hierarchy type implementing generic module (related to bug #165)" do + run(" + module Moo(T) + def moo + 1 + end + end + + abstract class Foo + end + + class Bar < Foo + include Moo(Int32) + end + + class Baz < Foo + end + + def method(x : Moo(Int32)) + x.moo + end + + def method(x : Baz) + 2 + end + + foo = Bar.new || Baz.new + method(foo) + ").to_i.should eq(1) + end end diff --git a/spec/compiler/type_inference/def_spec.cr b/spec/compiler/type_inference/def_spec.cr index 0ae4e7310bbcef92640c7b2aa48d9d71c7639f8f..2bb02df297e55eea3be56003927d1c0038ba12d2 100755 --- a/spec/compiler/type_inference/def_spec.cr +++ b/spec/compiler/type_inference/def_spec.cr @@ -303,4 +303,18 @@ describe "Type inference: def" do b.foo ) { int32 } end + + it "fixes bug #165" do + assert_error %( + abstract class Node + end + + def foo(nodes : Pointer(Node)) + foo nodes.value + end + + a = Pointer(Node).new(0_u64) + foo a + ), "no overload matches" + end end diff --git a/src/compiler/crystal/type_inference/restrictions.cr b/src/compiler/crystal/type_inference/restrictions.cr index 4a526da8c7e02f4f573cafa3d13a8c94684b4efe..ac8cee09c07438b87a9d3ba29786e44c0ae38d87 100644 --- a/src/compiler/crystal/type_inference/restrictions.cr +++ b/src/compiler/crystal/type_inference/restrictions.cr @@ -381,6 +381,15 @@ module Crystal nil end end + + def restrict(other : Generic, owner, type_lookup, free_vars) + types = [] of Type + base_type.subclasses.each do |subclass| + restricted = subclass.hierarchy_type.restrict(other, owner, type_lookup, free_vars) + types << restricted if restricted + end + program.type_merge_union_of types + end end class AliasType