Confusing error output `instance variable @x of A was inferred to be Nil`

Following is code:

class A
  def initialize(x)
    @x : Int32? = x
  end
end

a = A.new(100)
In 1.cr:3:5

 3 | @x : Int32? = x
     ^-
Error: declaring the type of an instance variable must be done at the class level

Okay, the output is expected. i delcar the type of @x wrong way.

Then, i change to this:

class A
  def initialize(x)
    @x : Int32? = x || nil
  end
end

a = A.new(100)
In 1.cr:3:5

 3 | @x : Int32? = x || nil
     ^
Error: instance variable @x of A was inferred to be Nil, but Nil alone provides no information

Above error message start to wired.

Questions:

  1. Should we output the previous (obviously) error output at first?
  2. Why @x inferred to Nil?

thanks

I think this is a compiler bug. The error message that instance variable declaration must be in class scope should take precedence in this case.

1 Like

Okay, i create a issue and reference back here for the first issue.

but, there have another question, why @x in following code inferred to Nil?

class A
  def initialize(x)
    @x = x || nil
  end
end

a = A.new(100)

x must be provided, i pass 100 to A.new, so x should be a Int32, @x should be a Int32 too, right?

Because when the compiler sees:

@var = some_expression

the compiler will try to infer the type from some_expression. In this case it’s this:

x || nil

Can we infer something from x? Let’s look if it has a type restriction. Nope, it doesn’t have any. Can we infer something from nil? Yes! It’s nil so it must be of type Nil. Well, Nil or something else (x) that we don’t know the type of. So the end result is that we can only infer it to be Nil.

It doesn’t matter what you pass to the constructor. The compiler doesn’t look at calls to infer the type of instance vars: just what you assign to @x inside the constructor (or, well, any other method, but never calls to methods.)

4 Likes

At this point I wouldn’t mind having to specify the type of instance variables explicitly. It doesn’t take much time and it would solve a lot of these issues/discussions. And it might make the code clearer. I hope maybe for Crystal 2.0…

7 Likes

What an impressive answer! thanks

At this point I wouldn’t mind having to specify the type of instance variables explicitly. It doesn’t take much time and it would solve a lot of these issues/discussions. And it might make the code clearer. I hope maybe for Crystal 2.0…

Indeed, I fell upon this error with:

@description : String? = nil

There is no other @description manipulation in the class because I’m doing TDD, so it is completely normal that the code is not complete yet. When I declare the type explicitly I’m waiting for the compiler to just swallow it and don’t complain about.

EDIT : okay, nevermind, declaring the type at the class level does the trick