Crystal: Compiler incorrect detect use of self when it's used as receiver in a simple method call.

Created on 27 Apr 2020  路  3Comments  路  Source: crystal-lang/crystal

If we explicit use self to call methods in the constructor from our own class the compiler believes we are passing self around and make all instance variables nilable. This would be ok if we didn't have the choice of hide the self. from the call and make the program behave differently.

class A
  def initialize
    self.foo
    @bar = 23 # Will be (Int32 | Nil) but self was used just to call
  end

  def foo
    42
  end
end

If this is intentional it's weird, Crystal hide the self because it isn't Python :-).

And will be harder to explain someone that the code bellow behaves differently from the one above.

class A
  def initialize
    foo
    @bar = 23 # @bar is Int32.
  end

  def foo
    42
  end
end

P.S.: I triggered this on the following use case: I needed to use the self. just to disambiguate a variable name from a existing method.

Tested with Crystal 0.34 on Archlinux.

bug topicsemantic lang

Most helpful comment

I'll leave this open. I guess it should be consistently erroring or working.

All 3 comments

For simplicity, whenever you use self the compiler will consider every subsequent instance var as nilable. Changing this is pretty hard. You can move 42 to a constant.

I would imagine this is far from trivial to fix. And this 42 was there just as a dummy example.

But IMO this still a bug since we have the same code, different only by making a implicit variable explicit, with different behavior.

My first suggestion (not thinking about all possible side effects) would be to just avoid this check if self is used as a receiver in a method call, since such code can be written without the word "self" and the current compiler allows it.

I'll leave this open. I guess it should be consistently erroring or working.

Was this page helpful?
0 / 5 - 0 ratings