2022/04/29 今回の気になった bugs.ruby のチケット

今週は右代入を TracePoint でフックする場合のバグ報告がありました。

[Bug #18753] lineno= is not returning an integer

  • ARGF.send(:lineno=, 1) の戻り値が nil になっているというバグ報告
# これは 1 を返す
p (ARGF.lineno=1)
# => 1

# これは nil を返す
p ARGF.send(:lineno=, 1)
# => nil
  • この問題は最新版では修正済み

[Bug #18752] defined? String.instance_method(:abcdefg) will return a "method" string instead nil.

  • defined? String.instance_method(:abcdefg) した時に nil を返すことを期待するが "method" が返るというバグ報告
p defined? String.instance_method(:abcdefg)
# => nil

p defined? String.instance_method(:abcdefg111111111111)
# => nil
  • これは defined?String.instance_method の呼び出しに対してチェックしているので期待する挙動になる
  • 逆に定義されてないメソッドを呼び出そうとすると nil を返す
p defined? String.abcdefg111111111111
# => nil

[Bug #18629] block args array splatting assigns to higher scope _ var

  • 以下のように仮引数が _ でない場合はスコープの外の変数は書き換わらないが _ の場合は外のスコープの変数が書き換わってしまうというバグ報告
# これは書き換わらない
v = 1; [[2]].each{ |(v)| }; p v   # => 1

# これは書き換わってしまう
_ = 1; [[2]].each{ |(_)| }; p _   # => 2
  • これは最新版で修正済み

Bug #18740 Use of rightward assignment changes line number needed for line-targeted TracePoint(https://bugs.ruby-lang.org/issues/18740)

  • 次のように右代入を使用している際に TracePoint でフックできないというバグ報告
def foo
  (1..)
      .lazy
      .filter { _1.even? }
      .take(10)
      .to_a => result

  puts result
end

# foo メソッドの 2行目の式に対して TracePoint をフックする
# error: `enable': can not enable any hooks (ArgumentError)
TracePoint.new(:line) { puts 'Hi' }.enable(target: RubyVM::InstructionSequence.of(method :foo), target_line: 2)
foo
  • 右代入ではなくて左代入だと問題なく動作する
def foo
  result = (1..)
      .lazy
      .filter { _1.even? }
      .take(10)
      .to_a

  puts result
end

# foo メソッドの 2行目の式に対して TracePoint をフックする
# OK
TracePoint.new(:line) { puts 'Hi' }.enable(target: RubyVM::InstructionSequence.of(method :foo), target_line: 2)
foo
def foo
  (1..)
      .lazy
      .filter { _1.even? }
      .take(10)
      .to_a => result   # <- この行数を指定すると OK

  puts result
end

# foo メソッドの 2行目の式に対して TracePoint をフックする
# OK
TracePoint.new(:line) { puts 'Hi' }.enable(target: RubyVM::InstructionSequence.of(method :foo), target_line: 6)
foo
  • 知らなかったので知見
  • これがバグなのか仕様なのかは現時点では未定義ぽい