Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

super inside initialize #4764

Closed
petoem opened this issue Jul 31, 2017 · 2 comments
Closed

super inside initialize #4764

petoem opened this issue Jul 31, 2017 · 2 comments

Comments

@petoem
Copy link
Contributor

petoem commented Jul 31, 2017

In #4762 @RX14 said its possible to use super from the child constructor.
Using the same example code as in the other issue, but adding a constructor that only calls super doesn't work.
https://play.crystal-lang.org/#/r/2gb3

class Parent
  property a : Int32

  def initialize(@a)
  end

  def initialize
    @a = 1
  end
end

class Child < Parent
  def initialize
    super
  end
  def initialize(a)
    @a = a
  end
end

puts Child.new.a

Outputs:

Error in line 13: this 'initialize' doesn't initialize instance variable '@a' of Parent, with Child < Parent, rendering it nilable

But the fun part starts now. If I remove the second constructor from the class Child it magically works.
https://play.crystal-lang.org/#/r/2gb4

class Parent
  property a : Int32

  def initialize(@a)
  end

  def initialize
    @a = 1
  end
end

class Child < Parent
  def initialize
    super
  end
end

puts Child.new.a

Now crystal detects that the Child classes initialize method calls super which calls Parent classes initialize method that initializes instance variable @a of Parent.

@faustinoaq
Copy link
Contributor

If you use super(a) instead of initialize(@a) the code works:

class Parent
  property a : Int32

  def initialize(@a)
  end

  def initialize
    @a = 1
  end
end

class Child < Parent
  def initialize
    super
  end
  def initialize(a)
    super(a)
  end
end

puts Child.new.a # => 1

Minimal code with this issue:

class A
  def initialize(@a = 1)
  end
end

class B < A
  def initialize
    super
  end
  def initialize(@a)
  end
end

B.new

Outputs:

Error in line 7: this 'initialize' doesn't initialize instance variable '@a' of A, with B < A, rendering it nilable

@RX14
Copy link
Contributor

RX14 commented Jul 31, 2017

This looks like a genuine bug to me. super calls should count for variable initialization, and i can't see a way which this could be abused to break initialization.

maxfierke added a commit to maxfierke/crystal that referenced this issue Aug 20, 2017
If initialize calls super and declares instance var that has already
been typed as non-nilable by an ancestor, it'll be non-nilable in the
child class.

Fixes crystal-lang#4764
RX14 pushed a commit that referenced this issue Aug 31, 2017
If initialize calls super and declares instance var that has already
been typed as non-nilable by an ancestor, it'll be non-nilable in the
child class.

Fixes #4764
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants