📌

【Ruby 4.0 Advent Calender】Fiber#raiseとThread#raiseでcause:が追加された【6日目】

に公開

Ruby 4.0 Advent Calender 6日目の記事です。

これはなに

今年 2025年12月25日にリリースされる予定の Ruby 4.0 の新機能や変更点などを1つずつ紹介していく Advent Calender になります。
基本的には NEWS に載っている機能を紹介すると思うんですがここにない機能についても書くかもしれません。
また、記事を書いてる時点ではまだ Ruby 4.0 はリリースされる前なので Ruby 4.0 がリリースされた時点で機能が変わっている 可能性があるかもしれないので注意してください。
記事のまとめは ここを参照 してください。

Fiber#raiseThread#raisecause: 引数がサポートされた

Ruby では例外が発生したときに rescue 節でネストして例外が発生した場合に Exception#cause で元の例外の情報を取得することができます。

begin
  begin
    # 最初にここで例外が発生する
    1 / 0
  rescue
    # 最初に発生した例外を rescue 節で受け取った後に更にそのあとに例外が発生する
    hoge
  end
rescue => e
  # ここの例外は2回目の例外を取得する
  pp e
  # => #<NameError: undefined local variable or method 'hoge' for main>

  # 最初の例外は Exception#cause で取得する
  pp e.cause
  # => #<ZeroDivisionError: divided by 0>
end

この #cause の値は Kernel#raisecause: で渡すこともできます。

cause = RuntimeError.new("cause")

begin
  # cause でよりネストした例外の情報を渡すことができる
  raise RuntimeError, "boom", cause: cause
rescue => e
  pp e
  # => #<RuntimeError: boom>

  pp e.cause
  # => #<RuntimeError: cause>
end

この cause: なのですが同じような例外を発生させる Fiber#raiseThread#raise では cause: を渡すことができていませんでした。

cause = RuntimeError.new("cause")

begin
  # cause: を渡すとキーワード引数ではなくてバックトレースを渡そうと解釈されエラーになる
  Fiber.current.raise RuntimeError, "boom", cause: cause
rescue => e
  p e
  # => #<TypeError: backtrace must be an Array of String or an Array of Thread::Backtrace::Location>
end

Ruby 4.0 では Fiber#raiseThread#raise にも cause: を渡すことができるようになりました。

cause = RuntimeError.new("cause")

begin
  # cause: を渡すとキーワード引数ではなくてバックトレースを渡そうと解釈されエラーになる
  Fiber.current.raise RuntimeError, "boom", cause: cause
rescue => e
  p e
  # Ruby 3.4 => #<TypeError: backtrace must be an Array of String or an Array of Thread::Backtrace::Location>
  # Ruby 4.0 => #<RuntimeError: boom>

  p e.cause
  # Ruby 3.4 => nil
  # Ruby 4.0 => #<RuntimeError: cause>
end

関連

GitHubで編集を提案

Discussion