diff --git a/spec/compiler/codegen/sizeof_spec.cr b/spec/compiler/codegen/sizeof_spec.cr index 168dabac67e8..2f703abd1c71 100644 --- a/spec/compiler/codegen/sizeof_spec.cr +++ b/spec/compiler/codegen/sizeof_spec.cr @@ -72,6 +72,21 @@ describe "Code gen: sizeof" do assert_error "instance_sizeof(Int32)", "Int32 is not a class, it's a struct" end + it "gives error if using instance_sizeof on a generic type without type vars" do + assert_error "instance_sizeof(Array)", "can't calculate instance_sizeof of generic class" + end + + it "gets instance_sizeof a generic type with type vars" do + run(%( + class Foo(T) + def initialize(@x : T) + end + end + + instance_sizeof(Foo(Int32)) + )).to_i.should eq(8) + end + it "gets sizeof Void" do # Same as the size of a byte run("sizeof(Void)").to_i.should eq(1) diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index 75e09d5ff6f9..ab83d48ecedf 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -2452,10 +2452,15 @@ module Crystal node.exp.accept self @in_type_args -= 1 + type = node.exp.type? + unless type + raise "BUG: #{node} at #{node.location} should receive a type" + end + # Try to resolve the sizeof right now to a number literal # (useful for sizeof inside as a generic type argument, but also # to make it easier for LLVM to optimize things) - if (type = node.exp.type?) && !node.exp.is_a?(TypeOf) + if !node.exp.is_a?(TypeOf) expanded = NumberLiteral.new(@program.size_of(type.sizeof_type)) expanded.type = @program.int32 node.expanded = expanded @@ -2469,10 +2474,19 @@ module Crystal node.exp.accept self @in_type_args -= 1 + type = node.exp.type? + unless type + raise "BUG: #{node} at #{node.location} should receive a type" + end + + if type.is_a? GenericType + node.raise "can't calculate instance_sizeof of generic class #{type} without specifying its type vars" + end + # Try to resolve the instance_sizeof right now to a number literal # (useful for sizeof inside as a generic type argument, but also # to make it easier for LLVM to optimize things) - if (type = node.exp.type?) && type.instance_type.devirtualize.class? && !node.exp.is_a?(TypeOf) + if type.instance_type.devirtualize.class? && !node.exp.is_a?(TypeOf) expanded = NumberLiteral.new(@program.instance_size_of(type.sizeof_type)) expanded.type = @program.int32 node.expanded = expanded