macro_rules! arg_error {
(@param $call:expr; call $($rest:tt)*) => { ... };
(@param $call:expr; param = $param:expr, call $($rest:tt)*) => { ... };
(@param $call:expr; param = $param:expr, class $($rest:tt)*) => { ... };
(@param $call:expr; param = $param:expr, data $($rest:tt)*) => { ... };
(@param $call:expr; param = $param:expr, $($arg:tt)+) => { ... };
(@param $call:expr; $($rest:tt)*) => { ... };
(@no_class_or_data) => { ... };
(call = none, $($rest:tt)*) => { ... };
(call $($rest:tt)*) => { ... };
($($rest:tt)*) => { ... };
}Expand description
Raise the argument error the generated R wrapper raises for a bad
argument, from a #[miniextendr] function body.
arg_error!(param = "mode", "'mode' should be one of {}", choices) raises
the condition of the wrapper’s own argument checks (match_arg,
inherits, no_na, type preconditions) and of a failed argument
conversion: kind = "conversion", e$param set to param (the
argument’s R name), the message as formatted, and the crate’s
conversion_error_class ([package.metadata.miniextendr]) before the
rust_error layering:
class(e)
# [1] "pkg_error_argument" "pkg_error" "rust_error" "simpleError" "error" "condition"Use it for a check that applies on some paths only, where a
#[miniextendr] attribute on the parameter would check every call: an
argument passed on to another function’s body, say, which skips that
function’s R wrapper and its checks. crate::match_arg_param matches a
raw choice argument with the wrapper’s semantics and message and raises
through this macro.
It diverges like crate::error! (the same panic_any transport), and
conditions queued with crate::defer_warning! & co. are signalled first.
The call is the one the wrapper’s checks report: the wrapper’s call as
written, or under #[miniextendr(call = caller)] its caller’s. A leading
call = none raises it without a call, as for the other condition macros.
There is no class = or data =: the classes are the crate’s and the only
field is param, so the condition is the wrapper’s.
use miniextendr_api::{arg_error, miniextendr};
#[miniextendr]
pub fn in_metres(x: f64, unit: &str) -> f64 {
match unit {
"m" => x,
"cm" => x / 100.0,
_ => arg_error!(param = "unit", "'unit' should be one of \"m\", \"cm\""),
}
}§How the crate’s classes get there
A macro_rules! macro cannot read [package.metadata.miniextendr], so the
tagged condition value carries the marker class
CONVERSION_ERROR_CLASS_MARKER
and the generated wrapper’s .miniextendr_raise_condition replaces it with
.miniextendr_conversion_error_class, the binding its own checks use. Across
a trait-ABI call the consumer package’s wrapper raises the condition, so
its crate’s classes apply. A raising guard (an ALTREP RUnwind callback,
with_r_unwind_protect_or_raise) has no generated R: it resolves the
marker in Rust against the classes miniextendr_init! registered (on
wasm32, the copy in the wasm_registry.rs snapshot), then raises the same
condition, kind = "conversion" included (#1768). A connection callback
returns its fallback, as for any panic.
The generated no_na check after a conversion builds the same condition
with crate::error_value::arg_check_condition_value, which takes the
classes the macro read at expansion time.
§Grammar
arg_error!([call = none,] param = <expr>, <format string>, <args>...).
param is anything Into<String>. A call anywhere but first, a repeated
one, a missing param, and class = / data = are compile errors:
mx::arg_error!(param = "mode", call = none, "bad");mx::arg_error!("'mode' is bad");mx::arg_error!(param = "mode", class = "pkg_error", "bad");mx::arg_error!(call = none, param = "mode", "'mode' is {mode:?}")