Skip to main content

catch_condition

Function catch_condition 

Source
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_protect or eval_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.