Forum | Documentation | Website | Blog

Skip to content
Snippets Groups Projects
Commit 996a0ebf authored by Ary Borenszweig's avatar Ary Borenszweig
Browse files

Simpler and more accurate way to infer generic type type vars from initialize

parent a469e3c1
No related merge requests found
......@@ -661,4 +661,21 @@ describe "Type inference: class" do
(types["Foo"] as GenericClassType).instantiate([types["Baz"]] of Type | ASTNode)
end
end
it "infers generic type after instance was created with explicit type" do
assert_type("
class Foo(T)
def initialize(@x : T)
end
def x
@x
end
end
foo1 = Foo(Bool).new(true)
foo2 = Foo.new(1)
foo2.x
") { int32 }
end
end
......@@ -615,36 +615,25 @@ module Crystal
end
def self.define_new_with_initialize(scope, arg_types, matches)
ms = matches.map do |match|
if match.free_vars.empty?
alloc = Call.new(nil, "allocate")
else
generic_class = scope.instance_type as GenericClassType
type_vars = Array(ASTNode?).new(generic_class.type_vars.length, nil)
match.free_vars.each do |name, type|
idx = generic_class.type_vars.index(name)
if idx
type_vars[idx] = Path.new([name])
end
end
if type_vars.all?
not_nil_type_vars = Array(ASTNode).new(generic_class.type_vars.length)
type_vars.each do |type_var|
not_nil_type_vars.push type_var.not_nil!
end
instance_type = scope.instance_type
instance_type = instance_type.generic_class if instance_type.is_a?(GenericClassInstanceType)
new_generic = NewGenericClass.new(Path.new([generic_class.name] of String), not_nil_type_vars)
alloc = Call.new(new_generic, "allocate")
else
alloc = Call.new(nil, "allocate")
ms = matches.map do |match|
if instance_type.is_a?(GenericClassType)
generic_type_args = Array(ASTNode).new(instance_type.type_vars.length)
instance_type.type_vars.each do |type_var|
generic_type_args << Path.new([type_var])
end
new_generic = NewGenericClass.new(Path.new([instance_type.name]), generic_type_args)
alloc = Call.new(new_generic, "allocate")
else
alloc = Call.new(nil, "allocate")
end
# This creates:
#
# x = allocate
# GC.add_finalizer x
# x.initialize ...
# x
var = Var.new("x")
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment