diff --git a/spec/compiler/codegen/generic_class_spec.cr b/spec/compiler/codegen/generic_class_spec.cr index 06ac018feee4f6990ee2fae54a0668cdffe5e4d7..82292484438eae2d7553072210cd23a3a80210b8 100644 --- a/spec/compiler/codegen/generic_class_spec.cr +++ b/spec/compiler/codegen/generic_class_spec.cr @@ -48,4 +48,44 @@ describe "Code gen: generic class type" do p.value.x.to_i )).to_i.should eq('a'.ord) end + + it "creates pointer of unspecified generic type with inherited class" do + run(%( + class Foo(T) + def initialize(@x : T) + end + + def x + @x + 1 + end + end + + class Bar < Foo(Int32) + end + + p = Pointer(Foo).malloc(1_u64) + p.value = Bar.new(1) + p.value.x + )).to_i.should eq(2) + end + + it "creates pointer of unspecified generic type with inherited class (2)" do + run(%( + class Foo(T) + def initialize(@x : T) + end + + def x + @x + 1 + end + end + + class Bar(T) < Foo(T) + end + + p = Pointer(Foo).malloc(1_u64) + p.value = Bar.new(1) + p.value.x + )).to_i.should eq(2) + end end diff --git a/spec/compiler/type_inference/generic_class_spec.cr b/spec/compiler/type_inference/generic_class_spec.cr index 24762d005dfd7cca750746a094c924ee44be8ce1..10fada620519bbb654aaf1ab48b29f7db085bc44 100644 --- a/spec/compiler/type_inference/generic_class_spec.cr +++ b/spec/compiler/type_inference/generic_class_spec.cr @@ -255,4 +255,18 @@ describe "Type inference: generic class" do p.value.x )) { union_of int32, char } end + + it "creates pointer of unspecified generic type with inherited class" do + assert_type(%( + class Foo(T) + end + + class Bar(T) < Foo(T) + end + + p = Pointer(Foo).malloc(1_u64) + p.value = Bar(Int32).new + p.value + )) { types["Foo"] } + end end diff --git a/src/compiler/crystal/semantic/restrictions.cr b/src/compiler/crystal/semantic/restrictions.cr index 72ca347990baa985a3df4f59129fa5ae2467fbdc..51c71f9b5427e9658af92434cc94ed1491482b82 100644 --- a/src/compiler/crystal/semantic/restrictions.cr +++ b/src/compiler/crystal/semantic/restrictions.cr @@ -302,7 +302,7 @@ module Crystal end def restrict(other : GenericClassType, context) - generic_class == other ? self : nil + generic_class == other ? self : super end def restrict(other : Generic, context) diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index d2f1e92a2aaf25ee5bfe36a1cff0105de954a455..5c7b5e85c8c0d9cadc0cede336fa985238710724 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -1672,7 +1672,16 @@ module Crystal end def including_types - program.union_of generic_types.values + instances = generic_types.values + subclasses.each do |subclass| + if subclass.is_a?(GenericClassType) + subtypes = subclass.including_types + instances.concat subtypes if subtypes + else + instances << subclass + end + end + program.union_of instances end def to_s(io)