Skip to content

Commit

Permalink
Fixed #2059: regression with class variables not being correctly typed
Browse files Browse the repository at this point in the history
  • Loading branch information
Ary Borenszweig committed Jan 24, 2016
1 parent 1e6f385 commit eee3eff
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
13 changes: 13 additions & 0 deletions spec/compiler/type_inference/class_var_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,17 @@ describe "Type inference: class var" do
),
"can't use class variable with generic types, only with generic types instances"
end

it "types class var as nil if assigned for the first time inside method (#2059)" do
assert_type("
class Foo
def self.foo
@@foo = 1
@@foo
end
end
Foo.foo
") { nilable int32 }
end
end
2 changes: 1 addition & 1 deletion spec/compiler/type_inference/type_declaration_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ describe "Type inference: type declaration" do
Foo.x = true
),
"type must be Int32, not Bool"
"type must be Int32, not Nil"
end

it "declares class variable (2)" do
Expand Down
13 changes: 9 additions & 4 deletions src/compiler/crystal/semantic/type_visitor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,11 @@ module Crystal
var = mod.global_vars[target.name]?
unless var
var = Var.new(target.name)
if @typed_def
var.bind_to mod.nil_var
end

# If we are assigning to a global inside a method, make it nilable
# if this is the first time we are assigning to it, because
# the method might be called conditionally
var.bind_to mod.nil_var if @typed_def
mod.global_vars[target.name] = var
end
var.add_attributes(target.attributes)
Expand All @@ -555,7 +557,10 @@ module Crystal
end

def type_assign(target : ClassVar, value, node)
var = lookup_class_var target, bind_to_nil_if_non_existent: false
# If we are assigning to a class variable inside a method, make it nilable
# if this is the first time we are assigning to it, because
# the method might be called conditionally
var = lookup_class_var target, bind_to_nil_if_non_existent: !!@typed_def
check_valid_attributes var, ValidClassVarAttributes, "class variable"

value.accept self
Expand Down

0 comments on commit eee3eff

Please sign in to comment.