🚀

[Bug #20505] ブロック引数の値を書き換えたあとに super を呼び出したときのバグ報告

2024/06/23に公開

[Bug #20505] Reassigning the block argument in method body keeps old block when calling super with implicit arguments

  • 次のように super を呼び出す前にブロック引数の値を変えたときに意図しない挙動になるバグ報告
class A
  def positional_arg(a)
    puts a
  end

  def block_arg(&block)
    yield
  end
end

class B < A
  def positional_arg(a = nil)
    a = 'b'
    # これは親メソッドに書き換えた a の値が渡される
    super
  end

  def block_arg(&block)
    block = proc { puts 'b' }
    # このときに書き換えた block の値が親メソッドに渡されない
    super
  end
end

B.new.positional_arg('a')      # => b
B.new.positional_arg           # => b
B.new.block_arg { puts 'a' }   # => a
B.new.block_arg                # => error: no block given (yield) (LocalJumpError)
  • これ自体は『現状そういう挙動になっています』以上の話ではないみたいですね
    • super 自体がかなり特殊な動きになっている
  • 同様に super() も『ブロック引数を委譲する』という挙動になります
class A
  def foo
    yield
  end
end

class B < A
  def foo
    # 親メソッドにブロック引数が委譲される
    super()
  end
end

B.new.foo { puts "Hello" } #=> Hello
  • そういえば Ruby やりはじめたときに super でいろいろとハマった記憶を思い出した
GitHubで編集を提案

Discussion