🌟

[Feature #21359] Exception#cause の値を Exception#cause= で制御できるようにする提案

に公開

[Feature #21359] Introduce Exception#cause= for Post-Initialization Assignment

begin
  begin
    raise "inner"
  rescue
    raise "outer"
  end
rescue => e
  p e       # => #<RuntimeError: outer>
  p e.cause # => #<RuntimeError: inner>
end
  • この causeraise の引数として制御することもできる
begin
  # ここで設定した例外が Exception#cause から参照できる
  raise "outer", cause: RuntimeError.new("inner")
rescue => e
  p e       # => #<RuntimeError: outer>
  p e.cause # => #<RuntimeError: inner>
end
  • この #cause の値を Exception#cause= で制御できるようにする提案
cause = RuntimeError.new("low-level error")
error = StandardError.new("higher-level error")
error.cause = cause
  • 明示的に cause を指定したケースってどういうときなんですかね?ライブラリの内部とかで使われたりするのかな
  • 以下のような実装イメージも書かれていますねー
    • 逆にこれを使えば現状でも同様の機能は実装できるんですねーはえ〜
error = StandardError.new("error")
cause = RuntimeError.new("cause")

class Exception
  def cause= value
    backtrace = self.backtrace_locations

    raise self, cause: value
  rescue Exception
    self.set_backtrace(backtrace)
  end
end

p error.cause # nil
error.cause = cause
p error.cause # => #<RuntimeError: cause>
GitHubで編集を提案

Discussion