🙄

[Feature #21279] NameErrorやNoMethodErrorをrescueでキャッチしないようにするチケット

に公開

[Feature #21279] Bare "rescue" should not rescue NameError

  • NameErrorNoMethodErrorrescue でキャッチすべきではない、という内容のチケット
  • 例えば次のような NameError が発生すると rescue で例外をキャッチすることができます
    • これは NameErrorStandardError を継承しており rescue ではクラスが指定されなかった場合は StandardError を継承しているクラスをキャッチするような挙動になっているため
    • また NomenclatureNameError のサブクラス
begin
  DoesNotExist
rescue => e
  p e # => #<NameError: uninitialized constant DoesNotExist>
end
  • NameErrorNoMethodError は通常タイプミスなどで発生し、実行時には回復することができないので SyntaxError と同様のエラーにするべき、みたいなのがモチベーションみたいですね
  • 対応としては NameError の親クラスを StandardError にしない、みたいな対応を想定しているみたいです
  • チケットのコメントでは歴史的な話が書かれているんですが Ruby 1.6 〜 1.8 ではもともと NameErrorException のサブクラスだったんですがそのあとに StandardError に移動した背景があるみたいです
  • これ、言いたいことはわからなくもないんですが NameError が発生するのは実行時になるので『エラーが発生してもとりあえずプログラムは止まってほしくない』みたいな場合にはカバーできない気がするんですよねえ
    • あと互換性的に NameError / NoMethodError を考慮してない rescue がほとんどだと思うので既存のコードはかなり壊れそう…
  • 最終的には歴史的な制約や互換性を考えて、現状のまま維持することになりました
  • ここら辺、ユーザ側で制御できるとよい気もするんですが継承リストをあとから変更することはできないのでなかなかむずかしそうですねえ
GitHubで編集を提案

Discussion