Skip to main content

raise_rust_condition_via_stop

Function raise_rust_condition_via_stop 

Source
pub(crate) unsafe fn raise_rust_condition_via_stop(
    tagged_value: impl FnOnce() -> SEXP,
    call: Option<SEXP>,
) -> !
Expand description

Raise the R condition for a tagged condition value by evaluating the shared .miniextendr_raise_condition helper on it, the helper every generated R wrapper calls on the value its .Call() returns.

This is Approach 3 from the issue-345 plan: an Rf_eval that ends in stop(structure(...)), for contexts with no outer R wrapper to inspect a tagged SEXP. It is the only viable option for ALTREP callbacks, which are invoked directly by R’s runtime (no .Call frame, no R wrapper).

tagged_value builds the value (with crate::error_value’s constructors). Because the helper raises it, the condition is the one the wrapper raises for the same value, field for field (#1768): message, call, kind, then the data = fields spliced with utils::modifyList, so a data field named message, call or kind replaces the base field on both transports (#1315); the classes ahead of the rust_* layering. The copy evaluated here lives in the base namespace, so the caller resolves arg_error!’s class marker in Rust first.

The value must be of an error kind (stop() longjmps, so this function never returns); the helper’s warning / message / condition arms return.

§Nothing Rust-owned survives the longjmp

The longjmp skips every Rust frame above R’s, so no destructor runs past this point. tagged_value consumes what it captures (message, classes, data) and is itself dropped before Rf_eval; the SEXPs are rooted with plain Rf_protect, whose stack R resets on the jump, rather than a drop guard that would never run.

§MXL300 compliance

This function raises an R error via Rf_eval(stop(...)), not via direct Rf_error/Rf_errorcall. MXL300 does not flag Rf_eval.

§Safety

Must be called from R’s main thread in a context where R longjmps are safe, with no Rust value that needs dropping left on the caller’s frames. In practice, always called from with_r_unwind_protect_sourced (ALTREP RUnwind guards, with_r_unwind_protect_or_raise) after its guarded closure has returned.