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 に移します。