Skip to content

Commit

Permalink
Showing 7 changed files with 110 additions and 8 deletions.
38 changes: 37 additions & 1 deletion spec/compiler/codegen/class_spec.cr
Original file line number Diff line number Diff line change
@@ -654,7 +654,7 @@ describe "Code gen: class" do
it "doesn't crash on instance variable assigned a proc, and never instantiated (#923)" do
codegen(%(
class Klass
def f(arg)
def self.f(arg)
end
@a : Proc(String, Nil) = ->f(String)
@@ -1039,4 +1039,40 @@ describe "Code gen: class" do
foo.x
), inject_primitives: false).to_i.should eq(1)
end

it "runs instance variable initializer at the class level" do
run(%(
class Foo
@x : Int32 = bar
def self.bar
42
end
def x
@x
end
end
Foo.new.x
)).to_i.should eq(42)
end

it "runs instance variable initializer at the class level, for generic type" do
run(%(
class Foo(T)
@x : T = bar
def self.bar
42
end
def x
@x
end
end
Foo(Int32).new.x
)).to_i.should eq(42)
end
end
2 changes: 1 addition & 1 deletion spec/compiler/codegen/proc_spec.cr
Original file line number Diff line number Diff line change
@@ -724,7 +724,7 @@ describe "Code gen: proc" do
class Foo
@f : -> Int32 = ->foo
def foo
def self.foo
42
end
2 changes: 1 addition & 1 deletion spec/compiler/semantic/class_spec.cr
Original file line number Diff line number Diff line change
@@ -822,7 +822,7 @@ describe "Semantic: class" do
it "doesn't crash on instance variable assigned a proc, and never instantiated (#923)" do
assert_type(%(
class Klass
def f(arg)
def self.f(arg)
end
@a : Proc(String, Nil) = ->f(String)
67 changes: 67 additions & 0 deletions spec/compiler/semantic/instance_var_spec.cr
Original file line number Diff line number Diff line change
@@ -5066,4 +5066,71 @@ describe "Semantic: instance var" do
Second.new.hash
)) { hash_of(hash_of(int32, int32).virtual_type, int32).virtual_type }
end

it "doesn't solve instance var initializer in instance context (1) (#5876)" do
assert_error %(
class Foo
@x : Int32 = bar
def bar
1
end
end
Foo.new
),
"undefined local variable or method 'bar'"
end

it "doesn't solve instance var initializer in instance context (2) (#5876)" do
assert_error %(
class Foo(T)
@x : T = bar
def bar
1
end
end
Foo(Int32).new
),
"undefined local variable or method 'bar'"
end

it "doesn't solve instance var initializer in instance context (3) (#5876)" do
assert_error %(
module Moo(T)
@x : T = bar
def bar
1
end
end
class Foo
include Moo(Int32)
end
Foo.new
),
"undefined local variable or method 'bar'"
end

it "solves instance var initializer in metaclass context (#5876)" do
assert_type(%(
class Foo
@x : Int32 = bar
def self.bar
1
end
def x
@x
end
end
Foo.new.x
)) { int32 }
end
end
3 changes: 1 addition & 2 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
@@ -1833,9 +1833,8 @@ module Crystal
with_cloned_context do
# Instance var initializers must run with "self"
# properly set up to the type being allocated
context.type = real_type
context.type = real_type.metaclass
context.vars = LLVMVars.new
context.vars["self"] = LLVMVar.new(type_ptr, real_type)
alloca_vars init.meta_vars

accept init.value
Original file line number Diff line number Diff line change
@@ -103,7 +103,7 @@ class Crystal::InstanceVarsInitializerVisitor < Crystal::SemanticVisitor
end

ivar_visitor = MainVisitor.new(program, meta_vars: i.meta_vars)
ivar_visitor.scope = scope
ivar_visitor.scope = scope.metaclass
value.accept ivar_visitor
end
end
4 changes: 2 additions & 2 deletions src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
@@ -992,7 +992,7 @@ module Crystal
if !meta_vars && !self.is_a?(GenericType)
meta_vars = MetaVars.new
visitor = MainVisitor.new(program, vars: meta_vars, meta_vars: meta_vars)
visitor.scope = self
visitor.scope = self.metaclass
value = value.clone
value.accept visitor
end
@@ -1507,7 +1507,7 @@ module Crystal
def run_instance_var_initializer(initializer, instance : GenericClassInstanceType | NonGenericClassType)
meta_vars = MetaVars.new
visitor = MainVisitor.new(program, vars: meta_vars, meta_vars: meta_vars)
visitor.scope = instance
visitor.scope = instance.metaclass
value = initializer.value.clone
value.accept visitor
instance_var = instance.lookup_instance_var(initializer.name)

0 comments on commit 3de4c52

Please sign in to comment.