Skip to content

Commit

Permalink
Showing 3 changed files with 28 additions and 18 deletions.
19 changes: 19 additions & 0 deletions spec/compiler/type_inference/class_var_spec.cr
Original file line number Diff line number Diff line change
@@ -459,4 +459,23 @@ describe "Type inference: class var" do
Bar.x.y
)) { int32 }
end

it "doesn't error on recursive depdendency if var is nilable (#2943)" do
assert_type(%(
class Foo
@@foo : Int32?
@@foo = Foo.bar
def self.bar
@@foo
end
def self.foo
@@foo
end
end
Foo.foo
)) { nilable int32 }
end
end
16 changes: 0 additions & 16 deletions spec/compiler/type_inference/const_spec.cr
Original file line number Diff line number Diff line change
@@ -269,22 +269,6 @@ describe "Type inference: const" do
"recursive dependency of constant B: B -> A -> B"
end

it "errors if recursive constant definition with class var" do
assert_error %(
def foo(x)
end
foo Foo::B
class Foo
@@a : Int32?
B = @@a
@@a = 1 + (B ? 0 : 2)
end
),
"recursive dependency of class var Foo::@@a: Foo::@@a -> Foo::B -> Foo::@@a"
end

it "can use constant defined later (#2906)" do
assert_type(%(
FOO = Foo.new
11 changes: 9 additions & 2 deletions src/compiler/crystal/semantic/class_vars_initializer_visitor.cr
Original file line number Diff line number Diff line change
@@ -67,9 +67,16 @@ module Crystal
had_class_var = false
end

self.class_var_and_const_being_typed.push class_var unless class_var.uninitialized
check_recursiveness = true
if class_var.uninitialized
check_recursiveness = false
elsif class_var.type?.try &.includes_type?(nil_type)
check_recursiveness = false
end

self.class_var_and_const_being_typed.push class_var if check_recursiveness
node.accept main_visitor
self.class_var_and_const_being_typed.pop unless class_var.uninitialized
self.class_var_and_const_being_typed.pop if check_recursiveness

unless had_class_var
main_visitor.undefined_class_variable(class_var, owner)

0 comments on commit a4df5f2

Please sign in to comment.