Skip to main content

REvalError

Struct REvalError 

Source
pub struct REvalError {
    message: String,
    classes: Vec<String>,
    roots: Preserved,
}
Expand description

An R error caught by RCall::eval / RCall::eval_base, r_eval_str, the helpers built on them (REnv::package_namespace, RCall::namespaced, dollar_extract), and try_eval_with_handlers / RCall::try_eval_with_handlers.

It holds R’s condition object, rooted while this value lives, and what R reports about it:

  • message: conditionMessage(cond), the text R prints after Error in <call> :, without that prefix and without the Calls: traceback line of a non-interactive session;
  • call: conditionCall(cond), None when it is NULL;
  • classes: the class vector, most specific first;
  • condition: the condition object itself.

Display writes the message alone. Every value holds a condition: a parse failure in r_eval_str and an evaluation under RCall::eval that jumps to the top level without an error (an interrupt) come back as a simpleError built for them, with no call.

§Raising your own condition with it

The condition macros take the message through Display, and reraise_class puts the package’s own classes ahead of the caught ones:

ⓘ
use miniextendr_api::rust_error;

match RCall::new("print").arg(x).named_arg("na.print", na).eval_base() {
    Ok(_) => {}
    // The package's own class with R's message:
    //   class = "pkg_print_error"
    // or with the caught classes kept after it, so a handler for those
    // still matches:
    Err(e) => rust_error!(class = e.reraise_class("pkg_print_error"), "{e}"),
}

reraise raises the caught condition itself instead, as R raised it.

A #[miniextendr] function returning Result<T, REvalError> raises the caught message with the caught specific classes (REvalError implements RConditionData). For a Result<T, condition::RError> return, RError::from(e) takes the message (it is a std::error::Error) and .class(...) adds the classes.

§Threads

!Send + !Sync: dropping the value releases its root on R’s precious list, which is R main-thread state, and condition / call hand out SEXPs. To carry the failure to another thread or into a Send error type (anyhow::Error, Box<dyn Error + Send>), take message or convert into condition::RError.

Fields§

§message: String

conditionMessage(cond).

§classes: Vec<String>

class(cond).

§roots: Preserved

list(cond, call), on R’s precious list while this value lives, where call is conditionCall(cond) or NULL (see REvalError::call). Its handle makes the value !Send + !Sync, see the type docs.

Implementations§

Source§

impl REvalError

Source

pub fn message(&self) -> &str

The condition’s message (conditionMessage(cond)), without R’s Error in <call> : prefix and Calls: line.

Source

pub fn call(&self) -> Option<SEXP>

The condition’s call (conditionCall(cond)), None when it is NULL.

Also None for an error raised at the top of the evaluated expression (stop() called directly rather than from a function): R gives such an error the call of the tryCatch() frame the evaluation runs in, doTryCatch(return(expr), name, parentenv, handler), which is no call of the evaluated code. The condition object keeps what R recorded.

The SEXP is rooted while this value lives; protect it to keep it longer.

Source

pub fn classes(&self) -> &[String]

The condition’s class vector, most specific first: for stop("boom"), ["simpleError", "error", "condition"].

Source

pub fn inherits(&self, class: &str) -> bool

Whether the condition’s class vector contains class.

Source

pub fn specific_classes(&self) -> &[String]

The classes ahead of the base layers: the class vector without its trailing rust_error, simpleError, error and condition, which the condition macros add again. Empty for stop("boom"); ["my_class"] for stop(errorCondition("boom", class = "my_class")) or for a miniextendr function’s error!(class = "my_class", "boom").

Source

pub fn reraise_class(&self, own: impl ConditionClass) -> Vec<String>

The class vector for raising this error again as the package’s own condition: own first (one class or several, most specific first), then the caught specific classes not already in own.

ⓘ
// stop(errorCondition("boom", class = "vctrs_error")) caught as `e`:
rust_error!(class = e.reraise_class(["pkg_print_error", "pkg_error"]), "{e}");
// class: pkg_print_error, pkg_error, vctrs_error, rust_error,
//        simpleError, error, condition
Source

pub fn condition(&self) -> SEXP

The condition object.

The SEXP is rooted while this value lives; protect it to keep it longer.

Source

pub unsafe fn reraise(self) -> !

Raise the caught condition again, as R raised it: its classes, message and fields are unchanged, and its call is call. So an error raised at the top of the evaluated expression reports no call, not R’s doTryCatch(...) frame.

Use it for the errors a body doesn’t explain itself, next to a package’s own condition for the ones it does (Quoted::try_eval_in has an example). Unlike rust_error!(class = e.reraise_class(..), "{e}"), the condition gets no rust_error class and keeps R’s call, not the wrapper’s.

The condition is signalled by base stop(cond), evaluated as eval_with_handlers evaluates: the caller’s handlers see it, and the exit stops at that evaluation’s R_UnwindProtect frame and leaves as a Rust unwind. The frames up to the #[miniextendr] boundary drop their values, and the boundary hands the exit back to R, which goes on to the caller’s handler or to the top level. The same rules hold as for eval_with_handlers: don’t catch the unwind with std::panic::catch_unwind, and don’t call this from a Drop implementation.

§Safety

As eval_with_handlers: R’s main thread, inside a miniextendr boundary (a #[miniextendr] function body, a with_r_unwind_protect closure, …).

Source

unsafe fn from_condition(cond: SEXP) -> Self

Take a caught condition: read its classes, message and call, and root the condition with its call.

§Safety

R’s main thread; cond is rooted by the caller for the call.

Source

unsafe fn simple_error(message: &str) -> Self

A simpleError with message and no call, for a failure that raised no R condition (a parse failure, a jump to the top level, a result RCall::eval_as can’t read).

§Safety

R’s main thread.

Source

unsafe fn adopt( cond: SEXP, call: SEXP, message: String, classes: Vec<String>, ) -> Self

Root cond and call together for the value’s lifetime.

§Safety

R’s main thread; cond and call are rooted by the caller for the call.

Trait Implementations§

Source§

impl Debug for REvalError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for REvalError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for REvalError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
Source§

#[doc(hidden)]
fn type_id(&self, _: Internal) -> TypeId
where Self: 'static,

🔬This is a nightly-only experimental API. (error_type_id)
Gets the TypeId of self.
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl RConditionData for REvalError

Returned as a #[miniextendr] function’s Err, the caught error is raised again with its message and its specific classes, ahead of the rust_error layers; the call is the function’s own.

Source§

fn message(&self) -> String

The condition message (conditionMessage(e)).
Source§

fn class(&self) -> Vec<String>

User classes, most specific first; empty for none.
Source§

fn data(&self) -> Option<ConditionData>

Structured fields spliced into the condition object (e$<name>).
Source§

fn call(&self) -> ConditionCall

Whether the condition reports a call. ConditionCall::None makes conditionCall() NULL, like R’s call. = FALSE, for a condition about the data rather than the call; the default keeps the call the transport captured. Honoured by defer_* and by Result returns; an argument-conversion error always keeps the call (see conversion_err_parts). #[condition(call = none)] on a derived type or variant overrides this.
Source§

fn argument_message(&self) -> Option<String>

The whole message when this error refuses an argument, or None. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<E> ConversionArgMessageClassed for E
where E: RConditionData,

Source§

impl<E> ConversionErrClassed for E
where E: RConditionData,

Source§

fn __mx_conversion_parts(&self, _expected_known: bool) -> ErrParts

Source§

impl<E> ErrPartsClassed for E
where E: RConditionData,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> RDebug for T
where T: Debug,

Source§

fn debug_str(&self) -> String

Get a compact debug string representation.
Source§

fn debug_str_pretty(&self) -> String

Get a pretty-printed debug string with indentation.
Source§

#[doc(hidden)]
unsafe extern "C" fn __RDebug_debug_str_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RDebug,

Method shim for RDebug::debug_str. Read more
Source§

#[doc(hidden)]
unsafe extern "C" fn __RDebug_debug_str_pretty_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RDebug,

Method shim for RDebug::debug_str_pretty. Read more
Source§

impl<T> RDisplay for T
where T: Display,

Source§

fn as_r_string(&self) -> String

Convert to a user-friendly string.
Source§

#[doc(hidden)]
unsafe extern "C" fn __RDisplay_as_r_string_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RDisplay,

Method shim for RDisplay::as_r_string. Read more
Source§

impl<T> RError for T
where T: Error,

Source§

fn error_message(&self) -> String

Get the error message (Display representation).
Source§

fn error_chain(&self) -> Vec<String>

Get all error messages in the chain, from outermost to innermost.
Source§

fn error_chain_length(&self) -> i32

Get the number of errors in the chain.
Source§

#[doc(hidden)]
unsafe extern "C" fn __RError_error_message_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RError,

Method shim for RError::error_message. Read more
Source§

#[doc(hidden)]
unsafe extern "C" fn __RError_error_chain_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RError,

Method shim for RError::error_chain. Read more
Source§

#[doc(hidden)]
unsafe extern "C" fn __RError_error_chain_length_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RError,

Method shim for RError::error_chain_length. Read more
Source§

impl<T> SizeHint for T
where T: ?Sized,

Source§

default fn lower_bound(&self) -> usize

🔬This is a nightly-only experimental API. (core_io_internals)
Returns a lower bound on the number of elements this container-like item contains. For example, an array [u8; 12] could return any value between 0 and 12 inclusively as a correct implementation. Read more
Source§

default fn upper_bound(&self) -> Option<usize>

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an upper bound on the number of elements this container-like item contains if it can be determined, otherwise None. Read more
Source§

final fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an estimate for the number of elements this container like type contains. Read more
Source§

impl<T> SizedTypeProperties for T

Source§

#[doc(hidden)]
const SIZE: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGNMENT: Alignment = _

🔬This is a nightly-only experimental API. (ptr_alignment_type)
Source§

#[doc(hidden)]
const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
Source§

#[doc(hidden)]
const LAYOUT: Layout = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const MAX_SLICE_LEN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
The largest safe length for a [Self]. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 56 bytes