🍣

[Feature #20275] 例外が発生したときのバックトレースを改善するチケット

2024/03/29に公開

[Feature #20275] Avoid extra backtrace entries for rescue and ensure

  • 以下のようなコードを実行すると
def raise_nested_exceptions
  raise "First error"
rescue
  begin
    raise "Second error"
  rescue
    raise "Third error"
  end
end

raise_nested_exceptions
  • 以下のようなエラーが出力される
-:7:in 'Object#raise_nested_exceptions': Third error (RuntimeError)
	from -:4:in 'Object#raise_nested_exceptions'
	from -:1:in 'Object#raise_nested_exceptions'
	from -:11:in '<main>'
-:5:in 'Object#raise_nested_exceptions': Second error (RuntimeError)
	from -:1:in 'Object#raise_nested_exceptions'
	from -:11:in '<main>'
-:2:in 'Object#raise_nested_exceptions': First error (RuntimeError)
	from -:11:in '<main>'
  • このときにバックトレースが繰り返し表示される
    • これは CRuby の実装依存らしい
  • この繰り返しをやめて以下の様に表示する提案
-:7:in 'Object#raise_nested_exceptions': Third error (RuntimeError)
	from -:11:in '<main>'
-:5:in 'Object#raise_nested_exceptions': Second error (RuntimeError)
	from -:11:in '<main>'
-:2:in 'Object#raise_nested_exceptions': First error (RuntimeError)
	from -:11:in '<main>'
  • TruffleRuby と JRuby は既にこのような動作になっているらしい
    • TruffleRuby 23.1.2:
      -:7:in `raise_nested_exceptions': Third error (RuntimeError)
          from -:11:in `<main>'
      -:5:in `raise_nested_exceptions': Second error (RuntimeError)
          from -:11:in `<main>'
      -:2:in `raise_nested_exceptions': First error (RuntimeError)
          from -:11:in `<main>'
      
    • JRuby 9.4.5.0:
      RuntimeError: Third error
        raise_nested_exceptions at -:7
                         <main> at -:11
      RuntimeError: Second error
        raise_nested_exceptions at -:5
                         <main> at -:11
      RuntimeError: First error
        raise_nested_exceptions at -:2
                         <main> at -:11
      
  • これは既に開発版の Ruby 3.4 で対応されています
  • また、この変更に伴い caller の戻り値なども調整されているみたいですね
def raise_nested_exceptions
  raise "First error"
rescue
  begin
    raise "Second error"
  rescue
    # caller の数も減る
    p caller
    # Ruby 3.3 => ["test.rb:12:in `rescue in raise_nested_exceptions'", "test.rb:9:in `raise_nested_exceptions'", "test.rb:22:in `<main>'"]
    # Ruby 3.4 => ["test.rb:12:in 'Object#raise_nested_exceptions'", "test.rb:20:in '<main>'"]
  end
end

raise_nested_exceptions
GitHubで編集を提案

Discussion