E0092

E0092#

警告名:fragile_catch_all

catch-all ハンドラーがクリーンアップを行ってから同じエラーを再送出しています。このパターンは堅牢ではありません。将来、catch-all ハンドラーは非同期キャンセルを捕捉しなくなりますが、処理がキャンセルされた場合にもクリーンアップは必要です。

誤った例#

///|
fn operation_that_may_fail() -> Unit raise {
  fail("operation failed")
}

///|
pub fn run() -> Unit raise {
  try operation_that_may_fail() catch {
    error => {
      println("cleanup")
      raise error
    }
  }
}

このハンドラーはエラーから回復したりエラーを変換したりせず、伝播する前にクリーンアップを行うだけです。

修正案#

catch-all ハンドラーを errdefer に置き換えます。後続の body がエラーで終了するたびにクリーンアップが実行され、元のエラーは自動的に伝播します。

///|
fn operation_that_may_fail() -> Unit raise {
  fail("operation failed")
}

///|
pub fn run() -> Unit raise {
  errdefer println("cleanup")
  operation_that_may_fail()
}

ハンドラーでエラーを調べる必要がある場合、そのロジックは catch に残し、独立したクリーンアップを errdefer に移します。