Crystal: Compiler error when using ||= in #initialize

Created on 10 Feb 2017  路  6Comments  路  Source: crystal-lang/crystal

Provided sample shows the problem:

class Foo
  def initialize
    @bar ||= true
  end
end

Foo.new

Above fails with:

Error in line 7: instantiating 'Foo:Class#new()'

instance variable '@bar' of Foo must be Bool, not Nil

Error: instance variable '@bar' was used before it was initialized in one of the 'initialize' methods, rendering it nilable

See https://carc.in/#/r/1me0

question discussion compiler

Most helpful comment

Whenever I see such code in Ruby I think "But... why?". An initializer initializes an object. There's no previous state for the object. So it doesn't make sense to do ||= there. So basically this is equivalent, and simpler:

class Foo
  def initialize
    @bar = true
  end
end

Foo.new

So here the compiler is forcing you to have simpler code. I think that's something good.

@Sija Unless there's a really strong reason you need this, I'd say to close this issue.

All 6 comments

Isn't this the expected behaviour? It expands to @bar = @bar || true, and since @bar is not initialized it doesn't work.

Technically it's correct, although Ruby for instance treats it just as nil and invokes the _else_ branch which is more intuitive to me as well.

Crystal evaluate the type of instance variable from initializer (both initialize method and catch-all initialization )

So when Crystal saw your code above, it considered @bar as Bool from @bar ||= true.
(that will be treat as@bar = @bar || true and the only known type in the right side is true : Bool)

You can do this now for nilable instance variable:

class Foo
  @bar : Bool?

  def initialize
    @bar ||= true
  end
end

Foo.new

Whenever I see such code in Ruby I think "But... why?". An initializer initializes an object. There's no previous state for the object. So it doesn't make sense to do ||= there. So basically this is equivalent, and simpler:

class Foo
  def initialize
    @bar = true
  end
end

Foo.new

So here the compiler is forcing you to have simpler code. I think that's something good.

@Sija Unless there's a really strong reason you need this, I'd say to close this issue.

I'll close this. Please reopen if you need to.

I agree, thanks for review!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benoist picture benoist  路  59Comments

akzhan picture akzhan  路  67Comments

farleyknight picture farleyknight  路  64Comments

straight-shoota picture straight-shoota  路  91Comments

rdp picture rdp  路  112Comments