2021/05/30 今週の気になった bugs.ruby のチケット

今週は prepend した際の定数探索のバグ報告がありました。

[Bug #17887] Missed constant lookup after prepend

  • 次のように prepend したときの定数の探索がおかしいというバグ報告
class A
  FOO = 'a'
end

class B < A
  def foo
    FOO
  end
end

b = B.new

# スーパークラスの FOO を参照するのでこれは正しい
p b.foo
# => "a"

module M
  FOO = 'm'
end
A.prepend M

# A に prepend すると B の継承リストはこうなる
p B.ancestors
# => [B, M, A, Object, Kernel, BasicObject]

# A よりも M が前にあるので M::FOO を参照してほしいが実際には A::FOO を参照している
p b.foo
# 期待する挙動 => "m"
# 実際の挙動   => "a"
  • ちなみに B.include M をすると期待する動作をする
class A
  FOO = 'a'
end

class B < A
  def foo
    FOO
  end
end

b = B.new

module M
  FOO = 'm'
end
B.include M

# A.prepend M と同じ継承リスト
p B.ancestors
# => [B, M, A, Object, Kernel, BasicObject]

# これは期待する挙動になる
p b.foo
# => "m"

[Feature #12913] A way to configure the default maximum width of pp

  • pp で表示幅を指定する時に PP.default_maxwidth みたいなグローバル値で設定できるようにする提案
require "pp"

# 現状幅を指定する場合は第三引数に幅数を渡す必要がある
# NOTE: チケットで提示されていたのは pp だけど現状は動かなくなってるぽい
PP.pp([1, 2, 3], $>, 1)
# => [1,
#     2,
#     3]
  • グローバル値だと意図しない箇所にまで範囲にまで影響を受けてしまうので危険だとコメントされている
  • 現在は PP.ppKernel#ppwidth: キーワード引数を受け取るような形で提案がされている
pp([1, 2, 3], width: 1)
  • ただし、この実装だと現在の挙動と非互換になる
# 現状は Hash として出力される
pp([1, 2, 3], width: 1)
# => [1, 2, 3]
#    {:width=>1}