👻

【bugs.ruby Advent Calender】警告が無効な場合に Warning.warn が呼び出されなくなる【13日目】

2024/12/13に公開

bugs.ruby Advent Calender 13日目の記事です。

これはなに

今年1年間通してみてきた bugs.ruby のチケットの中から気になったものを1つずつ取り上げていく Advent Calender です。
取り上げるチケットは基本的にこのブログで取り上げたものになります。
記事のまとめは ここを参照 してください。

[Bug #20573] Warning.warn shouldn't be called for disabled warnings

例えば以下のような Ruby のコードを -W 付きで実行すると警告が出力されます。

def get_var
  # warning: variable $= is no longer effective
  $=
end

get_var

この警告は deprecated をカテゴリとして出力されるんですがこのときに Warning#[]= でカテゴリごとに警告が出ないように制御することができます。

# deprecated な警告は出力されないように制御できる
Warning[:deprecated] = false


def get_var
  # warning: variable $= is no longer effective
  $=
end

get_var

この挙動を踏まえた上で Warning.warn を説明するんですが Warning.warn は内部で警告を出力する際に呼ばれるメソッドになります。
このメソッドを書き換えることで警告の内容を変えたりすることができます。

module Warning
  # 警告が出力される際にこのメソッドが呼び出される
  def self.warn(message, category:)
    pp category => message
  end
end

def get_var
  $=
end

get_var
__END__
output:
{:deprecated=>"/tmp/vofzcA0/16:8: warning: variable $= is no longer effective\n"}

このチケットは Warning.warnWarning[:deprecated] = false のときに呼び出されないようにするチケットになっています。
このメソッドを呼び出さないようにすることでパフォーマンスが向上するみたいですね。

このチケットではその変更が受け入れられて Warning#[]false が設定されている警告のカテゴリは Ruby 3.4 からは内部で Warning.warn が呼びされなくなりました。

module Warning
  def self.warn(message, category:)
    pp category => message
  end
end

def get_var
  $=
end

# deprecated の警告が無効な場合は deprecated の Warning#warn は呼び出されない
pp Warning[:deprecated]   # => false
get_var
# Ruby 3.3 => output: {:deprecated=>"/tmp/vlhK9hI/25:8: warning: variable $= is no longer effective\n"}
# Ruby 3.4 => output: なし

# deprecated の警告が有効な場合は deprecated の Warning#warn が呼び出される
Warning[:deprecated] = true
pp Warning[:deprecated]   # => true
get_var
# Ruby 3.3 => output: {:deprecated=>"/tmp/vlhK9hI/25:8: warning: variable $= is no longer effective\n"}
# Ruby 3.4 => output: {:deprecated=>"/tmp/vlhK9hI/25:8: warning: variable $= is no longer effective\n"}

それはそうと思いつつ一応非互換な変更になるのでご注意ください。

関連

GitHubで編集を提案

Discussion