pub fn catch_condition<T>(f: impl FnOnce() -> T) -> Result<T, RCondition>Expand description
Run f, returning a condition raised inside it as Err instead of
letting it reach R; any other unwind carries on.
For a body that turns another function’s failure into its own result: a refusal that names the reason, a fallback, a retry.
use miniextendr_api::condition::catch_condition;
match catch_condition(|| rebuild(&snapshot)) {
Ok(object) => object,
Err(cause) => error!(
class = "pkg_error_rebuild",
data = ("cause", cause.message().to_string()),
"cannot rebuild the object: {}", cause.message()
),
}Caught: every RCondition payload, with its kind, classes, data
and call choice: error! / rust_error!,
warning!, message!,
condition!, RCondition::raise, the argument and
conversion errors (RCondition::arg_error) and the ExternalPtr type
errors. An Err can be raised again with RCondition::raise or queued
with RCondition::defer.
Resumed unchanged, with std::panic::resume_unwind:
- an R error, interrupt or other R exit crossing the Rust frames (R code
run through
with_r_unwind_protectoreval_with_handlers), so R carries on to the context it was jumping to; - a plain
panic!()or any other payload, which still becomes an R error at the boundary, with its source location.
Use try_eval_with_handlers
to get an R error back as a value.
Deferred conditions queued inside f stay queued (see
deferred_condition::capture). A
caught raise still runs the panic hook: with MINIEXTENDR_BACKTRACE=true
it prints the panic to stderr.
Generated #[miniextendr(worker)] wrappers run the body through it on the
worker thread: the payload is Send, so it crosses back to the main
thread as a value and is raised there with its class, data and call kept.