# Some thoughts on a less slippery catch\_unwind

**URL:** <https://internals.rust-lang.org/t/some-thoughts-on-a-less-slippery-catch-unwind/16902>\
**Category:** libs\
**Created:** [June 27, 2022, 12:36am UTC](https://internals.rust-lang.org/t/some-thoughts-on-a-less-slippery-catch-unwind/16902 "2022-06-27T00:36:30Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![LegionMammal978](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/legionmammal978/32/8985_2.png) [@LegionMammal978](https://internals.rust-lang.org/u/LegionMammal978)\
**Post date:** [July 16, 2022, 3:17pm UTC](https://internals.rust-lang.org/t/some-thoughts-on-a-less-slippery-catch-unwind/16902/4 "2022-07-16T15:17:09Z")

</div>

It's been a few weeks, but I've finished my survey of how crates currently use `catch_unwind()` in practice. To summarize:

## Clean handling methods

26 crates:

1. Move the payload into a provided field, pointer, global variable, or thread-local variable.
2. Optionally, set some flag to inform the caller that a panic occurred.
3. Later, on the caller's side of the boundary, take the payload and `resume_unwind`.

22 crates:

1. If a panic occurred, optionally log a message, then `abort` or `exit` the process (or equivalent).

19 crates:

1. Do some additional processing or cleaning up, then `resume_unwind`.

6 crates:

1. Optionally do some additional processing.
2. Directly return the `thread::Result` (or equivalent) to the user.

3 crates:

1. Create a panic-on-drop guard before the payload is processed.
2. Only `forget` the guard after the payload has been dropped.

2 crates:

1. If a panic occurred, independently panic again, resulting in an abort if the payload panics.

## Leaky handling methods\*

69 crates (at least 24 unsound):

1. Produce a value, set some flags, or call some functions based on whether or not a panic occurred.
2. Optionally, use `downcast` or `downcast_ref` on the payload to extract the panic message, and either log it or embed it in a value.
3. Return and implicitly drop the payload.

13 crates (at least 5 unsound):

1. Use `let _ = catch_unwind(...);` or `catch_unwind(...).ok();` in an attempt to ignore all panics, which implicitly drops the payload.

4 crates:

1. Direct control flow based on whether or not a panic occurred.
2. At any point, implicitly drop the payload.

1 crate:

1. Move the payload into a provided field, pointer, global variable, or thread-local variable, to be processed later.
2. Implicitly drop the prior payload in that place.

\* These methods can be permissible when the panic comes from a controlled source, e.g., from a unit test.

> **Methodology**
>
> I only included uses of `catch_unwind()` in library crates published to [crates.io](http://crates.io). I did not include uses within test cases, but I did include uses within proc macros and testing support crates. Initially, I just searched for `lang:rust /\bcatch_unwind\b/` on GitHub Code Search, and added the crates from the 100 results it returned. Then, I scraped the [crates.io](http://crates.io) registry directly, and I added all crate versions where:
> 
> - the version is the latest non-prerelease, non-yanked version of the crate as of 2022-07-12;
> - the version has at least 10,000 total downloads on [crates.io](http://crates.io); and
> - the source repo is publicly available, usually on GitHub or a GitLab instance.
> 
> Many of the crates are old and unmaintained, but some are still frequently downloaded.

> **Raw results**
>
> These are quite messy, since I didn't have any consistent coding process. I just looked for enough details to categorize the uses and to judge their soundness.
> 
> abi\_stable v0.10.4 ([abi\_stable\_crates/abi\_stable at 0dcb0681cd9ef94978150b1a68f988d780fc9f61 · rodrimati1992/abi\_stable\_crates · GitHub](https://github.com/rodrimati1992/abi_stable_crates/tree/0dcb0681cd9ef94978150b1a68f988d780fc9f61/abi_stable)):  
> `abi_stable::external_types::parking_lot::once::Closure::call_with_closure()`: `match` with ref, return `RResult`, implicit drop (impossible?)  
> `abi_stable::external_types::parking_lot::once::Closure::run_call()`/`abi_stable::external_types::parking_lot::once::ROnce::call_once()`: `match` with ref, move into field, cross boundary, `resume_unwind`  
> `abi_stable::library::__call_root_module_loader()`: `unwrap_or`, return `Result` (uncontrolled, unsound!)
> 
> abi\_stable\_shared v0.10.3 ([abi\_stable\_crates/abi\_stable\_shared at ec2638d8c37329e6bb7d47a25bee7fba2b79010b · rodrimati1992/abi\_stable\_crates · GitHub](https://github.com/rodrimati1992/abi_stable_crates/tree/ec2638d8c37329e6bb7d47a25bee7fba2b79010b/abi_stable_shared)):  
> `abi_stable_shared::test_utils::must_panic()`: `match Err(e)`, return `Result`
> 
> allo-isolate v0.1.12 ([GitHub - shekohex/allo-isolate at ee2a2cb0bc1dc8a5006ced8b3c9b93343f8c084a](https://github.com/sunshine-protocol/allo-isolate/tree/ee2a2cb0bc1dc8a5006ced8b3c9b93343f8c084a)):  
> `allo_isolate::Isolate::catch_unwind()`/`<allo_isolate::catch_unwind::CatchUnwind as Future>::poll()`: return `Result`
> 
> alpm v2.2.1 ([alpm.rs/alpm at alpm-v2.2.1 · archlinux/alpm.rs · GitHub](https://github.com/archlinux/alpm.rs/tree/alpm-v2.2.1/alpm)):  
> `alpm::cb::dlcb()`: `let _` (uncontrolled, unsound!)  
> `alpm::cb::eventcb()`: `let _` (uncontrolled, unsound!)  
> `alpm::cb::fetchcb()`: `unwrap_or`, return `c_int` (uncontrolled, unsound!)  
> `alpm::cb::logcb()`: `let _` (uncontrolled, unsound!)  
> `alpm::cb::progresscb()`: `let _` (uncontrolled, unsound!)  
> `alpm::cb::questioncb()`: `let _` (uncontrolled, unsound!)
> 
> async-global-executor v2.2.0 ([GitHub - async-rs/async-global-executor at v2.2.0](https://github.com/async-rs/async-global-executor/tree/v2.2.0)):  
> `async_global_executor::threading::thread_main_loop()`: if `is_ok`, `break`, implicit drop (uncontrolled!)  
> `async_global_executor::threading::wait_for_local_executor_completion()`: if `is_ok`, `break`, implicit drop (uncontrolled!)
> 
> async-io v1.7.0 ([GitHub - smol-rs/async-io at v1.7.0](https://github.com/smol-rs/async-io/tree/v1.7.0)):  
> `async_io::src::reactor::ReactorLock::react()`: `ok` (uncontrolled!)  
> `async_io::src::reactor::Source::poll_ready()`: `ok` (uncontrolled!)
> 
> bcc v0.0.32 ([GitHub - rust-bpf/rust-bcc at v0.0.32](https://github.com/rust-bpf/rust-bcc/tree/v0.0.32)):  
> `bcc::ring_buf::callback::raw_callback()`: `let _` (uncontrolled, unsound!)  
> `bcc::perf_event::callback::raw_callback()`: `let _` (uncontrolled, unsound!)
> 
> blocking v1.2.0 ([GitHub - smol-rs/blocking at v1.2.0](https://github.com/smol-rs/blocking/tree/v1.2.0)):  
> `blocking::Executor::main_loop()`: `ok` (uncontrolled!)
> 
> boring v2.0.0 ([boring/boring at db6867b794303c7666c922c7f8ef5cf3d5f58396 · cloudflare/boring · GitHub](https://github.com/cloudflare/boring/tree/db6867b794303c7666c922c7f8ef5cf3d5f58396/boring)):  
> `boring::ssl::bio::bread()`/`boring::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `boring::ssl::bio::bwrite()`/`boring::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `boring::ssl::bio::ctrl()`/`boring::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `boring::util::invoke_passwd_cb()`/`<boring::util::CallbackState as Drop>::drop()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`
> 
> brotli v3.3.4 ([GitHub - dropbox/rust-brotli at 3.3.4](https://github.com/dropbox/rust-brotli/tree/3.3.4)):  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::compressor::BrotliEncoderCompress()`: `match Err(panic_err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::compressor::BrotliEncoderCompressStream()`: `match Err(panic_err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::compressor::BrotliEncoderSetCustomDictionary()`: `if let Err(panic_err)`, call function with ref, implicit drop (impossible)  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::multicompress::BrotliEncoderCompressMulti()`: `match Err(panic_err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::multicompress::BrotliEncoderCompressWorkPool()`: `match Err(panic_err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::compressor::catch_panic()`/`brotli::ffi::multicompress::BrotliEncoderDestroyWorkPool()`: `if let Err(panic_err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::compressor::catch_panic_cstate()`/`brotli::ffi::compressor::BrotliEncoderCreateInstance()`: `match Err(err)`, call function with ref, implicit drop (controlled)  
> `brotli::ffi::multicompress::catch_panic_wstate()`/`brotli::ffi::multicompress::BrotliEncoderCreateWorkPool()`: `match Err(err)`, call function with ref, implicit drop (controlled)
> 
> brotli-decompressor v2.3.2 ([GitHub - dropbox/rust-brotli-decompressor at 67d75006199b2d062f8e74706cb104add012a96e](https://github.com/dropbox/rust-brotli-decompressor/tree/67d75006199b2d062f8e74706cb104add012a96e)):  
> `brotli_decompressor::ffi::catch_panic()`/`brotli_decompressor::ffi::BrotliDecoderDecompressStream()`: `match Err(mut readable_err)`, call function with ref, set indep. field, return `BrotliDecoderResult`, implicit drop (impossible)  
> `brotli_decompressor::ffi::catch_panic_state()`/`brotli_decompressor::ffi::BrotliDecoderCreateInstance()`: `match Err(mut e)`, call function with ref, return `*mut BrotliDecoderState`, implicit drop (controlled)
> 
> cairo-rs v0.15.12 ([gtk-rs-core/cairo at 0.15.12 · gtk-rs/gtk-rs-core · GitHub](https://github.com/gtk-rs/gtk-rs-core/tree/0.15.12/cairo)):  
> `cairo_rs::image_surface_png::read_func()`/`cairo_rs::image_surface_png::ImageSurface::create_from_png()`: `match Err(payload)`, move into field, cross boundary, `resume_unwind`  
> `cairo_rs::image_surface_png::write_func()`/`cairo_rs::image_surface_png::ImageSurface::write_to_png()`: `match Err(payload)`, move into field, cross boundary, `resume_unwind`  
> `cairo_rs::stream::write_callback()`/`cairo_rs::stream::Surface::finish_output_stream()`: `match Err(payload)`, move into field, cross boundary, `resume_unwind`
> 
> civet v0.11.0 ([GitHub - jtgeibel/rust-civet at v0.11.0](https://github.com/jtgeibel/rust-civet/tree/v0.11.0)) [old]:  
> `civet::raw::raw_handler()`: `match Err(..)`, return `i32` (uncontrolled, unsound!)
> 
> cool\_asserts v2.0.3 ([GitHub - Lucretiel/cool\_asserts at 2.0.3](https://github.com/Lucretiel/cool_asserts/tree/2.0.3)):  
> `cool_asserts::assert_panics::assert_panics!`: `match Err($panic)`, maybe call function with ref, implicit drop (controlled)
> 
> cpython v0.7.0 ([GitHub - dgrunwald/rust-cpython at 0.7.0](https://github.com/dgrunwald/rust-cpython/tree/0.7.0)):  
> `cpython::function::handle_callback()`: `match Err(err)`, create `AbortOnDrop` guard, implicit drop, forget guard
> 
> credibility v0.1.3 ([GitHub - antifuchs/credibility at v0.1.3](https://github.com/antifuchs/credibility/tree/v0.1.3)):  
> `credibility::test_block::TestBlock::eval_aver()`/`<credibility::reporter::DefaultTestReporter as TestReporter>::averred()`: if `is_err`, set indep. field, implicit drop (controlled)  
> `credibility::test_block::TestBlock::eval_aver()`/`<credibility::selftest::TestTracker as TestReporter>::averred()`: call indep. function, `match Err(_)`, set indep. field, implicit drop (controlled)  
> `credibility::test_block::TestBlock::eval_aver()`: move into trait function
> 
> crossbeam-utils v0.8.10 ([crossbeam/crossbeam-utils at crossbeam-utils-0.8.10 · crossbeam-rs/crossbeam · GitHub](https://github.com/crossbeam-rs/crossbeam/tree/crossbeam-utils-0.8.10/crossbeam-utils)):  
> `crossbeam_utils::thread::scope()`: call indep. functions, `match Err(err)`, `resume_unwind`
> 
> cryptobox-c v1.1.3 ([GitHub - wireapp/cryptobox-c at v1.1.3](https://github.com/wireapp/cryptobox-c/tree/v1.1.3)) [old]:  
> `cryptobox::catch_unwind()`: `match Err(_)`, return `CBoxResult`, implicit drop (controlled)
> 
> csound v0.1.8 ([GitHub - neithanmo/csound-rs at v0.1.8](https://github.com/neithanmo/csound-rs/tree/v0.1.8)):  
> `csound::callbacks::Trampoline::catch()`: `match Err(_)`, `exit`
> 
> cucumber v0.13.0 ([GitHub - cucumber-rs/cucumber at v0.13.0](https://github.com/cucumber-rs/cucumber/tree/v0.13.0)):  
> `cucumber::runner::basic::Executor::run_before_hook()`/`cucumber::runner::basic::Executor::run_scenario()`/`cucumber::runner::basic::Executor::emit_failed_events()`: `match Err((panic_info, world))`, move into `ExecutionFailure`, call function with ref, call indep. functions, `err`, `if let Some(exec_err)`, `match ExecutionFailure::BeforeHookPanicked { panic_info, meta, .. }`, move into `Cucumber`, move into channel (uncontrolled?)
> 
> curl v0.4.43 ([GitHub - alexcrichton/curl-rust at 0.4.43](https://github.com/alexcrichton/curl-rust/tree/0.4.43)):  
> `curl::panic::catch()`/`curl::panic::propagate()`: `match Err(e)`, move into global, cross boundary, `resume_unwind`
> 
> directwrite v0.1.4 ([GitHub - Connicpu/directwrite-rs at 39c4dea396e833920cdd4eff20138944f067a7ff](https://github.com/Connicpu/directwrite-rs/tree/39c4dea396e833920cdd4eff20138944f067a7ff)):  
> `directwrite::inline_object::vtbl::draw()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::inline_object::vtbl::get_break_conditions()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::inline_object::vtbl::get_metrics()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::inline_object::vtbl::get_overhand_metrics()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::draw_glyph_run()`: `match _`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::draw_inline_object()`: `match _`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::draw_strikethrough()`: `match _`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::draw_underline()`: `match _`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::get_current_transform()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::get_pixels_per_dip()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)  
> `directwrite::text_renderer::vtbl::comref::is_pixel_snapping_disabled()`: `match Err(_)`, return `HRESULT`, implicit drop (uncontrolled, unsound!)
> 
> easy-parallel v3.2.0 ([GitHub - smol-rs/easy-parallel at v3.2.0](https://github.com/smol-rs/easy-parallel/tree/v3.2.0)):  
> `easy_parallel::Parallel::finish()`: call indep. functions, `if let Some(err)`, `resume_unwind`
> 
> emacs v0.18.0 ([GitHub - ubolonton/emacs-module-rs at a9b573c3ef443e9adf04cfc349ac7b3bc91b28e2](https://github.com/ubolonton/emacs-module-rs/tree/a9b573c3ef443e9adf04cfc349ac7b3bc91b28e2)):  
> `<emacs::func::CallEnv as HandleCall>::handle_call()`/`emacs::env::Env::handle_panic()`: `match Err(error)`, attempt to `downcast`, call function with ref, implicit drop (uncontrolled, unwound! incidentally unsound!)  
> `emacs::init::initialize()`: `match Err(e)`, call function with ref, return `c_int`, implicit drop (uncontrolled, unsound! incidentally unsound!)
> 
> ert v0.2.2 ([GitHub - YushiOMOTE/ert at 0fbcee6b3c377d06aada4199d28f63445e255234](https://github.com/YushiOMOTE/ert/tree/0fbcee6b3c377d06aada4199d28f63445e255234)):  
> `ert::router::Via::new()`/`<ert::router::Via as Future>::poll()`: `expect`
> 
> execution-context v0.1.0 ([GitHub - mitsuhiko/rust-execution-context at 0.1.0](https://github.com/mitsuhiko/rust-execution-context/tree/0.1.0)) [old]:  
> `execution_context::ctx::ExecutionContext::run()`: set indep. field, `match Err(err)`, `resume_unwind`
> 
> festive v0.2.2 ([GitHub - estk/festive at c69ce3ab08196a678d632ada7425b497b5c7c0ba](https://github.com/estk/festive/tree/c69ce3ab08196a678d632ada7425b497b5c7c0ba)):  
> `festive::fork::fork_impl()`: `match Err(_)`, `exit`
> 
> ffi-support v0.4.4 ([GitHub - mozilla/ffi-support at v0.4.4](https://github.com/mozilla/ffi-support/tree/v0.4.4)):  
> `ffi_support::call_with_result_impl()`/`<ffi_support::error::ExternError as From<Box<dyn Any + Send + 'static>>>::from()`: `match Err(e)`, call functions with ref, return `ExternError`, implicit drop (uncontrolled, unsound!)
> 
> ffi-toolkit v0.5.0 ([rust-fil-ffi-toolkit/ffi-toolkit at ffi-toolkit-v0.5.0 · filecoin-project/rust-fil-ffi-toolkit · GitHub](https://github.com/filecoin-project/rust-fil-ffi-toolkit/tree/ffi-toolkit-v0.5.0/ffi-toolkit)):  
> `ffi_toolkit::catch_panic_response()`: `match Err(panic)`, call function with ref, call indep. functions, return `*mut T`, implicit drop (uncontrolled, unsound!)
> 
> ffms2 v0.2.0 ([GitHub - rust-av/ffms2-rs at 52a43f3566dfa55784fe7fc5f41d2a2cf7ac0241](https://github.com/rust-av/ffms2-rs/tree/52a43f3566dfa55784fe7fc5f41d2a2cf7ac0241)):  
> `ffms2::index::Indexer::ProgressCallback::IndexCallback()`: if `is_err`, `abort`
> 
> fil-rustacuda v0.1.3 ([GitHub - filecoin-project/fil-rustacuda at v0.1.3](https://github.com/filecoin-project/fil-rustacuda/tree/v0.1.3)):  
> `fil_rustacuda::stream::callback_wrapper()`: `let _` (uncontrolled, unsound!)
> 
> findshlibs v0.10.2 ([GitHub - gimli-rs/findshlibs at 0.10.2](https://github.com/gimli-rs/findshlibs/tree/0.10.2)):  
> `findshlibs::linux::SharedLibrary::callback()`/`findshlibs::linux::SharedLibrary::each()`: `match Err(panicked)`, move into `Option` field, cross boundary, `if let Some(panic)`, `resume_unwind`
> 
> flaky\_test v0.1.0 ([GitHub - denoland/flaky\_test at v0.1.0](https://github.com/denoland/flaky_test/tree/v0.1.0)):  
> `flaky_test::flaky_test::#name()`: if `is_ok`, else if `i == 2`, (`unwrap_err`, `resume_unwind`), else implicit drop (controlled)
> 
> frame-benchmarking v3.1.0 ([substrate/frame/benchmarking at f6de92e1f353be3b88a575187a22a3827a823bf2 · paritytech/substrate · GitHub](https://github.com/paritytech/substrate/tree/f6de92e1f353be3b88a575187a22a3827a823bf2/frame/benchmarking)):  
> `frame_benchmarking::impl_benchmark_test_suite!::benchmark_tests::test_benchmarks()`: `if let Err(err)`, call function with ref, set indep. field, implicit drop (controlled)
> 
> fruity v0.3.0 ([GitHub - nvzqz/fruity at v0.3.0](https://github.com/nvzqz/fruity/tree/v0.3.0)):  
> `fruity::dispatch::queue::DispatchQueue::apply()`: `match Err(_error)`, `abort`  
> `fruity::dispatch::queue::DispatchQueue::apply_auto()`: `match Err(_error)`, `abort`  
> `fruity::dispatch::queue::DispatchQueue::spawn_async()`: `match Err(_error)`, `abort`  
> `fruity::dispatch::queue::DispatchQueue::spawn_sync()`: cross boundary, `match Err(error)`, `resume_unwind`
> 
> fruity\_\_bbqsrc v0.2.0 ([GitHub - nvzqz/fruity at eadc4f576936c554ac2b9935679281230040c644](https://github.com/nvzqz/fruity/tree/eadc4f576936c554ac2b9935679281230040c644)):  
> `fruity__bbqsrc::dispatch::queue::DispatchQueue::apply()`: `match Err(_error)`, `abort`  
> `fruity__bbqsrc::dispatch::queue::DispatchQueue::apply_auto()`: `match Err(_error)`, `abort`  
> `fruity__bbqsrc::dispatch::queue::DispatchQueue::spawn_async()`: `match Err(_error)`, `abort`  
> `fruity__bbqsrc::dispatch::queue::DispatchQueue::spawn_sync()`: cross boundary, `match Err(error)`, `resume_unwind`
> 
> futures-cpupool v0.1.8 ([futures-rs/futures-cpupool at futures-cpupool-0.1.8 · rust-lang/futures-rs · GitHub](https://github.com/rust-lang/futures-rs/tree/futures-cpupool-0.1.8/futures-cpupool)):  
> `futures_cpupool::CpuPool::spawn()`/`<futures_cpupool::CpuFuture as Future>::poll()`: `resume_unwind`
> 
> futures-executor-preview v0.2.2 ([futures-rs/futures-executor at 0.2.2 · rust-lang/futures-rs · GitHub](https://github.com/rust-lang/futures-rs/tree/0.2.2/futures-executor)):  
> `<futures_executor_preview::spawn::SpawnWithHandle as Future>::poll()`/`<futures_executor_preview::spawn::JoinHandle as Future>::poll()`: cross boundary, `match Err(e)`, `resume_unwind`
> 
> futures-lite v1.12.0 ([GitHub - smol-rs/futures-lite at v1.12.0](https://github.com/smol-rs/futures-lite/tree/v1.12.0)):  
> `futures_lite::future::FutureExt::catch_unwind()`/`<futures_lite::future::CatchUnwind as Future>::poll()`: return `Result`
> 
> futures-util v0.3.21 ([futures-rs/futures-util at 0.2.2 · rust-lang/futures-rs · GitHub](https://github.com/rust-lang/futures-rs/tree/0.2.2/futures-util)):  
> `futures_util::future::future::FutureExt::catch_unwind()`/`<futures_util::future::future::catch_unwind::CatchUnwind as Future>::poll()`: return `Result`  
> `futures_util::future::future::FutureExt::remote_handle()`/`<futures_util::future::future::remote_handle::RemoteHandle as Future>::poll()`: `resume_unwind`  
> `futures_util::stream::stream::StreamExt::catch_unwind()`/`<futures_util::stream::stream::catch_unwind::CatchUnwind as Stream>::poll_next()`: set indep. field, return `Result`
> 
> futures-util-preview v0.2.2 ([futures-rs/futures-util at 0.3.21 · rust-lang/futures-rs · GitHub](https://github.com/rust-lang/futures-rs/tree/0.3.21/futures-util)):  
> `futures_util::future::FutureExt::catch_unwind()`/`<futures_util::future::catch_unwind::CatchUnwind as Future>::poll()`: return `Result`  
> `futures_util::stream::StreamExt::catch_unwind()`/`<futures_util::stream::catch_unwind::CatchUnwind as Stream>::poll_next()`: return `Result`
> 
> galvanic-assert v0.8.7 ([GitHub - mindsbackyard/galvanic-assert at 33855f4a2ef829ddd5652e7edbbf0249dddf77b6](https://github.com/mindsbackyard/galvanic-assert/tree/33855f4a2ef829ddd5652e7edbbf0249dddf77b6)):  
> `galvanic_assert::assert_that!($actual:expr, does not panic)`: if `is_err`, call indep. function, implicit drop (controlled)  
> `galvanic_assert::assert_that!($actual:expr, panics)`: if `is_ok`, else implicit drop (controlled)  
> `galvanic_assert::get_expectation_for!($actual:expr, does not panic)`: if `is_err`, else return `Expectation`, implicit drop (controlled)  
> `galvanic_assert::get_expectation_for!($actual:expr, panics)`: if `is_ok`, else return `Expectation`, implicit drop (controlled)
> 
> galvanic-test v0.2.0 ([GitHub - mindsbackyard/galvanic-test at v0.2.0](https://github.com/mindsbackyard/galvanic-test/tree/v0.2.0)):  
> `galvanic_test::test!`: if `is_err`, call indep. functions, implicit drop (controlled)
> 
> generator v0.7.0 ([GitHub - Xudong-Huang/generator-rs at 0.7.0](https://github.com/Xudong-Huang/generator-rs/tree/0.7.0)):  
> `generator::gen_impl::gen_init()`/`generator::gen_impl::GeneratorImpl::resume_gen()`: `if let Err(cause)`, call function with ref, call indep. function, move into local, cross boundary, `if let Some(err)`, `resume_unwind`
> 
> gio v0.15.12 ([gtk-rs-core/gio at 0.15.12 · gtk-rs/gtk-rs-core · GitHub](https://github.com/gtk-rs/gtk-rs-core/tree/0.15.12/gio)):  
> `gio::read_input_stream::AnyReader::with_inner()`/`gio::read_input_stream::ReadInputStream::close_and_take()`: `match Err(panic)`, move into field, cross boundary, `resume_unwind`  
> `gio::write_output_stream::AnyWriter::with_inner()`/`gio::write_output_stream::WriteOutputStream::close_and_take()`: `match Err(panic)`, move into field, cross boundary, `resume_unwind`
> 
> git2 v0.14.4 ([GitHub - rust-lang/git2-rs at 0.14.4](https://github.com/rust-lang/git2-rs/tree/0.14.4)):  
> `git2::panic::wrap()`/`git2::panic::check()`: `match Err(e)`, move into global `Option`, cross boundary, `if let Some(err)`, `resume_unwind`
> 
> glow v0.11.2 ([GitHub - grovesNL/glow at 3bf1f8acef58edaeda3275b53b3cc00d7615d7f0](https://github.com/grovesNL/glow/tree/3bf1f8acef58edaeda3275b53b3cc00d7615d7f0)):  
> `glow::native::raw_debug_message_callback()`: `ok` (uncontrolled, unsound!)
> 
> gstreamer v0.18.7 ([Making sure you're not a bot!](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/tree/0.18.7/gstreamer)):  
> `gstreamer::subclass::error::panic_to_error!`: `match Err(err)`, call functions with ref, return `$ret`, implicit drop (uncontrolled, unsound!)  
> `gstreamer::subclass::plugin_1_12::plugin_define!::plugin_desc::plugin_init_trampoline()`: `match Err(err)`, call functions with ref, return `gboolean`, implicit drop (uncontrolled, unsound!)  
> `gstreamer::subclass::plugin_1_14::plugin_define!::plugin_desc::plugin_init_trampoline()`: `match Err(err)`, call functions with ref, return `gboolean`, implicit drop (uncontrolled, unsound!)
> 
> gstreamer-app v0.18.7 ([Making sure you're not a bot!](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/tree/0.18.7/gstreamer-app)):  
> `gstreamer_app::app_sink::trampoline_eos()`: `match Err(err)`, set indep. field, call function with ref, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_sink::trampoline_new_event()`: `match Err(err)`, set indep. field, call function with ref, return `gboolean`, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_sink::trampoline_new_preroll()`: `match Err(err)`, set indep. field, call function with ref, return `GstFlowReturn`, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_sink::trampoline_new_sample()`: `match Err(err)`, set indep. field, call function with ref, return `GstFlowReturn`, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_src::trampoline_enough_data()`: `match Err(err)`, set indep. field, call function with ref, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_src::trampoline_need_data()`: `match Err(err)`, set indep. field, call function with ref, implicit drop (uncontrolled, unsound!)  
> `gstreamer_app::app_src::trampoline_seek_data()`: `match Err(err)`, set indep. field, call function with ref, implicit drop (uncontrolled, unsound!)
> 
> guillotiere v0.6.2 ([GitHub - nical/guillotiere at bf7e9464390485a96399f77e9b1bff3d442b8258](https://github.com/nical/guillotiere/tree/bf7e9464390485a96399f77e9b1bff3d442b8258)):  
> `guillotiere::recording::Recording::replay()`/`guillotiere::recording::Recording::find_reduced_testcase()`: `is_ok`, implicit drop (controlled)
> 
> gurobi v0.3.4 ([https://github.com/ubnt-intrepid/rust-gurobi/tree/v0.3.4](https://github.com/ubnt-intrepid/rust-gurobi/tree/v0.3.4)) [old]:  
> `gurobi::model::callback_wrapper()`: `match Err(e)`, return `c_int`, implicit drop (uncontrolled, unsound!)
> 
> hdf5 v0.8.1 ([https://github.com/aldanor/hdf5-rust/tree/v0.8.1](https://github.com/aldanor/hdf5-rust/tree/v0.8.1)):  
> `hdf5::error::ErrorStack::expand::callback()`: `unwrap_or`, return `herr_t` (controlled)
> 
> helix v0.7.5 ([https://github.com/tildeio/helix/tree/v0.7.5](https://github.com/tildeio/helix/tree/v0.7.5)):  
> `helix::macros::init::handle_exception!`/`helix::errors::Error::from_any()`: `map_err(|e|)`, attempt to `downcast`, `unwrap_or_else(|any|)`, call function with ref, return `Error`, implicit drop (uncontrolled, unsound!)
> 
> honggfuzz v0.5.54 ([https://github.com/rust-fuzz/honggfuzz-rs/tree/v0.5.54](https://github.com/rust-fuzz/honggfuzz-rs/tree/v0.5.54)):  
> `honggfuzz::fuzz()`: `is_err`, implicit drop (uncontrolled!)
> 
> httpbis v0.9.1 ([https://github.com/stepancheg/rust-http2/tree/v0.9.1](https://github.com/stepancheg/rust-http2/tree/v0.9.1)):  
> `httpbis::client_died_error_holder::SomethingDiedErrorHolder::wrap_future()`/`httpbis::misc::any_to_string()`: `if let Err(e)`, attempt to `downcast`, else implicit drop (uncontrolled!)
> 
> hyper v0.14.20 ([https://github.com/hyperium/hyper/tree/v0.14.20](https://github.com/hyperium/hyper/tree/v0.14.20)):  
> `hyper::ffi::macros::ffi_fn!::$name()`: `match Err(_)`, return default value, implicit drop (uncontrolled, unsound!)
> 
> imgui v0.8.2 ([https://github.com/imgui-rs/imgui-rs/tree/v0.8.2/imgui](https://github.com/imgui-rs/imgui-rs/tree/v0.8.2/imgui)):  
> `imgui::clipboard::get_clipboard_text()`: `unwrap_or_else(|_|)`, call function, `abort` (incidentally unsound!)  
> `imgui::clipboard::set_clipboard_text()`: `unwrap_or_else(|_|)`, call function, `abort` (incidentally unsound!)
> 
> interprocess v1.1.1 ([https://github.com/kotauskas/interprocess/tree/1.1.1](https://github.com/kotauskas/interprocess/tree/1.1.1)):  
> `interprocess::os::unix::signal::signal_receiver()`: `unwrap_or_else(|_|)`, `abort`  
> `interprocess::os::windows::signal::signal_receiver()`: `unwrap_or_else(|_|)`, `abort`
> 
> ladspa v0.3.4 ([https://github.com/nwoeanhinnogaehr/ladspa.rs/tree/e8c899912225ec6b8c93146aa886c09c1846d766](https://github.com/nwoeanhinnogaehr/ladspa.rs/tree/e8c899912225ec6b8c93146aa886c09c1846d766)) [old]:  
> `ladspa::fii::call_user_code!`: `match Err(_)`, call indep. function, return `Option`, implicit drop (uncontrolled, unsound!)
> 
> lambda\_runtime v0.5.1 ([https://github.com/awslabs/aws-lambda-rust-runtime/tree/v0.5.1-runtime/lambda-runtime](https://github.com/awslabs/aws-lambda-rust-runtime/tree/v0.5.1-runtime/lambda-runtime)):  
> `lambda_runtime::Runtime::run()`: `match Err(err)`, call functions with ref, return `Result`, implicit drop (uncontrolled!)
> 
> libfuzzer-sys v0.4.3 ([https://github.com/rust-fuzz/libfuzzer/tree/0.4.3](https://github.com/rust-fuzz/libfuzzer/tree/0.4.3)):  
> `libfuzzer_sys::test_input_wrap()`: `err`, if `is_some`, `abort` (incidentally unsound!)
> 
> liblightning v0.0.2 ([https://github.com/losfair/liblightning/tree/41056bb1cfd2b870ac8b62b9c64b1890a7be8650](https://github.com/losfair/liblightning/tree/41056bb1cfd2b870ac8b62b9c64b1890a7be8650)):  
> `liblightning::co::CoState::co_initializer()`/`<liblightning::co::CoState as CommonCoState>::resume()`: `if let Err(e)`, move into field, cross boundary, `resume_unwind`  
> `liblightning::scheduler::SharedSchedState::prepare_coroutine()`: move into field, cross boundary, return `Result`
> 
> libpulse-binding v2.26.0 ([https://github.com/jnqnfe/pulse-binding-rust/tree/v2.26.0/pulse-binding](https://github.com/jnqnfe/pulse-binding-rust/tree/v2.26.0/pulse-binding)):  
> `libpulse_binding::context::event_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_device_manager::read_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_device_restore::ext_subscribe_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_device_restore::read_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_stream_restore::read_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_subscribe_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::ext_test_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::context_index_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_card_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_client_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_sample_info_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_server_info_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_sink_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_sink_input_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_source_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_source_output_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::get_stat_info_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::mod_info_list_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::introspect::send_message_to_object_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::notify_cb_proxy_multi()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::notify_cb_proxy_single()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::scache::play_sample_success_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::subscribe::cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::context::success_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::mainloop::api::once_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::mainloop::events::deferred::event_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::mainloop::events::io::event_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::mainloop::events::timer::event_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::mainloop::signal::signal_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::operation::notify_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::stream::event_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::stream::notify_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::stream::request_cb_proxy()`: `let _` (uncontrolled, unsound!)  
> `libpulse_binding::stream::success_cb_proxy()`: `let _` (uncontrolled, unsound!)
> 
> libtest v0.0.1 ([https://github.com/rust-lang/libtest/tree/72798cdede83eead387f32875d3ea77c85e29276/libtest](https://github.com/rust-lang/libtest/tree/72798cdede83eead387f32875d3ea77c85e29276/libtest)):  
> `libtest::bench::benchmark()`: `match Err(_)`, return `TestResult`, implicit drop (controlled)  
> `libtest::run_test::run_test_inner()`/`libtest::calc_result()`: call indep. functions, `match`, maybe call functions with ref, return `TestResult`, implicit drop (controlled)
> 
> lightproc v0.3.5 ([https://github.com/bastion-rs/bastion/tree/lightproc-v0.3.5/src/lightproc](https://github.com/bastion-rs/bastion/tree/lightproc-v0.3.5/src/lightproc)):  
> `lightproc::lightproc::LightProc::recoverable()`/`<lightproc::recoverable_handle::RecoverableHandle as Future>::poll()`: `match Err(_)`, call indep. functions, return `Option`, implicit drop (uncontrolled!)
> 
> lignin v0.1.0 ([https://github.com/Tamschi/lignin/tree/v0.1.0](https://github.com/Tamschi/lignin/tree/v0.1.0)):  
> `lignin::callback_registry::callbacks_on::invoke()`: `match Err(panic)`, call indep. function, `resume_unwind`
> 
> mendes v0.0.64 ([https://github.com/djc/mendes/tree/8766d9f6f18df902281cb9ad6235cd8fe9399ba5/mendes](https://github.com/djc/mendes/tree/8766d9f6f18df902281cb9ad6235cd8fe9399ba5/mendes)):  
> `<mendes::hyper::ConnectionService as Service<Request<Body>>>::call()/`mendes::hyper::panic\_response()`, `match Err(e)`, maybe call functions with ref, return `Result`, implicit drop (uncontrolled!)
> 
> mini-v8 v0.3.0 ([https://github.com/SkylerLipthay/mini-v8/tree/39a44d1d78c8293da7be83751da907f18a90eeb5](https://github.com/SkylerLipthay/mini-v8/tree/39a44d1d78c8293da7be83751da907f18a90eeb5)) [tough to build]:  
> `mini_v8::ffi::callback_wrapper()`: `match Err(err)`, call function with ref, `abort`  
> (contains another unsound function)
> 
> miniz\_oxide\_c\_api v0.3.0 ([https://github.com/Frommi/miniz\_oxide/tree/cff503a88812b4c467d9859ca7603cc623815d6b](https://github.com/Frommi/miniz_oxide/tree/cff503a88812b4c467d9859ca7603cc623815d6b)):  
> `miniz_oxide_c_api::mz_deflateInit2()`: `match Err(_)`, call indep. function, return `c_int`, implicit drop (controlled)  
> `miniz_oxide_c_api::mz_inflateInit2()`: `match Err(_)`, call indep. function, return `c_int`, implicit drop (controlled)  
> `miniz_oxide_c_api::oxidize!::$mz_func()`: `match Err(_)`, call indep. function, return `c_int`, implicit drop (controlled)  
> `miniz_oxide_c_api::tdef::tdefl_init()`: `match Err(_)`, call indep. function, return `tdefl_status`, implicit drop (controlled)
> 
> mlua v0.8.0 ([https://github.com/khvzak/mlua/tree/v0.8.0](https://github.com/khvzak/mlua/tree/v0.8.0)):  
> `mlua::lua::callback_error_ext()`/`mlua::util::pop_error()`: `match Err(p)`, move into field, cross boundary, `resume_unwind`  
> `mlua::util::callback_error()`/`mlua::util::pop_error()`: `match Err(p)`, move into field, cross boundary, `resume_unwind`
> 
> mocktopus\_macros v0.7.11 ([https://github.com/CodeSandwich/Mocktopus/tree/aa93669b731074e47bf47628af1f299752f69901/macros](https://github.com/CodeSandwich/Mocktopus/tree/aa93669b731074e47bf47628af1f299752f69901/macros)):  
> `mocktopus_macros::header_builder::FnHeaderBuilder::build()`: `match Err({unwind})`, call indep. functions, `resume_unwind`
> 
> mozjs v0.10.1 ([https://github.com/servo/rust-mozjs/tree/v0.10.1](https://github.com/servo/rust-mozjs/tree/v0.10.1)):  
> `mozjs::panic::wrap_panic()`/`mozjs::panic::maybe_resume_unwind()`: `match Err(error)`, call indep. functions, move into global, implicit drop of prior value (uncontrolled!)
> 
> neon v0.10.1 ([https://github.com/neon-bindings/neon/tree/0.10.1](https://github.com/neon-bindings/neon/tree/0.10.1)):  
> `neon::context::internal::try_catch_glue()`/`neon::context::internal::ContextInternal::try_catch_internal()`: `match Err(err)`, move into pointer, cross boundary, `resume_unwind`  
> `neon::types::error::convert_panics()`: `match Err(panic)`, call functions with ref, call indep. functions, return `Result`, implicit drop (uncontrolled, unsound!)
> 
> neon-runtime v0.10.1 ([https://github.com/neon-bindings/neon/tree/0.10.1/crates/neon-runtime](https://github.com/neon-bindings/neon/tree/0.10.1/crates/neon-runtime)):  
> `neon_runtime::napi::async_work::call_execute()`/`neon_runtime::napi::async_work::call_complete()`, move into field, cross boundary, `resume_unwind`  
> `neon_runtime::napi::no_panic::FailureBoundary::catch_failure()`/`neon_runtime::napi::error::fatal_error()`: `if let Err(panic)`, call function with ref, `napi::fatal_error`, `unreachable!()`
> 
> ntest v0.8.0 ([https://github.com/becheran/ntest/tree/v0.8.0/ntest](https://github.com/becheran/ntest/tree/v0.8.0/ntest)):  
> `ntest::assert_panics()`: if not `is_err`, `panic!()`, else implicit drop (controlled)
> 
> openssl v0.10.41 ([https://github.com/sfackler/rust-openssl/tree/openssl-v0.10.41/openssl](https://github.com/sfackler/rust-openssl/tree/openssl-v0.10.41/openssl)):  
> `openssl::util::bio::bread()`/`openssl::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `openssl::util::bio::bwrite()`/`openssl::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `openssl::util::bio::ctrl()`/`openssl::ssl::SslStream::check_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`  
> `openssl::util::invoke_passwd_cb()`/`<openssl::util::CallbackState as Drop>::drop()`: `match Err(err)`, move into field, cross boundary, `resume_unwind`
> 
> openvpn-plugin v0.4.1 ([https://github.com/mullvad/openvpn-plugin-rs/tree/v0.4.1](https://github.com/mullvad/openvpn-plugin-rs/tree/v0.4.1)):  
> `openvpn_plugin::openvpn_plugin_close()`: `if let Err(e)`, call function with ref, implicit drop (uncontrolled, unsound!)  
> `openvpn_plugin::openvpn_plugin_func()`: `match Err(e)`, call function with ref, return `c_int`, implicit drop (uncontrolled, unsound!)  
> `openvpn_plugin::openvpn_plugin_open()`: `match Err(e)`, call function with ref, return `c_int`, implicit drop (uncontrolled, unsound!)
> 
> paste v1.0.7 ([https://github.com/dtolnay/paste/tree/1.0.7](https://github.com/dtolnay/paste/tree/1.0.7)):  
> `paste::pasted_to_tokens()`: `match Err(_)`, return `Result`, implicit drop (controlled)
> 
> paste-impl v0.1.18 ([https://github.com/dtolnay/paste/tree/0.1.18/impl](https://github.com/dtolnay/paste/tree/0.1.18/impl)):  
> `paste_impl::paste_segments()`: `match Err(_)`, return `Result`, implicit drop (controlled)
> 
> proc-macro-error v1.0.4 ([https://gitlab.com/CreepySkeleton/proc-macro-error/-/tree/v1.0.4](https://gitlab.com/CreepySkeleton/proc-macro-error/-/tree/v1.0.4)):  
> `proc_macro_error::entry_point()`: `match Err(boxed)`, attempt to `downcast`, `resume_unwind`
> 
> proc-macro2 v1.0.40 ([https://github.com/dtolnay/proc-macro2/tree/1.0.40](https://github.com/dtolnay/proc-macro2/tree/1.0.40)):  
> `proc_macro2::detection::initialize()`: `is_ok`, implicit drop (controlled)  
> `proc_macro2::wrapper::proc_macro_parse()`: `unwrap_or_else(|_|)`, return `Result`, implicit drop (controlled)
> 
> proc-macro2-diagnostics v0.9.1 ([https://github.com/SergioBenitez/proc-macro2-diagnostics/tree/8a739598692e195858249fb3ad89370dca893371](https://github.com/SergioBenitez/proc-macro2-diagnostics/tree/8a739598692e195858249fb3ad89370dca893371)):  
> `proc_macro2_diagnostics::nightly_works()`: `is_ok`, implicit drop (controlled)
> 
> procspawn v0.10.1 ([https://github.com/mitsuhiko/procspawn/tree/0.10.1](https://github.com/mitsuhiko/procspawn/tree/0.10.1)):  
> `procspawn::core::run_func()`: `match Err(panic)`, call function with ref, return `Result`, implicit drop (uncontrolled, sound)
> 
> proptest v1.0.0 ([https://github.com/AltSysrq/proptest/tree/1.0.0/proptest](https://github.com/AltSysrq/proptest/tree/1.0.0/proptest)):  
> `proptest::test_runner::runner::call_test()`: `match Err(what)`, attempt to `downcast`, `unwrap_or_else(|_|)`, return `String`, implicit drop (uncontrolled!)
> 
> pyo3 v0.16.5 ([https://github.com/PyO3/pyo3/tree/v0.16.5](https://github.com/PyO3/pyo3/tree/v0.16.5)):  
> `pyo3::callback::handle_panic()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (uncontrolled, unsound?)  
> `pyo3::impl_::pyclass::generate_pyclass_getattro_slot!::__wrap()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (controlled?)  
> `pyo3::impl_::pymodule::ModuleDef::module_init()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (controlled?)  
> `pyo3::types::function::drop_closure()`: `if let Err(err)`, call function with ref, implicit drop (uncontrolled, unsound!); `let _` (controlled)
> 
> pyo3-macros-backend v0.16.5 ([https://github.com/PyO3/pyo3/tree/v0.16.5/pyo3-macros-backend](https://github.com/PyO3/pyo3/tree/v0.16.5/pyo3-macros-backend)):  
> `pyo3_macros_backend::method::FnSpec::get_wrapper_function::#ident()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (controlled?)  
> `pyo3_macros_backend::pymethod::impl_py_getter_def::__wrap()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (controlled?)  
> `pyo3_macros_backend::pymethod::impl_py_setter_def::__wrap()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (uncontrolled, unsound!)  
> `pyo3_macros_backend::pymethod::impl_traverse_slot::__wrap_()`/`pyo3::callback::abort_on_traverse_panic()`: `match Err(_payload)`, call indep. function, `abort`  
> `pyo3_macros_backend::pymethod::SlotDef::generate_type_slot::__wrap()`/`pyo3::callback::panic_result_into_callback_output()`/`pyo3::panic::PanicException::from_panic_payload()`: `match Err(payload)`, call functions by ref, implicit drop (controlled?)
> 
> quick-js v0.4.1 ([https://github.com/theduke/quickjs-rs/tree/quick-js-v0.4.1](https://github.com/theduke/quickjs-rs/tree/quick-js-v0.4.1)):  
> `quick_js::bindings::ContextWrapper::exec_callback()`: `match Err(_e)`, return indep. `Result`, implicit drop (uncontrolled, unsound!)
> 
> quickcheck v1.0.3 ([https://github.com/BurntSushi/quickcheck/tree/1.0.3](https://github.com/BurntSushi/quickcheck/tree/1.0.3)):  
> `quickcheck::tester::safe()`: `map_err(|any_err|)`, call functions with ref, return `String`, implicit drop (uncontrolled!)  
> `quickcheck::tester::TestResult::must_fail()`: `is_err`, return `TestResult`, implicit drop (uncontrolled!)
> 
> rayon-core v1.9.3 ([https://github.com/rayon-rs/rayon/tree/rayon-core-v1.9.3/rayon-core](https://github.com/rayon-rs/rayon/tree/rayon-core-v1.9.3/rayon-core)):  
> `<rayon_core::job::StackJob as Job>::execute()`/`rayon_core::job::JobResult::into_return_value()`: `match Err(x)`, move into field, cross boundary, `resume_unwind`  
> `rayon_core::join::join_context()`/`rayon_core::join::join_recover_from_panic()`: `match Err(err)`, call indep. function, `resume_unwind`  
> `rayon_core::scope::ScopeBase::execute_job_closure()`/`rayon_core::scope::ScopeBase::job_panicked()`/`rayon_core::scope::ScopeBase::maybe_propagate_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind` (incidentally unsound?)  
> `rayon_core::spawn::spawn_job()`/`rayon_core::registry::Registry::handle_panic()`: `match Err(err)`, move into function (abort on panic) OR abort
> 
> riker v0.4.2 ([https://github.com/riker-rs/riker/tree/2fbd243ce477839c15d74e22fceed10ee4a97f3b](https://github.com/riker-rs/riker/tree/2fbd243ce477839c15d74e22fceed10ee4a97f3b)):  
> `riker::kernel::kernel()`: `let _` (uncontrolled!)  
> `riker::kernel::start_actor()`: `map_err(|_|)`, return `CreateError`, implicit drop (uncontrolled!)
> 
> rlua v0.19.2 ([https://github.com/amethyst/rlua/tree/v0.19.2](https://github.com/amethyst/rlua/tree/v0.19.2)):  
> `rlua::util::callback_error()`/`rlua::util::pop_error()`: `match Err(p)`, move into field, cross boundary, `resume_unwind`
> 
> rouille v3.5.0 ([https://github.com/tomaka/rouille/tree/v3.5.0](https://github.com/tomaka/rouille/tree/v3.5.0)):  
> `rouille::log::log()`: `match Err(payload)`, call indep. function, `resume_unwind`  
> `rouille::log::log_custom(): `match Err(payload)`, call indep. function, `resume\_unwind` `rouille::Server::process()`: `match Err(\_)`, return `Response`, implicit drop (uncontrolled!)
> 
> rusb v0.9.1 ([https://github.com/a1ien/rusb/tree/v0.9.1-rusb](https://github.com/a1ien/rusb/tree/v0.9.1-rusb)):  
> `rusb::hotplug::hotplug_callback()`: `match Err(_)`, return `c_int`, implicit drop (uncontrolled, unsound!)
> 
> ruscii v0.3.2 ([https://github.com/lemunozm/ruscii/tree/v0.3.2](https://github.com/lemunozm/ruscii/tree/v0.3.2)):  
> `ruscii::app::App::run()`: `if let Err(_)`, call indep. functions, implicit drop (uncontrolled!)
> 
> rusqlite v0.27.0 ([https://github.com/rusqlite/rusqlite/tree/v0.27.0](https://github.com/rusqlite/rusqlite/tree/v0.27.0)):  
> `rusqlite::Connection::busy_handler::busy_handler_callback()`: `if let Ok(true)`, else return `c_int` (uncontrolled, unsound!)  
> `rusqlite::Connection::trace()`: `drop` (uncontrolled, unsound!)  
> `rusqlite::functions::call_boxed_final()`: `match Err(_)`, call function, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::functions::call_boxed_inverse()`: `match Err(_)`, call function, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::functions::call_boxed_step()`: `match Err(_)`, call function, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::functions::call_boxed_value()`: `match Err(_)`, call function, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::authorizer::call_boxed_closure()`: `map_or_else(|_|)`, return `c_int`, implicit drop (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::collation_needed::collation_needed_callback()`: `is_err`, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::commit_hook::call_boxed_closure()`: `drop` (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::create_collation::call_boxed_closure()`: `match Err(_)`, return `c_int`, implicit drop (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::create_scalar_function::call_boxed_closure()`: `match Err(_)`, call function, return, implicit drop (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::progress_handler::call_boxed_closure()`: `if let Ok(true)`, else return `c_int` (uncontrolled, unsound!)  
> `rusqlite::inner_connection::InnerConnection::rollback_hook::call_boxed_closure()`: `drop` (uncontrolled, unsound!)  
> `rusqlite::session::call_conflict()`: `if let Ok(action)`, else return `c_int` (uncontrolled, unsound!)  
> `rusqlite::session::call_filter()`: `if let Ok(true)`, else return `c_int` (uncontrolled, unsound!)  
> `rusqlite::session::Session::table_filter::call_boxed_closure()`: `if let Ok(true)`, else return `c_int` (uncontrolled, unsound!)  
> `rusqlite::trace::config_log()`: `drop` (uncontrolled, unsound!)  
> `rusqlite::unlock_notify::unlock_notify_cb()`: `drop` (impossible)
> 
> rustc-rayon v0.4.0 ([https://github.com/rust-lang/rustc-rayon/tree/v0.4.0](https://github.com/rust-lang/rustc-rayon/tree/v0.4.0)):  
> `rustc_rayon::job::JobImpl::run_result()`/`rustc_rayon::job::JobImpl::into_result()`: `match Err(x)`, move into field, cross boundary, `resume_unwind`
> 
> rustc-rayon-core v0.4.1 ([https://github.com/rust-lang/rustc-rayon/tree/e70e468c72fc6832f53ed3fbe88bd24d77f7ccb9/rayon-core](https://github.com/rust-lang/rustc-rayon/tree/e70e468c72fc6832f53ed3fbe88bd24d77f7ccb9/rayon-core)):  
> `<rustc_rayon_core::job::StackJob as Job>::execute()`/`rustc_rayon_core::job::JobResult::into_return_value()`: `match Err(x)`, move into field, cross boundary, `resume_unwind`  
> `rustc_rayon_core::join::join_context()`/`rustc_rayon_core::join::join_recover_from_panic()`: `match Err(err)`, call indep. function, `resume_unwind`  
> `rustc_rayon_core::scope::ScopeBase::execute_job_closure()`/`rustc_rayon_core::scope::ScopeBase::job_panicked()`/`rustc_rayon_core::scope::ScopeBase::maybe_propagate_panic()`: `match Err(err)`, move into field, cross boundary, `resume_unwind` (incidentally unsound?)  
> `rustc_rayon_core::spawn::spawn_job()`/`rustc_rayon_core::registry::Registry::handle_panic()`: `match Err(err)`, move into function (abort on panic) OR abort  
> `rustc_rayon_core::ThreadPoolBuilder::build_scoped()`: call indep. function, `match Err(err)`, `resume_unwind`  
> `rustc_rayon_core::registry::main_loop()`/`rustc_rayon_core::registry::Registry::handle_panic()`: create `AbortIfPanic` guard, `match Err(err)`, move into trait function, `forget` guard
> 
> rustler v0.25.0 ([https://github.com/rusterlium/rustler/tree/rustler-0.25.0/rustler](https://github.com/rusterlium/rustler/tree/rustler-0.25.0/rustler)):  
> `rustler::thread::spawn()`: `match Err(err)`, call functions with ref, implicit drop (uncontrolled, unsound?)
> 
> rustler\_codegen v0.25.0 ([https://github.com/rusterlium/rustler/tree/rustler-0.25.0/rustler\_codegen](https://github.com/rusterlium/rustler/tree/rustler-0.25.0/rustler_codegen)):  
> `rustler_codegen::nif::transcoder_decorator::<#name as Nif>::RAW_FUNC::nif_func::wrapper()`/`rustler::codegen_runtime::handle_nif_result()`: `match Err(err)`, `downcast`, `match Err(_)`, return `NifReturned`, implicit drop (uncontrolled, unsound!)
> 
> rustls-ffi v0.9.1 ([https://github.com/rustls/rustls-ffi/tree/v0.9.1](https://github.com/rustls/rustls-ffi/tree/v0.9.1)):  
> `rustls_ffi::panic::ffi_panic_boundary!`: `match Err(_)`, return error, implicit drop (uncontrolled, unsound?)
> 
> rusty-fork v0.3.0 ([https://github.com/AltSysrq/rusty-fork/tree/0.3.0](https://github.com/AltSysrq/rusty-fork/tree/0.3.0)):  
> `rusty_fork::fork::fork_impl()`: `match Err(_)`, `exit`
> 
> rutie-serde v0.3.0 ([https://github.com/deliveroo/rutie-serde/tree/0.3.0](https://github.com/deliveroo/rutie-serde/tree/0.3.0)):  
> `rutie_serde::panics::catch_and_raise()`: `match Err(_)`, call functions, call nonreturning function, `unreachable!()`
> 
> safe-proc-macro2 v1.0.36 ([https://gitlab.com/leonhard-llc/safe-regex-rs/-/tree/safe-proc-macro2-v1.0.36/safe-proc-macro2](https://gitlab.com/leonhard-llc/safe-regex-rs/-/tree/safe-proc-macro2-v1.0.36/safe-proc-macro2)):  
> `safe_proc_macro2::detection::initialize()`: `is_ok`, implicit drop (controlled)  
> `safe_proc_macro2::wrapper::proc_macro_parse()`: `unwrap_or_else(|_|)`, return `Result`, implicit drop (controlled)
> 
> sc-executor v0.9.0 ([https://github.com/paritytech/substrate/tree/v3.0.0/client/executor](https://github.com/paritytech/substrate/tree/v3.0.0/client/executor)):  
> `sc_executor::native_executor::with_externalities_safe()`: `map_err(|e|)`, call functions with ref, return `Error`, implicit drop (uncontrolled!)
> 
> sc-executor-wasmtime v0.9.0 ([https://github.com/paritytech/substrate/tree/v3.0.0/client/executor/wasmtime](https://github.com/paritytech/substrate/tree/v3.0.0/client/executor/wasmtime)):  
> `sc_executor_wasmtime::imports::call_static()`/`sc_executor_wasmtime::imports::stringify_panic_payload()`: `match Err(err)`, attempt to `downcast`, implicit drop (uncontrolled!)
> 
> sc-service v0.9.0 ([https://github.com/paritytech/substrate/tree/v3.0.0/client/service](https://github.com/paritytech/substrate/tree/v3.0.0/client/service)):  
> `sc_service::task_manager::SpawnTaskHandle::spawn_inner()`: `match Err(payload)`, call indep. function, `resume_unwind`
> 
> scheduled-thread-pool v0.2.6 ([https://github.com/sfackler/scheduled-thread-pool/tree/v0.2.6](https://github.com/sfackler/scheduled-thread-pool/tree/v0.2.6)):  
> `scheduled_thread_pool::Worker::run()`: `let _` (uncontrolled, sound)
> 
> security-framework v2.6.1 ([https://github.com/kornelski/rust-security-framework/tree/v2.6.1/security-framework](https://github.com/kornelski/rust-security-framework/tree/v2.6.1/security-framework)):  
> `security_framework::secure_transport::read_func()`/`security_framework::secure_transport::SslStream::check_panic()`: `match Err(e)`, move into field, cross boundary, `resume_unwind``security_framework::secure_transport::write_func()`/`security_framework::secure_transport::SslStream::check_panic()`: `match Err(e)`, move into field, cross boundary, `resume_unwind`
> 
> sentry-core v0.27.0 ([https://github.com/getsentry/sentry-rust/tree/0.27.0/sentry-core](https://github.com/getsentry/sentry-rust/tree/0.27.0/sentry-core)):  
> `sentry_core::hub::Hub::run()`: call indep. functions, `match Err(err)`, `resume_unwind`
> 
> serial\_test v0.8.0 ([https://github.com/palfrey/serial\_test/tree/v0.8.0/serial\_test](https://github.com/palfrey/serial_test/tree/v0.8.0/serial_test)):  
> `serial_test::parallel_code_lock::local_async_parallel_core()`: call indep. function, `if let Err(err)`, `resume_unwind`  
> `serial_test::parallel_code_lock::local_async_parallel_core_with_return()`: call indep. function, `match Err(err)`, `resume_unwind`  
> `serial_test::parallel_code_lock::local_parallel_core()`: call indep. function, `if let Err(err)`, `resume_unwind`  
> `serial_test::parallel_code_lock::local_parallel_core_with_return()`: call indep. function, `match Err(err)`, `resume_unwind`  
> `serial_test::parallel_file_lock::fs_async_parallel_core()`: call indep. function, `if let Err(err)`, `resume_unwind`  
> `serial_test::parallel_file_lock::fs_async_parallel_core_with_return()`: call indep. function, `match Err(err)`, `resume_unwind`  
> `serial_test::parallel_file_lock::fs_parallel_core()`: call indep. function, `if let Err(err)`, `resume_unwind`  
> `serial_test::parallel_file_lock::fs_parallel_core_with_return()`: call indep. function, `match Err(err)`, `resume_unwind`
> 
> sled v0.34.7 ([https://github.com/spacejam/sled/tree/v0.34.7](https://github.com/spacejam/sled/tree/v0.34.7)):  
> `sled::threadpool::spawn_new_thread()`: set indep. global, if `is_err`, call function with ref, set indep. global, return, implicit drop (uncontrolled, sound)
> 
> smbc v0.1.0 ([https://github.com/smbc-rs/smbc/tree/f12958560d6179b10eb0f91971ca0c13c8b01aa8](https://github.com/smbc-rs/smbc/tree/f12958560d6179b10eb0f91971ca0c13c8b01aa8)):  
> `smbc::smbc::SmbClient::auth_wrapper()`: `unwrap_or`, return default values (uncontrolled, unsound!)
> 
> smol v1.2.5 ([https://github.com/smol-rs/smol/tree/v1.2.5](https://github.com/smol-rs/smol/tree/v1.2.5)):  
> `smol::spawn::spawn()`: `ok` (uncontrolled!)
> 
> sp-state-machine ([https://github.com/paritytech/substrate/tree/d14784fee8eddead26efc8617c512cc8775bfde5/primitives/state-machine](https://github.com/paritytech/substrate/tree/d14784fee8eddead26efc8617c512cc8775bfde5/primitives/state-machine)):  
> `sp_state_machine::testing::TestExternalities::execute_with_safe()`: `map_err(|e|)`, call function with ref, return `String`, implicit drop (controlled)
> 
> sp-tasks v3.0.0 ([https://github.com/paritytech/substrate/tree/v3.0.0/primitives/tasks](https://github.com/paritytech/substrate/tree/v3.0.0/primitives/tasks)):  
> `sp_tasks::inner::spawn()`: `match Err(panic)`, call function with ref, return, implicit drop (uncontrolled!)
> 
> ssi v0.4.0 ([https://github.com/spruceid/ssi/tree/v0.4.0](https://github.com/spruceid/ssi/tree/v0.4.0)):  
> `ssi::jws::verify_bytes_warnable()`: `map_err(|e|)`, return indep. `Error`, implicit drop (controlled)
> 
> stacker v0.1.14 ([https://github.com/rust-lang/stacker/tree/stacker-0.1.14](https://github.com/rust-lang/stacker/tree/stacker-0.1.14)):  
> `stacker::_grow()`: `err`, cross boundary, call indep. function, `if let Some(p)`, `resume_unwind`  
> `stacker::fiber_proc()`/`stacker::_grow()`: `err`, move into field, cross boundary, call indep. functions, `if let Some(p)`, `resume_unwind`
> 
> static\_init v1.0.2 ([https://gitlab.com/okannen/static\_init/-/tree/6f2b42eed0015f394998482f5b28eb18395f39d2](https://gitlab.com/okannen/static_init/-/tree/6f2b42eed0015f394998482f5b28eb18395f39d2)):  
> `static_init::generic_lazy::may_debug()`: `match Err(x)`, if `is::<CyclicPanic>`, `panic!()`, else `resume_unwind`
> 
> steamworks v0.9.0 ([https://github.com/Noxime/steamworks-rs/tree/v0.9.0](https://github.com/Noxime/steamworks-rs/tree/v0.9.0)):  
> `steamworks::networking_types::free_rust_message_buffer()`: `if let Err(e)`, call function with ref, implicit drop (impossible, incidentally unsound!)  
> `steamworks::utils::c_warning_callback()`: `if let Err(err)`, call functions with ref, `abort`
> 
> take\_mut v0.2.2 ([https://github.com/Sgeo/take\_mut/tree/v0.2.2](https://github.com/Sgeo/take_mut/tree/v0.2.2)):  
> `take_mut::scoped::scope()`: call indep. function, `abort` OR (`match Err(p)`, `resume_unwind`)  
> `take_mut::take()`: `unwrap_or_else(|_|)`, `abort`  
> `take_mut::take_or_recover()`: `match Err(err)`, call indep. functions, `resume_unwind`; `unwrap_or_else(|_|)`, `abort`
> 
> temp-env v0.2.0 ([https://github.com/vmx/temp-env/tree/v0.2.0](https://github.com/vmx/temp-env/tree/v0.2.0)):  
> `temp_env::with_vars()`: `match Err(err)`, call indep. functions, `resume_unwind`
> 
> test-context-macros v0.1.1 ([https://github.com/markhildreth/test-context/tree/v0.1.1/macros](https://github.com/markhildreth/test-context/tree/v0.1.1/macros)):  
> `test_context_macros::test_context()`: call indep. function, `match Err(err)`, `resume_unwind`
> 
> tester v0.9.0 ([https://github.com/messense/rustc-test/tree/v0.9.0](https://github.com/messense/rustc-test/tree/v0.9.0)):  
> `tester::bench::benchmark()`: call indep. function, `match Err(_)`, return `TestResult`, implicit drop (uncontrolled, sound)  
> `tester::run_test_in_process()`: call indep. functions, `match Err(e)`, call function with ref, implicit drop (uncontrolled, sound)
> 
> thread-pool v0.1.1 ([https://github.com/carllerche/thread-pool/tree/4f3599617fc14a7d83b4f936ceca99d7af98a6eb](https://github.com/carllerche/thread-pool/tree/4f3599617fc14a7d83b4f936ceca99d7af98a6eb)):  
> `thread_pool::thread_pool::Worker::run()`: `let _` (uncontrolled!)
> 
> tokio v1.19.2 ([https://github.com/tokio-rs/tokio/tree/tokio-1.19.2/tokio](https://github.com/tokio-rs/tokio/tree/tokio-1.19.2/tokio)):  
> `tokio::runtime::task::harness::cancel_task()`: `match Err(panic)`, move into field  
> `tokio::runtime::task::harness::Harness::complete()`: `let _` (uncontrolled!)  
> `tokio::runtime::task::harness::Harness::drop_join_handle_slow()`: `let _` (uncontrolled!)  
> `tokio::runtime::task::harness::poll_future()`: `match Err(panic)`, move into `Result`, move into field; `let _` (controlled?)  
> `tokio::signal::reusable_box::ReusableBoxFuture::set_same_layout()`: call indep. functions, `match Err(payload)`, `resume_unwind`  
> `tokio::sync::task::atomic_waker::AtomicWaker::do_register()`: `match Err(panic)`, move into `Option`, call functions with `is_some`, `if let Some(panic)`, `resume_unwind`; `let _` (uncontrolled!); `let _` (uncontrolled!)  
> `tokio::sync::watch::Sender::send_if_modified()`: `match Err(panicked)`, call indep. function, `resume_unwind`
> 
> tokio-threadpool v0.1.17 ([https://github.com/tokio-rs/tokio/tree/tokio-threadpool-0.1.17/tokio-threadpool](https://github.com/tokio-rs/tokio/tree/tokio-threadpool-0.1.17/tokio-threadpool)):  
> `tokio_threadpool::task::Task::run()`: `match Err(_)`, call functions, return `Run`, implicit drop (uncontrolled!)
> 
> tokio-unix-ipc v0.2.0 ([https://github.com/mitsuhiko/tokio-unix-ipc/tree/0.2.0](https://github.com/mitsuhiko/tokio-unix-ipc/tree/0.2.0)):  
> `tokio_unix_ipc::panic::catch_panic()`: `match Err(panic)`, call function with ref, return `Result`, implicit drop (uncontrolled!)
> 
> tower-http v0.3.4 ([https://github.com/tower-rs/tower-http/tree/tower-http-0.3.4/tower-http](https://github.com/tower-rs/tower-http/tree/tower-http-0.3.4/tower-http)):  
> `<tower_http::catch_panic::CatchPanic as Service<Request<_>>>::call()`/`<tower_http::catch_panic::ResponseFuture as Future>::poll()`: return `Result`
> 
> tracing-gstreamer v0.3.2 ([https://github.com/standard-ai/tracing-gstreamer/tree/v0.3.2](https://github.com/standard-ai/tracing-gstreamer/tree/v0.3.2)):  
> `tracing_gstreamer::log::log_callback()`: `unwrap_or_else(|_e|)`, `abort`
> 
> trybuild v1.0.63 ([https://github.com/dtolnay/trybuild/tree/1.0.63](https://github.com/dtolnay/trybuild/tree/1.0.63)):  
> `trybuild::diff::r#impl::Diff::compute()`: `ok`, `?` (controlled)
> 
> twinstar v0.4.0 ([https://github.com/panicbit/twinstar/tree/v0.4.0](https://github.com/panicbit/twinstar/tree/v0.4.0)):  
> `twinstar::Server::serve_client()`: `unwrap_or_else(|_|)`, return `Response`, implicit drop (uncontrolled!)
> 
> two-rusty-forks v0.4.0 ([https://github.com/inikulin/two-rusty-forks/tree/9346a869dab75ce6dad915b088231b4911ef1d99](https://github.com/inikulin/two-rusty-forks/tree/9346a869dab75ce6dad915b088231b4911ef1d99)):  
> `two_rusy_forks::fork::fork_impl()`: `match Err(_)`, `exit`
> 
> uppercut v0.4.0 ([https://github.com/sergey-melnychuk/uppercut/tree/0.4](https://github.com/sergey-melnychuk/uppercut/tree/0.4)):  
> `uppercut::core::worker_loop()`: if `is_err`, `err`, `unwrap`, move into user-supplied trait method, default implicit drop (uncontrolled!)
> 
> vapoursynth v0.3.0 ([https://github.com/YaLTeR/vapoursynth-rs/tree/v0.3.0/vapoursynth](https://github.com/YaLTeR/vapoursynth-rs/tree/v0.3.0/vapoursynth)):  
> `vapoursynth::api::API::add_message_handler::c_callback()`: if `is_err`, `abort`  
> `vapoursynth::api::API::add_message_handler_trivial::c_callback()`: if `is_err`, call indep. function, `abort` (incidentally unsound!)  
> `vapoursynth::api::API::set_message_handler::c_callback()`: if `is_err`, `abort`  
> `vapoursynth::api::API::set_message_handler_trivial::c_callback()`: if `is_err`, call indep. function, `abort` (incidentally unsound!)  
> `vapoursynth::node::Node::get_frame_async::c_callback()`: if `is_err`, `abort`  
> `vapoursynth::plugins::ffi::create()`: if `is_err`, `abort`  
> `vapoursynth::plugins::ffi::export_vapoursynth_plugin!::VapourSynthPluginInit()`: if `is_err`, `abort`  
> `vapoursynth::plugins::ffi::free()`: if `is_err`, `abort`  
> `vapoursynth::plugins::ffi::get_frame()`: `match Err(_)`, `abort`  
> `vapoursynth::plugins::ffi::init()`: if `is_err`, call indep. functions, implicit drop (uncontrolled, unsound!); if `is_err`, `abort`
> 
> wasmer v2.3.0 ([https://github.com/wasmerio/wasmer/tree/2.3.0/lib/api](https://github.com/wasmerio/wasmer/tree/2.3.0/lib/api)):  
> `<wasmer_vm::VMDynamicFunctionContext as VMDynamicFunctionCall<_>>::func_wrapper()`/`wasmer_vm::trap::traphandlers::resume_panic()`/`wasmer_fm::trap::traphandlers::unwind_with()`/`wasmer_fm::trap::traphandlers::UnwindReason::to_trap()`: `match Err(panic)`, move into `UnwindReason`, cross boundary, `resume_unwind`  
> `wasmer::js::externals::function::inner::impl_host_function!::HostFunction::function_body_pointer::func_wrapper()`: `match _`, `unimplemented!()`  
> `wasmer::sys::externals::function::inner::impl_host_function!::HostFunction::function_body_ptr()`/`wasmer_vm::trap::traphandlers::resume_panic()`/`wasmer_fm::trap::traphandlers::unwind_with()`/`wasmer_fm::trap::traphandlers::UnwindReason::to_trap()`: `match Err(panic)`, move into `UnwindReason`, cross boundary, `resume_unwind`  
> `wasmer::sys::native::impl_native_traits!::NativeFunc::call()`: `map_err(|e|)`, call function with ref, return `RuntimeError`, implicit drop (uncontrolled, unsound?)
> 
> wasmer-runtime-core v0.17.1 ([https://github.com/wasmerio/wasmer/tree/0.17.1/lib/runtime-core](https://github.com/wasmerio/wasmer/tree/0.17.1/lib/runtime-core)):  
> `wasmer_runtime_core::typed_func::DynamicFunc::new::do_enter_host_polymorphic()`/`wasmer_runtime_core::tiering::run_tiering()`: `match Err(e)`, move into `RuntimeError`, cross boundary, `if let Err(e)`, `match _`, return `Result`, implicit drop (uncontrolled!)  
> `wasmer_runtime_core::typed_func::impl_traits!::HostFunction::to_raw::wrap()`/`wasmer_runtime_core::tiering::run_tiering()`: `match Err(err)`, move into `RuntimeError`, cross boundary, `if let Err(e)`, `match _`, return `Result`, implicit drop (uncontrolled!)
> 
> wayland-client v0.29.4 ([https://github.com/Smithay/wayland-rs/tree/39a24803925a6831959229e85faffdab39552a61/wayland-client](https://github.com/Smithay/wayland-rs/tree/39a24803925a6831959229e85faffdab39552a61/wayland-client)):  
> `wayland_client::native_lib::proxy::proxy_dispatcher()`: `match Err(_)`, call function, `libc::abort`
> 
> webview2 v0.1.4 ([https://github.com/sopium/webview2/tree/v0.1.4](https://github.com/sopium/webview2/tree/v0.1.4)):  
> `webview2::callback!::<Impl as $name>::invoke()`: `match Err(_)`, call indep. function, `abort` (incidentally unsound!)
> 
> winit v0.26.1 ([https://github.com/rust-windowing/winit/tree/v0.26.1](https://github.com/rust-windowing/winit/tree/v0.26.1)):  
> `winit::platform_impl::macos::event_loop::stop_app_on_panic()`/`winit::platform_impl::macos::event_loop::EventLoop::run_return()`: `match Err(e)`, move into `Rc`, call indep. functions, cross boundary, `if let Some(panic)`, call indep. function, `resume_unwind`  
> `winit::platform_impl::windows::event_loop::runner::EventLoopRunner::catch_unwind()`: on condition call indep. function, return `Option`, implicit drop (uncontrolled, unsound!)
> 
> with\_locals-proc\_macros v0.3.0 ([https://github.com/danielhenrymantilla/with\_locals.rs/tree/v0.3.0/src/proc\_macros](https://github.com/danielhenrymantilla/with_locals.rs/tree/v0.3.0/src/proc_macros)):  
> `with_locals_proc_macros::handle_let_bindings::handle_let_bindings()`: `if let Err(panic)`, (return `Result`, implicit drop) OR `resume_unwind` (controlled)  
> `with_locals_proc_macros::wrap_statements_inside_closure_body::wrap_statements_inside_closure_body()`: `if let Err(panic)`, (return `Result`, implicit drop) OR `resume_unwind` (controlled)
> 
> wstp v0.2.2 ([https://github.com/WolframResearch/wstp-rs/tree/v0.2.2](https://github.com/WolframResearch/wstp-rs/tree/v0.2.2)):  
> `wstp::wait::link_wait_callback_trampoline()`: `match Err(_)`, return `i32`, implicit drop (uncontrolled, unsound!)

* * *

**TL;DR: `catch_unwind()` is a horrible interface for preventing unwinding.** It works well when paired with `resume_unwind()` or when followed by `abort()`, but nearly every crate that handles it otherwise ends up leaking panics from dropping the payload. Something like `drop_err_or_{forget, abort}()` would be a safe and reasonable behavior (IMHO), but no currently widespread crate implements that logic.

Regarding `UnwindResult`, crates often move a value or access a mutable reference depending on whether a panic occurred. `inspect_err()` is insufficient to handle this, so `into_result()` would probably be more commonly used than I initially expected. Also, a very frequent pattern is to ignore the result and just to extract the payload for later. Therefore, it would likely need an `err()` method, with the same footgun warnings as `into_result()`:

```rust
impl<T> UnwindResult<T> {
    // If there is a payload, return it; otherwise, return `None`. Be careful
    // when dropping it.
    pub fn err(self) -> Option<Box<dyn Any + Send>>;
}

```

---

_[View the full topic](https://internals.rust-lang.org/t/some-thoughts-on-a-less-slippery-catch-unwind/16902)._
