Skip to main content

miniextendr_macros/
c_wrapper_builder.rs

1//! Unified C wrapper generation for standalone functions and impl methods.
2//!
3//! This module provides shared infrastructure for generating C wrappers that:
4//! - Handle worker thread vs main thread execution strategies
5//! - Perform parameter conversion from SEXP to Rust types
6//! - Convert Rust return values back to SEXP
7//! - Properly handle panics and R errors
8//!
9//! The same infrastructure is used by both `#[miniextendr]` on standalone functions
10//! and `#[miniextendr(env|r6|s3|s4|s7)]` on impl blocks.
11
12use proc_macro2::TokenStream;
13use quote::{format_ident, quote};
14
15/// Thread execution strategy for C wrappers.
16#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ThreadStrategy {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ThreadStrategy::MainThread => "MainThread",
                ThreadStrategy::WorkerThread => "WorkerThread",
            })
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ThreadStrategy { }
#[automatically_derived]
impl ::core::clone::Clone for ThreadStrategy {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ThreadStrategy { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ThreadStrategy { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ThreadStrategy {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ThreadStrategy { }Eq)]
17pub enum ThreadStrategy {
18    /// Execute on main R thread with `with_r_unwind_protect`. **Default.**
19    ///
20    /// All code runs on R's main thread. Errors are returned as tagged SEXP values
21    /// (via `make_rust_condition_value`) and the R wrapper raises structured
22    /// condition objects. Simpler execution model with better R integration.
23    ///
24    /// Also required when:
25    /// - Function takes SEXP inputs (not Send)
26    /// - Function returns raw SEXP
27    /// - Instance method (self_ptr isn't Send)
28    /// - Function uses variadic dots (Dots type isn't Send)
29    /// - `#[miniextendr(check_interrupt)]` used
30    MainThread,
31
32    /// Execute on worker thread with panic catching. **Opt-in via `#[miniextendr(worker)]`.**
33    ///
34    /// Structure:
35    /// 1. Argument conversion on main thread
36    /// 2. Function execution on worker thread via `run_on_worker`
37    /// 3. SEXP conversion on main thread with `with_r_unwind_protect`
38    WorkerThread,
39}
40
41/// Strategy for converting a Rust return value into an R `SEXP`.
42///
43/// Determined automatically by [`detect_return_handling`] from the function's return type,
44/// or set explicitly via [`CWrapperContextBuilder::return_handling`]. Each variant
45/// handles a different return type pattern, controlling how the C wrapper converts
46/// the Rust value back to R and how errors/None values are surfaced.
47#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ReturnHandling {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ReturnHandling::Unit => "Unit",
                ReturnHandling::RawSexp => "RawSexp",
                ReturnHandling::ExternalPtr => "ExternalPtr",
                ReturnHandling::SelfHandle => "SelfHandle",
                ReturnHandling::SelfHandleResult => "SelfHandleResult",
                ReturnHandling::SelfHandleOption => "SelfHandleOption",
                ReturnHandling::IntoR => "IntoR",
                ReturnHandling::OptionUnit => "OptionUnit",
                ReturnHandling::OptionSexp => "OptionSexp",
                ReturnHandling::OptionIntoR => "OptionIntoR",
                ReturnHandling::OptionClassPayload => "OptionClassPayload",
                ReturnHandling::OptionExternalPtr => "OptionExternalPtr",
                ReturnHandling::ResultUnit => "ResultUnit",
                ReturnHandling::ResultSexp => "ResultSexp",
                ReturnHandling::ResultIntoR => "ResultIntoR",
                ReturnHandling::ResultNullOnErr => "ResultNullOnErr",
                ReturnHandling::ResultExternalPtr => "ResultExternalPtr",
                ReturnHandling::AsListOf => "AsListOf",
                ReturnHandling::AsExternalPtrOf => "AsExternalPtrOf",
                ReturnHandling::AsNativeOf => "AsNativeOf",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ReturnHandling {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Unit => ReturnHandling::Unit,
            Self::RawSexp => ReturnHandling::RawSexp,
            Self::ExternalPtr => ReturnHandling::ExternalPtr,
            Self::SelfHandle => ReturnHandling::SelfHandle,
            Self::SelfHandleResult => ReturnHandling::SelfHandleResult,
            Self::SelfHandleOption => ReturnHandling::SelfHandleOption,
            Self::IntoR => ReturnHandling::IntoR,
            Self::OptionUnit => ReturnHandling::OptionUnit,
            Self::OptionSexp => ReturnHandling::OptionSexp,
            Self::OptionIntoR => ReturnHandling::OptionIntoR,
            Self::OptionClassPayload => ReturnHandling::OptionClassPayload,
            Self::OptionExternalPtr => ReturnHandling::OptionExternalPtr,
            Self::ResultUnit => ReturnHandling::ResultUnit,
            Self::ResultSexp => ReturnHandling::ResultSexp,
            Self::ResultIntoR => ReturnHandling::ResultIntoR,
            Self::ResultNullOnErr => ReturnHandling::ResultNullOnErr,
            Self::ResultExternalPtr => ReturnHandling::ResultExternalPtr,
            Self::AsListOf => ReturnHandling::AsListOf,
            Self::AsExternalPtrOf => ReturnHandling::AsExternalPtrOf,
            Self::AsNativeOf => ReturnHandling::AsNativeOf,
        }
    }
}Clone)]
48pub enum ReturnHandling {
49    /// Returns unit type `()` -- emits `R_NilValue`.
50    Unit,
51    /// Returns raw `SEXP` -- passes the value through unchanged (no conversion).
52    RawSexp,
53    /// Returns `Self` -- wraps the value in an `ExternalPtr` via `ExternalPtr::new`.
54    ExternalPtr,
55    /// Returns `&Self` / `&mut Self` (an in-place builder) -- evaluates the call
56    /// for its side effect (the mutation already happened through `&mut self`),
57    /// discards the returned borrow, and returns the *same* `self_sexp` handle
58    /// unchanged. This gives R in-place value semantics with no clone: the R
59    /// object the user piped in is returned verbatim, wrapping the now-mutated
60    /// Rust value. Only valid for instance methods (requires `self_sexp`).
61    SelfHandle,
62    /// Fallible in-place step whose call expression yields `Result<(), E>`
63    /// (`&mut self -> Result<&mut Self, E>`, or `self -> Result<Self, E>` after
64    /// the write-back closure): raise on `Err`, return the same `self_sexp`
65    /// handle on `Ok` (#1432, #1433).
66    SelfHandleResult,
67    /// `Option` sibling of [`SelfHandleResult`](Self::SelfHandleResult): the
68    /// call yields `Option<()>`; `NULL` on `None`, as every `Option` return
69    /// gives, and the same handle on `Some`.
70    SelfHandleOption,
71    /// Returns an arbitrary type `T: IntoR` -- converts via `IntoR::into_sexp`.
72    IntoR,
73    /// Returns `Option<()>` -- raises an error on `None`, otherwise emits `R_NilValue`.
74    OptionUnit,
75    /// Returns `Option<SEXP>` -- raises an error on `None`, otherwise passes through.
76    OptionSexp,
77    /// Returns `Option<T>` -- calls `IntoR::into_sexp` on the whole `Option`, so `None`
78    /// becomes whatever `IntoR for Option<T>` gives: `NULL` for containers, references
79    /// and pointers, a typed `NA` for scalars. This is the one rule for an `Option<T>`
80    /// return from a standalone function, an inherent method and a trait method
81    /// (#1415, #2088); [`detect_return_handling`] picks it for every `Option<T>` but
82    /// the shapes below.
83    OptionIntoR,
84    /// Returns `Option<T>` under an explicit class wrap (`Option<WrapAs*<T>>` or
85    /// `wrap = "..."`): `Some` converts the class payload through `T: IntoR`, `None`
86    /// is `NULL`, as `IntoR for Option<T>` would give if it could exist (the orphan
87    /// rule refuses it in the class's crate). The R wrapper's class constructor lets
88    /// `NULL` through.
89    OptionClassPayload,
90    /// Returns `Option<Self>` -- a lookup-shaped fallible constructor (e.g. `try_find`).
91    /// A method-only shape: `Some(Self)` is wrapped in an `ExternalPtr` via
92    /// `ExternalPtr::new` (same as [`ExternalPtr`](Self::ExternalPtr)), since `Self`
93    /// generally has no `IntoR`, and the `Option<ExternalPtr<Self>>` converts as
94    /// any `Option` does: `None` is `NULL`. The R-side wrapper treats a non-`NULL`
95    /// value exactly like a bare `Self` return (wrapped class object via
96    /// `ReturnStrategy::for_method` — see `ParsedMethod::returns_option_self`).
97    OptionExternalPtr,
98    /// Returns `Result<(), E>` -- raises an error on `Err`, otherwise emits `R_NilValue`.
99    ResultUnit,
100    /// Returns `Result<SEXP, E>` -- raises an error on `Err`, otherwise passes through.
101    ResultSexp,
102    /// Returns `Result<T, E>` -- raises an error on `Err`, otherwise converts via `IntoR::into_sexp`.
103    ResultIntoR,
104    /// Returns `Result<T, ()>` -- maps `Err(())` to `Err(NullOnErr)` then converts via `IntoR`.
105    /// `None`/`Err` maps to R `NULL` (unit error is a deliberate sentinel, not a Rust failure).
106    ResultNullOnErr,
107    /// Returns `Result<Self, E>` -- a fallible constructor-shaped method (e.g. `from_r`,
108    /// `try_new`). Raises an error on `Err` (same as [`ResultIntoR`](Self::ResultIntoR)), but
109    /// wraps `Ok(Self)` in an `ExternalPtr` via `ExternalPtr::new` (same as
110    /// [`ExternalPtr`](Self::ExternalPtr)) instead of routing it through `IntoR` (which `Self`
111    /// generally does not implement). The R-side wrapper mirrors this: a successful return is
112    /// treated exactly like a bare `Self` return (wrapped class object via
113    /// `ReturnStrategy::for_method` — see `ParsedMethod::returns_result_self`).
114    ResultExternalPtr,
115    /// Returns `T` where `T: IntoList` -- wraps in `AsList(result)` then calls `IntoR::into_sexp`.
116    ///
117    /// Produced when `#[miniextendr(prefer = "list")]` is used on a function returning `T: IntoList`.
118    /// Distinct from returning `AsList<T>` explicitly only in that the wrapping is generated
119    /// by the macro rather than written by the user.
120    AsListOf,
121    /// Returns `T` where `T: IntoExternalPtr` -- wraps in `AsExternalPtr(result)` then calls `IntoR::into_sexp`.
122    ///
123    /// Produced when `#[miniextendr(prefer = "externalptr")]` is used on a function returning
124    /// `T: IntoExternalPtr`. Distinct from the existing `ExternalPtr` variant (which boxes `Self`
125    /// via `ExternalPtr::new`): this variant calls `IntoExternalPtr::into_external_ptr()` on `T`.
126    AsExternalPtrOf,
127    /// Returns `T` where `T: RNativeType` -- wraps in `AsRNative(result)` then calls `IntoR::into_sexp`.
128    ///
129    /// Produced when `#[miniextendr(prefer = "native")]` is used on a function returning `T: RNativeType`.
130    AsNativeOf,
131}
132
133/// How the generated `Err` arm turns an error value into condition parts
134/// (message, class vector, structured data).
135#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErrPartsMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Probe { prefix: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Probe",
                    "prefix", &__self_0),
            Self::Serde { prefix: __self_0, spec: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Serde",
                    "prefix", __self_0, "spec", &__self_1),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ErrPartsMode {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Probe { prefix: __self_0 } =>
                ErrPartsMode::Probe {
                    prefix: ::core::clone::Clone::clone(__self_0),
                },
            Self::Serde { prefix: __self_0, spec: __self_1 } =>
                ErrPartsMode::Serde {
                    prefix: ::core::clone::Clone::clone(__self_0),
                    spec: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for ErrPartsMode { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ErrPartsMode {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Probe { prefix: __self_0 }, Self::Probe {
                    prefix: __arg1_0 }) => __self_0 == __arg1_0,
                (Self::Serde { prefix: __self_0, spec: __self_1 },
                    Self::Serde { prefix: __arg1_0, spec: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErrPartsMode {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<String>;
        let _:
                ::core::cmp::AssertParamIsEq<crate::miniextendr_fn::SerdeErrorSpec>;
    }
}Eq)]
136pub enum ErrPartsMode {
137    /// Autoref-specialisation probe (`__mx_result_err_parts!`): under the API
138    /// crate's `serde` feature, the shape `serde_error_shape!` declared for the
139    /// error type in this crate, if any; else `RConditionData` when the error
140    /// type implements it; else, under `serde`, the serde shape for an
141    /// `E: Serialize + Display` with `prefix` (`<crate>_error`) as the family
142    /// class; `Debug` otherwise.
143    Probe { prefix: String },
144    /// `#[miniextendr(serde_error(..))]`: serialize the error with serde; the enum
145    /// variant becomes the member class `<prefix>_<variant>`, the payload fields
146    /// become the condition's data. `prefix` is the crate default (`<crate>_error`);
147    /// the shape declared for the error type, the spec's named `shape` and its
148    /// own options (`tag`, `prefix`, `skip`, `rename`, `as_*`) reach
149    /// `serde_err_parts` as `SerdeErrorShape`s, applied in that order.
150    Serde {
151        prefix: String,
152        spec: crate::miniextendr_fn::SerdeErrorSpec,
153    },
154}
155
156impl ErrPartsMode {
157    /// Resolve a parsed `serde_error` spec (or its absence) into a mode.
158    pub fn from_spec(spec: Option<&crate::miniextendr_fn::SerdeErrorSpec>) -> Self {
159        let prefix = crate::miniextendr_fn::default_serde_error_prefix();
160        match spec {
161            None => ErrPartsMode::Probe { prefix },
162            Some(spec) => ErrPartsMode::Serde {
163                prefix,
164                spec: spec.clone(),
165            },
166        }
167    }
168
169    /// The expression yielding an `ErrParts` from the bound error `e`.
170    pub fn expr(&self) -> TokenStream {
171        match self {
172            ErrPartsMode::Probe { prefix } => {
173                let marker = crate::miniextendr_fn::init_marker_path();
174                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__mx_result_err_parts");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "e");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&prefix, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&marker, &mut _s);
            _s
        });
    _s
}quote! { ::miniextendr_api::__mx_result_err_parts!(e, #prefix, #marker) }
175            }
176            ErrPartsMode::Serde { prefix, spec } => {
177                // The shape declared for the error type comes first. The
178                // user's path keeps its span: a misspelt or mistyped shape is
179                // reported on it.
180                let marker = crate::miniextendr_fn::init_marker_path();
181                let declared = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__mx_declared_serde_shape");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "e");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&marker, &mut _s);
            _s
        });
    _s
}quote! { ::miniextendr_api::__mx_declared_serde_shape!(e, #marker) };
182                let mut shapes: Vec<TokenStream> = std::iter::once(declared)
183                    .chain(spec.shape.iter().map(
184                        |path| {
    let mut _s = ::quote::__private::TokenStream::new();
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(syn::spanned::Spanned::span(path)).__into_span();
    ::quote::__private::push_and_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&path, &mut _s);
    _s
}quote::quote_spanned!(syn::spanned::Spanned::span(path)=> &#path),
185                    ))
186                    .collect();
187                let call = |shapes: &[TokenStream]| {
188                    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "condition");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "serde_err_parts");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "e");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&prefix, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let mut _first = true;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut shapes, i) = shapes.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let shapes =
                                match shapes.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            if !_first { ::quote::__private::push_comma(&mut _s); }
                            _first = false;
                            ::quote::ToTokens::to_tokens(&shapes, &mut _s);
                        }
                    }
                    _s
                });
            _s
        });
    _s
}quote! {
189                        ::miniextendr_api::condition::serde_err_parts(&e, #prefix, &[#(#shapes),*])
190                    }
191                };
192                match spec.own_shape() {
193                    None => call(&shapes),
194                    Some(own) => {
195                        let ident = syn::Ident::new(
196                            "__MX_SERDE_ERROR_SHAPE",
197                            proc_macro2::Span::mixed_site(),
198                        );
199                        shapes.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    _s
}quote!(&#ident));
200                        let call = call(&shapes);
201                        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "const");
            ::quote::ToTokens::to_tokens(&ident, &mut _s);
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "condition");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SerdeErrorShape");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&own, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::ToTokens::to_tokens(&call, &mut _s);
            _s
        });
    _s
}quote! {{
202                            const #ident: ::miniextendr_api::condition::SerdeErrorShape = #own;
203                            #call
204                        }}
205                    }
206                }
207            }
208        }
209    }
210}
211
212/// All information needed to generate a C wrapper function for an R-exported Rust item.
213///
214/// This struct abstracts over the differences between standalone `#[miniextendr]` functions
215/// and `impl` block methods (R6, S3, S4, S7, Env). It is constructed via
216/// [`CWrapperContextBuilder`] and consumed by [`CWrapperContext::generate`], which emits
217/// both the `extern "C-unwind"` wrapper and the corresponding `R_CallMethodDef` constant.
218pub struct CWrapperContext {
219    /// Identifier of the original Rust function or method being wrapped.
220    pub fn_ident: syn::Ident,
221    /// The name R calls the item by, for the messages the wrapper raises
222    /// (`` `name()` returned no value``). `None` uses `fn_ident`.
223    pub r_name: Option<String>,
224    /// Identifier for the generated C wrapper (e.g., `C_<crate>_foo` or `C_<crate>_Type__method`).
225    pub c_ident: syn::Ident,
226    /// Identifier of the `R_WRAPPER_*` const that holds the generated R wrapper
227    /// code string, for a rustdoc cross-reference. `None` for impl methods: the
228    /// class's wrapper parts are registered in an anonymous `const _` per impl
229    /// block, which has no path to link to.
230    pub r_wrapper_const: Option<syn::Ident>,
231    /// Function parameters (excluding the `self` receiver for methods).
232    /// Each parameter becomes a `SEXP` argument in the C wrapper signature.
233    pub inputs: syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]>,
234    /// Concrete method item supplying types for declaration-copied signatures.
235    pub inferred_signature: Option<TokenStream>,
236    /// The original Rust return type. Used by strict-mode to inspect whether the inner
237    /// type is lossy (e.g., `i64`, `u64`) and needs checked conversion.
238    pub output: syn::ReturnType,
239    /// Statements emitted before the call expression. For instance methods, this
240    /// includes extracting `self` from the `ExternalPtr` SEXP.
241    pub pre_call: Vec<TokenStream>,
242    /// Statements after argument conversion, before the argument borrows and
243    /// the Rust call. They run on R's main thread in both wrappers.
244    pub post_conversion: Vec<TokenStream>,
245    /// The actual Rust call expression (e.g., `my_func(arg0, arg1)` or
246    /// `self_ref.method(arg0)`). Inserted into the wrapper body after conversions.
247    pub call_expr: TokenStream,
248    /// Whether to run on the main R thread or dispatch to the worker thread.
249    pub thread_strategy: ThreadStrategy,
250    /// How to convert the Rust return value into a `SEXP` for R.
251    pub return_handling: ReturnHandling,
252    /// When `true`, all parameters use coercing conversion (`Rf_coerceVector`) instead
253    /// of strict type-matching. Set by `#[miniextendr(coerce)]`.
254    pub coerce_all: bool,
255    /// Names of individual parameters that use coercing conversion.
256    /// Set by `#[miniextendr(coerce = "param_name")]`.
257    pub coerce_params: Vec<String>,
258    /// When `true`, emits `R_CheckUserInterrupt()` before the call expression.
259    /// Set by `#[miniextendr(check_interrupt)]`.
260    pub check_interrupt: bool,
261    /// When `true`, wraps the call in `GetRNGstate()`/`PutRNGstate()` for R's
262    /// random number generator state management. Set by `#[miniextendr(rng)]`.
263    pub rng: bool,
264    /// `#[cfg(...)]` attributes from the original item, propagated to the C wrapper
265    /// and `call_method_def` constant so they are conditionally compiled.
266    pub cfg_attrs: Vec<syn::Attribute>,
267    /// For methods: the type identifier (e.g., `MyStruct`). Used in doc comments
268    /// and default `call_method_def` naming. `None` for standalone functions.
269    pub type_context: Option<syn::Ident>,
270    /// Whether the original method has a `self` receiver. When `true`, the C wrapper
271    /// includes a `self_sexp` parameter before the regular arguments.
272    pub has_self: bool,
273    /// Override for the `call_method_def` constant name. If `None`, defaults to
274    /// `call_method_def_{type}_{method}` (methods) or `call_method_def_{fn}` (standalone).
275    pub call_method_def_ident: Option<syn::Ident>,
276    /// When `true`, uses `checked_into_sexp_*` for lossy return types (`i64`, `u64`,
277    /// `isize`, `usize` and their `Vec` variants) instead of regular `IntoR::into_sexp`.
278    /// Set by `#[miniextendr(strict)]`.
279    pub strict: bool,
280    /// How `Err` values become condition parts. Set by `#[miniextendr(serde_error)]`.
281    pub err_parts: ErrPartsMode,
282    /// Parameter names with `#[miniextendr(match_arg, several_ok)]` — use
283    /// `match_arg_vec_from_sexp` (instead of `TryFromSexp`) for the `Vec<T>` conversion
284    /// so each element is validated against the enum's `MatchArg::CHOICES`.
285    ///
286    /// Scalar `match_arg` doesn't need entries here because R-side `match.arg()`
287    /// already narrowed the SEXP to a valid choice; the default `TryFromSexp for Enum`
288    /// (generated by `#[derive(MatchArg)]`) decodes it.
289    pub match_arg_several_ok_params: Vec<String>,
290    /// Choice parameters whose type wraps the choice in `Missing` / `Option`
291    /// layers (#1473, #1551), with where their innermost value comes from.
292    /// Converted by the layered decoder
293    /// (`RustConversionBuilder::with_layered_choice`) instead of
294    /// `TryFromSexp`, which no downstream crate can implement for
295    /// `Option<ItsEnum>`.
296    pub layered_choice_params: Vec<(String, crate::rust_conversion_builder::ChoiceLeaf)>,
297    /// `#[miniextendr(no_na)]` parameters (Rust name) with the author's
298    /// `no_na(message = ..)`, if any. Their converted value is checked right
299    /// after the conversion (`RustConversionBuilder::with_no_na`), after the R
300    /// guard `!anyNA(x)` already ran (for an `Either`, in place of the guard).
301    pub no_na_params: Vec<(String, Option<String>)>,
302    /// Parameters whose declared type carries parameter markers
303    /// (`Checked<T>` / `Unchecked<T>`, #1566), with the markers, outermost
304    /// first. `inputs` holds the inner type, which is what converts; the
305    /// value is then wrapped in the markers for the call
306    /// (`RustConversionBuilder::with_param_markers`).
307    pub param_markers: Vec<(String, Vec<crate::type_inspect::ParamMarker>)>,
308    /// The R formal of each parameter (#1842): the name a conversion error
309    /// gives the argument, in its message and `e$param`
310    /// (`RustConversionBuilder::with_formals`).
311    pub formals: crate::r_wrapper_builder::Formals,
312    /// When `true`, preserve original parameter names from `inputs` in the C wrapper
313    /// signature instead of renaming to `arg_0`, `arg_1`, ... The fn path preserves
314    /// user identifiers for rustdoc visibility; impl method path uses `arg_N` for safety.
315    pub preserve_param_names: bool,
316    /// Visibility of the generated `extern "C-unwind"` wrapper function.
317    /// Default: [`syn::Visibility::Inherited`] (no visibility keyword).
318    /// Standalone `#[miniextendr]` fns forward the user's visibility (`pub`, `pub(crate)`, etc.).
319    pub vis: syn::Visibility,
320    /// Generic parameters of the wrapped function, emitted on the C wrapper signature
321    /// as `fn #c_ident #generics(...)`. Default: empty (no generics).
322    pub generics: syn::Generics,
323    /// When `true`, the original Rust fn is already an `extern "C-unwind"` symbol (user-written).
324    /// Skip generating the wrapper body but still emit the `R_CallMethodDef` for registration.
325    /// The `numArgs` count excludes the synthetic `__miniextendr_call` SEXP parameter since
326    /// the user-written fn doesn't have it.
327    pub skip_wrapper: bool,
328}
329
330impl CWrapperContext {
331    /// Creates a new [`CWrapperContextBuilder`] with the given function and C wrapper identifiers.
332    ///
333    /// All other fields start at their defaults (empty/false/None). Use the builder methods
334    /// to configure the context, then call [`CWrapperContextBuilder::build`] to finalize.
335    pub fn builder(fn_ident: syn::Ident, c_ident: syn::Ident) -> CWrapperContextBuilder {
336        CWrapperContextBuilder {
337            fn_ident,
338            r_name: None,
339            c_ident,
340            r_wrapper_const: None,
341            inputs: syn::punctuated::Punctuated::new(),
342            inferred_signature: None,
343            output: syn::ReturnType::Default,
344            pre_call: Vec::new(),
345            post_conversion: Vec::new(),
346            call_expr: None,
347            thread_strategy: None,
348            return_handling: None,
349            coerce_all: false,
350            coerce_params: Vec::new(),
351            check_interrupt: false,
352            rng: false,
353            cfg_attrs: Vec::new(),
354            type_context: None,
355            has_self: false,
356            call_method_def_ident: None,
357            strict: false,
358            err_parts: ErrPartsMode::from_spec(None),
359            match_arg_several_ok_params: Vec::new(),
360            layered_choice_params: Vec::new(),
361            no_na_params: Vec::new(),
362            param_markers: Vec::new(),
363            formals: crate::r_wrapper_builder::Formals::default(),
364            preserve_param_names: false,
365            vis: syn::Visibility::Inherited,
366            generics: syn::Generics::default(),
367            skip_wrapper: false,
368        }
369    }
370
371    /// Generates the complete output for this wrapper: an `extern "C-unwind"` function
372    /// and an `R_CallMethodDef` constant, both decorated with `#[cfg(...)]` attributes
373    /// if present.
374    ///
375    /// When `skip_wrapper` is set (for user-written `extern "C-unwind"` fns), only the
376    /// `R_CallMethodDef` is emitted — the fn body itself is already the C symbol.
377    ///
378    /// Dispatches to [`generate_main_thread_wrapper`](Self::generate_main_thread_wrapper) or
379    /// [`generate_worker_thread_wrapper`](Self::generate_worker_thread_wrapper) based on
380    /// [`thread_strategy`](Self::thread_strategy).
381    pub fn generate(&self) -> TokenStream {
382        let call_method_def = self.generate_call_method_def();
383
384        let cfg_attrs = &self.cfg_attrs;
385
386        if self.skip_wrapper {
387            // User-written extern "C-unwind" fn — only emit the registration entry
388            {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut cfg_attrs, i) = cfg_attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let cfg_attrs =
                match cfg_attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&cfg_attrs, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&call_method_def, &mut _s);
    _s
}quote! {
389                #(#cfg_attrs)*
390                #call_method_def
391            }
392        } else {
393            let c_wrapper = match self.thread_strategy {
394                ThreadStrategy::MainThread => self.generate_main_thread_wrapper(),
395                ThreadStrategy::WorkerThread => self.generate_worker_thread_wrapper(),
396            };
397
398            {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut cfg_attrs, i) = cfg_attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let cfg_attrs =
                match cfg_attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&cfg_attrs, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&c_wrapper, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut cfg_attrs, i) = cfg_attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let cfg_attrs =
                match cfg_attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&cfg_attrs, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&call_method_def, &mut _s);
    _s
}quote! {
399                #(#cfg_attrs)*
400                #c_wrapper
401
402                #(#cfg_attrs)*
403                #call_method_def
404            }
405        }
406    }
407
408    /// The name the wrapper's messages give the item: `r_name` when set,
409    /// otherwise the Rust identifier.
410    fn message_name(&self) -> String {
411        self.r_name
412            .clone()
413            .unwrap_or_else(|| self.fn_ident.to_string())
414    }
415
416    /// Builds the C wrapper's parameter list from the Rust function signature.
417    ///
418    /// Returns a tuple of:
419    /// - `c_params`: `SEXP` parameter declarations for the C wrapper signature. Always
420    ///   starts with `__miniextendr_call` (the R call object for error context), followed
421    ///   by `self_sexp` for instance methods, then `arg_0`, `arg_1`, ... for each input.
422    /// - `rust_args`: The original Rust parameter identifiers (used in the call expression).
423    /// - `sexp_idents`: The generated `arg_N` identifiers (used in SEXP-to-Rust conversions).
424    fn build_c_params(&self) -> (Vec<TokenStream>, Vec<syn::Ident>, Vec<syn::Ident>) {
425        let mut c_params: Vec<TokenStream> = Vec::new();
426        let mut rust_args: Vec<syn::Ident> = Vec::new();
427        let mut sexp_idents: Vec<syn::Ident> = Vec::new();
428
429        // First param is always __miniextendr_call for error context
430        c_params.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "__miniextendr_call");
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    _s
}quote!(__miniextendr_call: ::miniextendr_api::SEXP));
431
432        // For instance methods, add self_sexp parameter
433        if self.has_self {
434            let self_sexp = crate::naming::self_sexp_ident();
435            c_params.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&self_sexp, &mut _s);
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    _s
}quote!(#self_sexp: ::miniextendr_api::SEXP));
436        }
437
438        // Add regular parameters
439        for (idx, arg) in self.inputs.iter().enumerate() {
440            if let syn::FnArg::Typed(pt) = arg
441                && let syn::Pat::Ident(pat_ident) = pt.pat.as_ref()
442            {
443                let ident = &pat_ident.ident;
444                // When preserve_param_names is set, use the original parameter name
445                // (visible in rustdoc). Otherwise use arg_N for predictable mangling.
446                let param_ident = if self.preserve_param_names {
447                    // Keep the user's span: the names are distinct, so no
448                    // conversion rebinds another slot, and a mixed-site span
449                    // would take this crate's edition (`gen` is a keyword in
450                    // 2024 but a plain parameter name in a 2021 crate).
451                    ident.clone()
452                } else {
453                    // Conversion binds the user's identifiers in order. A
454                    // mixed-site slot keeps a parameter named `arg_1` from
455                    // replacing the next argument's SEXP.
456                    match ::quote::__private::IdentFragmentAdapter(&idx) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("arg_{0}", arg))
                    }),
            ::quote::__private::Option::Some::<::quote::__private::Span>(proc_macro2::Span::mixed_site())),
}format_ident!("arg_{}", idx, span = proc_macro2::Span::mixed_site())
457                };
458
459                c_params.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&param_ident, &mut _s);
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    _s
}quote!(#param_ident: ::miniextendr_api::SEXP));
460                rust_args.push(ident.clone());
461                sexp_idents.push(param_ident);
462            }
463        }
464
465        (c_params, rust_args, sexp_idents)
466    }
467
468    /// Generates `TryFromSexp` conversion statements for each parameter.
469    ///
470    /// Each statement converts an `arg_N: SEXP` into the corresponding Rust type
471    /// declared in the original function signature. Respects `strict` and `coerce` settings.
472    ///
473    /// Used by the main-thread wrapper where all conversions happen inline.
474    fn build_conversion_stmts(&self, sexp_idents: &[syn::Ident]) -> Vec<TokenStream> {
475        let builder = self.conversion_builder();
476        builder.build_conversions(&self.inputs, sexp_idents)
477    }
478
479    /// Build conversion statements split for worker thread execution.
480    ///
481    /// Returns (pre_closure, in_closure) statements:
482    /// - pre_closure: Run on main thread, produce owned values to move
483    /// - in_closure: Run inside worker closure, create borrows
484    fn build_conversion_stmts_split(
485        &self,
486        sexp_idents: &[syn::Ident],
487    ) -> (Vec<TokenStream>, Vec<TokenStream>) {
488        let builder = self.conversion_builder();
489
490        let mut all_pre = Vec::new();
491        let mut all_in = Vec::new();
492
493        for (arg, sexp_ident) in self.inputs.iter().zip(sexp_idents.iter()) {
494            if let syn::FnArg::Typed(pat_type) = arg {
495                let (owned, borrowed) = builder.build_conversion_split(pat_type, sexp_ident);
496                all_pre.extend(owned);
497                all_in.extend(borrowed);
498            }
499        }
500
501        (all_pre, all_in)
502    }
503
504    /// Configure argument conversion once for both metadata and value conversion.
505    fn conversion_builder(&self) -> crate::RustConversionBuilder {
506        let mut builder = crate::RustConversionBuilder::new();
507        if self.inferred_signature.is_some() {
508            builder = builder.with_inferred_types();
509        }
510        if self.strict {
511            builder = builder.with_strict();
512        }
513        if self.coerce_all {
514            builder = builder.with_coerce_all();
515        }
516        for param in &self.coerce_params {
517            builder = builder.with_coerce_param(param.clone());
518        }
519        for param in &self.match_arg_several_ok_params {
520            builder = builder.with_match_arg_several_ok(param.clone());
521        }
522        for (param, leaf) in &self.layered_choice_params {
523            builder = builder.with_layered_choice(param.clone(), leaf.clone());
524        }
525        for (param, message) in &self.no_na_params {
526            builder = builder.with_no_na(param.clone(), message.clone());
527        }
528        for (param, markers) in &self.param_markers {
529            builder = builder.with_param_markers(param.clone(), markers.clone());
530        }
531        builder = builder.with_formals(self.formals.clone());
532        // A standalone fn's R wrapper passes `Quoted` / `Quosure` arguments
533        // unevaluated (#1835); a method's is generated per class system and
534        // does not, so there they stay a compile error.
535        match &self.type_context {
536            None => builder = builder.with_unevaluated_args(),
537            Some(type_ident) => builder = builder.with_self_type(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&type_ident, &mut _s);
        _s
    })syn::parse_quote!(#type_ident)),
538        }
539        builder
540    }
541
542    /// Check the actual converters' native borrows before creating references.
543    /// Metadata handles scalar/slice leaves, aliases, and supported containers.
544    fn build_alias_guard(&self, sexp_idents: &[syn::Ident]) -> TokenStream {
545        let builder = self.conversion_builder();
546        let mut metadata = Vec::new();
547        let mut args = Vec::new();
548        for (arg, sexp_ident) in self.inputs.iter().zip(sexp_idents) {
549            if let syn::FnArg::Typed(pt) = arg
550                && let syn::Pat::Ident(pat_ident) = pt.pat.as_ref()
551                && let Some(borrow) = builder.native_borrow_metadata(pt, sexp_ident)
552            {
553                let name = crate::naming::ident_name(&pat_ident.ident);
554                metadata.push(borrow);
555                args.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&sexp_ident, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            _s
        });
    _s
}quote! { (#sexp_ident, #name) });
556            }
557        }
558        if args.is_empty() {
559            return TokenStream::new();
560        }
561        let check = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "from_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "borrow");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "assert_no_aliases");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Bracket,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            {
                                use ::quote::__private::ext::*;
                                let mut _first = true;
                                let has_iter = ::quote::__private::HasIterator::<false>;
                                #[allow(unused_mut)]
                                let (mut args, i) = args.quote_into_iter();
                                let has_iter = has_iter | i;
                                <_ as
                                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                                while true {
                                    let args =
                                        match args.next() {
                                            Some(_x) => ::quote::__private::RepInterp(_x),
                                            None => break,
                                        };
                                    if !_first { ::quote::__private::push_comma(&mut _s); }
                                    _first = false;
                                    ::quote::ToTokens::to_tokens(&args, &mut _s);
                                }
                            }
                            _s
                        });
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_native_borrows");
                    ::quote::__private::push_comma(&mut _s);
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
562            // SAFETY: wrapper arguments are rooted on R's main thread, and
563            // every allocating traversal runs inside R unwind protection.
564            unsafe {
565                ::miniextendr_api::from_r::borrow::assert_no_aliases(
566                    [#(#args),*], __miniextendr_native_borrows,
567                );
568            }
569        };
570        let check = if self.thread_strategy == ThreadStrategy::WorkerThread {
571            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_alias_result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "unwind_protect");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "with_r_unwind_protect");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&check, &mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "SEXP");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "nil");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_alias_result");
    ::quote::__private::push_ne(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "nil");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s,
                "__miniextendr_alias_result");
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
572                let __miniextendr_alias_result =
573                    ::miniextendr_api::unwind_protect::with_r_unwind_protect(
574                        || { #check; ::miniextendr_api::SEXP::nil() },
575                        ::core::option::Option::Some(__miniextendr_call),
576                    );
577                if __miniextendr_alias_result != ::miniextendr_api::SEXP::nil() {
578                    return __miniextendr_alias_result;
579                }
580            }
581        } else {
582            check
583        };
584        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s,
                "__miniextendr_native_borrows");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let mut _first = true;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut metadata, i) = metadata.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let metadata =
                                match metadata.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            if !_first { ::quote::__private::push_comma(&mut _s); }
                            _first = false;
                            ::quote::ToTokens::to_tokens(&metadata, &mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "if");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "from_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "borrow");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "needs_check");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_native_borrows");
                    _s
                });
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&check, &mut _s);
                    _s
                });
            _s
        });
    _s
}quote! {{
585            let __miniextendr_native_borrows = [#(#metadata),*];
586            if ::miniextendr_api::from_r::borrow::needs_check(&__miniextendr_native_borrows) {
587                #check
588            }
589        }}
590    }
591
592    /// The borrows of the borrowed external arguments (`&T` / `&mut T` /
593    /// views, #2106), except those a marker rebinds to another type.
594    fn arg_borrows(&self) -> TokenStream {
595        let unborrowed: Vec<String> = self
596            .param_markers
597            .iter()
598            .map(|(name, _)| name.clone())
599            .collect();
600        let self_ty: Option<syn::Type> = self.type_context.as_ref().map(|t| ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&t, &mut _s);
        _s
    })syn::parse_quote!(#t));
601        crate::externalptr_args::arg_borrows(&self.inputs, &unborrowed, self_ty.as_ref())
602    }
603
604    /// Generates an `extern "C-unwind"` wrapper that runs entirely on the R main thread.
605    ///
606    /// The wrapper body is enclosed in `with_r_unwind_protect`: Rust panics become
607    /// tagged conditions for the R wrapper to raise, while R exits resume after Rust
608    /// cleanup. With `rng`, an outer R unwind guard also covers loading and saving
609    /// state. The inner guard converts Rust panics to values so `PutRNGstate()` still
610    /// runs; the result stays rooted while that call may allocate.
611    fn generate_main_thread_wrapper(&self) -> TokenStream {
612        let c_ident = &self.c_ident;
613        let vis = &self.vis;
614        let generics = &self.generics;
615        let (c_params, _, sexp_idents) = self.build_c_params();
616        let conversion_stmts = self.build_conversion_stmts(&sexp_idents);
617        let alias_guard = self.build_alias_guard(&sexp_idents);
618        let type_setup = self
619            .inferred_signature
620            .as_ref()
621            .map(|callable| crate::trait_signature::setup(&self.inputs, self.has_self, callable));
622        let borrow = self.arg_borrows();
623        let pre_call = &self.pre_call;
624        let post_conversion = &self.post_conversion;
625        let call_expr = &self.call_expr;
626
627        let pre_call_checks = if self.check_interrupt {
628            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "sys");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "R_CheckUserInterrupt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
629                unsafe { ::miniextendr_api::sys::R_CheckUserInterrupt(); }
630            }
631        } else {
632            TokenStream::new()
633        };
634
635        let return_handling = self.generate_return_handling(call_expr);
636
637        let doc = self.generate_doc_comment("main thread");
638        let source_loc_doc = crate::source_location_doc(self.fn_ident.span());
639
640        let guarded_body = self.protect_wrapper_body({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&type_setup, &mut _s);
    ::quote::ToTokens::to_tokens(&alias_guard, &mut _s);
    ::quote::ToTokens::to_tokens(&pre_call_checks, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut pre_call, i) = pre_call.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let pre_call =
                match pre_call.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&pre_call, &mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut conversion_stmts, i) = conversion_stmts.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let conversion_stmts =
                match conversion_stmts.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&conversion_stmts, &mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut post_conversion, i) = post_conversion.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let post_conversion =
                match post_conversion.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&post_conversion, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&borrow, &mut _s);
    ::quote::ToTokens::to_tokens(&return_handling, &mut _s);
    _s
}quote! {
641            #type_setup
642            #alias_guard
643            #pre_call_checks
644            #(#pre_call)*
645            #(#conversion_stmts)*
646            #(#post_conversion)*
647            #borrow
648            #return_handling
649        });
650
651        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&source_loc_doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "concat");
            ::quote::__private::push_bang(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::parse(&mut _s,
                        "\"Generated from source file `\"");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "file");
                    ::quote::__private::push_bang(&mut _s);
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::parse(&mut _s, "\"`.\"");
                    _s
                });
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "no_mangle");
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&vis, &mut _s);
    ::quote::__private::push_ident(&mut _s, "extern");
    ::quote::__private::parse(&mut _s, "\"C-unwind\"");
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::ToTokens::to_tokens(&c_ident, &mut _s);
    ::quote::ToTokens::to_tokens(&generics, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let mut _first = true;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut c_params, i) = c_params.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let c_params =
                        match c_params.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    if !_first { ::quote::__private::push_comma(&mut _s); }
                    _first = false;
                    ::quote::ToTokens::to_tokens(&c_params, &mut _s);
                }
            }
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s,
                "__miniextendr_deferred_mark");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "deferred_condition");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "mark");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s, "__miniextendr_value");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&guarded_body, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "deferred_condition");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "finish");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_deferred_mark");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_value");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
652            #[doc = #doc]
653            #[doc = #source_loc_doc]
654            #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
655            #[unsafe(no_mangle)]
656            #vis extern "C-unwind" fn #c_ident #generics(#(#c_params),*) -> ::miniextendr_api::SEXP {
657                let __miniextendr_deferred_mark = ::miniextendr_api::deferred_condition::mark();
658                let __miniextendr_value = #guarded_body;
659                unsafe {
660                    ::miniextendr_api::deferred_condition::finish(
661                        __miniextendr_deferred_mark,
662                        __miniextendr_value,
663                        ::core::option::Option::Some(__miniextendr_call),
664                    )
665                }
666            }
667        }
668    }
669
670    /// Protect the complete main-thread portion of a wrapper.
671    ///
672    /// With RNG enabled, the inner guard converts Rust panics into values so
673    /// state is saved on both success and panic. The outer guard covers RNG
674    /// loading, result protection, and saving; either RNG call can raise in R.
675    fn protect_wrapper_body(&self, body: TokenStream) -> TokenStream {
676        let guarded_body = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "unwind_protect");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "with_r_unwind_protect");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "move");
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&body, &mut _s);
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
677            ::miniextendr_api::unwind_protect::with_r_unwind_protect(
678                move || { #body },
679                ::core::option::Option::Some(__miniextendr_call),
680            )
681        };
682        if self.rng {
683            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "unwind_protect");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "with_r_unwind_protect");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "move");
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "sys");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "GetRNGstate_unchecked");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                ::quote::__private::TokenStream::new());
                            ::quote::__private::push_semi(&mut _s);
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s, "let");
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_rng_value");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&guarded_body, &mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "let");
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_rng_result");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "gc_protect");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "OwnedProtect");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "new");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_rng_value");
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "sys");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "PutRNGstate_unchecked");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                ::quote::__private::TokenStream::new());
                            ::quote::__private::push_semi(&mut _s);
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_rng_result");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "get");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
684                ::miniextendr_api::unwind_protect::with_r_unwind_protect(
685                    move || {
686                        unsafe { ::miniextendr_api::sys::GetRNGstate_unchecked(); }
687                        let __miniextendr_rng_value = #guarded_body;
688                        let __miniextendr_rng_result = unsafe {
689                            ::miniextendr_api::gc_protect::OwnedProtect::new(__miniextendr_rng_value)
690                        };
691                        unsafe { ::miniextendr_api::sys::PutRNGstate_unchecked(); }
692                        __miniextendr_rng_result.get()
693                    },
694                    ::core::option::Option::Some(__miniextendr_call),
695                )
696            }
697        } else {
698            guarded_body
699        }
700    }
701
702    /// Generates an `extern "C-unwind"` wrapper that dispatches to the worker thread.
703    ///
704    /// Structure:
705    /// 1. Protect RNG loading/saving too, if `rng` is enabled
706    /// 2. `with_r_unwind_protect` around setup, dispatch, and return conversion
707    /// 3. Pre-closure conversions on the main thread (produces owned values)
708    /// 4. `run_on_worker` (returns `Result<T, String>`) with a
709    ///    `move` closure containing in-closure conversions and the call expression,
710    ///    run through `condition::catch_condition` so an `error!()` /
711    ///    `warning!()` / ... payload comes back as a value and is raised on the
712    ///    main thread with its class, data and call choice
713    /// 5. Return conversion back on the main thread via `with_r_unwind_protect`
714    /// 6. `PutRNGstate()` (if `rng` enabled)
715    /// 7. Rust panics become tagged conditions; R exits continue through the guard
716    /// 8. Conditions queued with `defer_warning` & co. during the call are
717    ///    signalled (`deferred_condition::finish`) before the SEXP reaches R
718    fn generate_worker_thread_wrapper(&self) -> TokenStream {
719        let c_ident = &self.c_ident;
720        let vis = &self.vis;
721        let generics = &self.generics;
722        let (c_params, _, sexp_idents) = self.build_c_params();
723        let (pre_closure_stmts, in_closure_stmts) = self.build_conversion_stmts_split(&sexp_idents);
724        let alias_guard = self.build_alias_guard(&sexp_idents);
725        let type_setup = self
726            .inferred_signature
727            .as_ref()
728            .map(|callable| crate::trait_signature::setup(&self.inputs, self.has_self, callable));
729        let borrow = self.arg_borrows();
730        let pre_call = &self.pre_call;
731        let post_conversion = &self.post_conversion;
732        let call_expr = &self.call_expr;
733
734        // Compile-time check: worker dispatch requires the `worker-thread` feature.
735        // Check both `worker-thread` (direct) and `worker-default` (implies worker-thread
736        // via miniextendr-api, but the user crate may only have the latter in its features).
737        let fn_name = self.fn_ident.to_string();
738        let feature_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`#[miniextendr(worker)]` on `{0}` requires the `worker-thread` cargo feature. Add `worker-thread = [\"miniextendr-api/worker-thread\"]` to your [features] in Cargo.toml.",
                fn_name))
    })format!(
739            "`#[miniextendr(worker)]` on `{fn_name}` requires the `worker-thread` cargo feature. \
740             Add `worker-thread = [\"miniextendr-api/worker-thread\"]` to your [features] in Cargo.toml."
741        );
742        let worker_feature_check = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "not");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "any");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "feature");
                                    ::quote::__private::push_eq(&mut _s);
                                    ::quote::__private::parse(&mut _s, "\"worker-thread\"");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "feature");
                                    ::quote::__private::push_eq(&mut _s);
                                    ::quote::__private::parse(&mut _s, "\"worker-default\"");
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "compile_error");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&feature_msg, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
743            #[cfg(not(any(feature = "worker-thread", feature = "worker-default")))]
744            ::core::compile_error!(#feature_msg);
745        };
746
747        let pre_call_checks = if self.check_interrupt {
748            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "sys");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "R_CheckUserInterrupt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
749                unsafe { ::miniextendr_api::sys::R_CheckUserInterrupt(); }
750            }
751        } else {
752            TokenStream::new()
753        };
754
755        let (worker_body, return_conversion) = self.generate_worker_return_handling(call_expr);
756
757        let doc = self.generate_doc_comment("worker thread");
758        let source_loc_doc = crate::source_location_doc(self.fn_ident.span());
759
760        let guarded_body = self.protect_wrapper_body({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&type_setup, &mut _s);
    ::quote::ToTokens::to_tokens(&alias_guard, &mut _s);
    ::quote::ToTokens::to_tokens(&pre_call_checks, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut pre_call, i) = pre_call.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let pre_call =
                match pre_call.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&pre_call, &mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut pre_closure_stmts, i) = pre_closure_stmts.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let pre_closure_stmts =
                match pre_closure_stmts.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&pre_closure_stmts, &mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut post_conversion, i) = post_conversion.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let post_conversion =
                match post_conversion.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&post_conversion, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&borrow, &mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "worker");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "run_on_worker");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "move");
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "condition");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "catch_condition");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "move");
                            ::quote::__private::push_or_or(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    {
                                        use ::quote::__private::ext::*;
                                        let has_iter = ::quote::__private::HasIterator::<false>;
                                        #[allow(unused_mut)]
                                        let (mut in_closure_stmts, i) =
                                            in_closure_stmts.quote_into_iter();
                                        let has_iter = has_iter | i;
                                        <_ as
                                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                                        while true {
                                            let in_closure_stmts =
                                                match in_closure_stmts.next() {
                                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                                    None => break,
                                                };
                                            ::quote::ToTokens::to_tokens(&in_closure_stmts, &mut _s);
                                        }
                                    }
                                    ::quote::ToTokens::to_tokens(&worker_body, &mut _s);
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "result");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Result");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Ok");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_result");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&return_conversion, &mut _s);
                    _s
                });
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "result");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Result");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Err");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_condition");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "rust_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_condition");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__panic_msg");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "error_value");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "make_rust_condition_value");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_and(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "__panic_msg");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "error_value");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "kind");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "PANIC");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "core");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "option");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Option");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "None");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "core");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "option");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Option");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Some");
                                    ::quote::__private::push_group(&mut _s,
                                        ::quote::__private::Delimiter::Parenthesis,
                                        {
                                            let mut _s = ::quote::__private::TokenStream::new();
                                            ::quote::__private::push_ident(&mut _s,
                                                "__miniextendr_call");
                                            _s
                                        });
                                    ::quote::__private::push_comma(&mut _s);
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
761            #type_setup
762            #alias_guard
763            #pre_call_checks
764            #(#pre_call)*
765            #(#pre_closure_stmts)*
766            // Post-conversion checks stay on the main thread. A borrowed
767            // external argument keeps the whole call there, so `borrow` is
768            // empty here.
769            #(#post_conversion)*
770            #borrow
771
772            // `catch_condition` returns an `error!()` / `warning!()` / ...
773            // raised on the worker as a value (its payload is `Send`), so
774            // it is raised here with its class, data and call choice;
775            // only generic panics come back as the message `Err`.
776            match ::miniextendr_api::worker::run_on_worker(move || {
777                ::miniextendr_api::condition::catch_condition(move || {
778                    #(#in_closure_stmts)*
779                    #worker_body
780                })
781            }) {
782                ::core::result::Result::Ok(::core::result::Result::Ok(__miniextendr_result)) => {
783                    #return_conversion
784                }
785                ::core::result::Result::Ok(::core::result::Result::Err(__miniextendr_condition)) => unsafe {
786                    ::miniextendr_api::error_value::rust_condition_value(
787                        __miniextendr_condition,
788                        ::core::option::Option::Some(__miniextendr_call),
789                    )
790                },
791                ::core::result::Result::Err(__panic_msg) => {
792                    unsafe { ::miniextendr_api::error_value::make_rust_condition_value(
793                        &__panic_msg, ::miniextendr_api::error_value::kind::PANIC, ::core::option::Option::None, ::core::option::Option::Some(__miniextendr_call),
794                    ) }
795                }
796            }
797        });
798
799        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&worker_feature_check, &mut _s);
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&source_loc_doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "concat");
            ::quote::__private::push_bang(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::parse(&mut _s,
                        "\"Generated from source file `\"");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "file");
                    ::quote::__private::push_bang(&mut _s);
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::parse(&mut _s, "\"`.\"");
                    _s
                });
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "no_mangle");
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&vis, &mut _s);
    ::quote::__private::push_ident(&mut _s, "extern");
    ::quote::__private::parse(&mut _s, "\"C-unwind\"");
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::ToTokens::to_tokens(&c_ident, &mut _s);
    ::quote::ToTokens::to_tokens(&generics, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let mut _first = true;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut c_params, i) = c_params.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let c_params =
                        match c_params.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    if !_first { ::quote::__private::push_comma(&mut _s); }
                    _first = false;
                    ::quote::ToTokens::to_tokens(&c_params, &mut _s);
                }
            }
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s,
                "__miniextendr_deferred_mark");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "deferred_condition");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "mark");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s, "__miniextendr_value");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&guarded_body, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "deferred_condition");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "finish");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_deferred_mark");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_value");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
800            #worker_feature_check
801
802            #[doc = #doc]
803            #[doc = #source_loc_doc]
804            #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
805            #[unsafe(no_mangle)]
806            #vis extern "C-unwind" fn #c_ident #generics(#(#c_params),*) -> ::miniextendr_api::SEXP {
807                let __miniextendr_deferred_mark = ::miniextendr_api::deferred_condition::mark();
808                let __miniextendr_value = #guarded_body;
809                unsafe {
810                    ::miniextendr_api::deferred_condition::finish(
811                        __miniextendr_deferred_mark,
812                        __miniextendr_value,
813                        ::core::option::Option::Some(__miniextendr_call),
814                    )
815                }
816            }
817        }
818    }
819
820    /// Generates the inline return-handling code for the main-thread wrapper.
821    ///
822    /// Emits the call expression followed by conversion logic based on [`ReturnHandling`].
823    /// For `Option`/`Result` variants, also emits error-path code that returns a
824    /// tagged condition SEXP (which the R-side wrapper raises).
825    fn generate_return_handling(&self, call_expr: &TokenStream) -> TokenStream {
826        let fn_name = self.message_name();
827        let err_parts = self.err_parts.expr();
828        let self_sexp = crate::naming::self_sexp_ident();
829
830        match &self.return_handling {
831            ReturnHandling::Unit => {
832                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "nil");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
833                    #call_expr;
834                    ::miniextendr_api::SEXP::nil()
835                }
836            }
837            ReturnHandling::RawSexp => {
838                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! {
839                    #call_expr
840                }
841            }
842            ReturnHandling::ExternalPtr => {
843                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "externalptr");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExternalPtr");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "new");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__result");
                    _s
                });
            _s
        });
    _s
}quote! {
844                    let __result = #call_expr;
845                    ::miniextendr_api::into_r::IntoR::into_sexp(
846                        ::miniextendr_api::externalptr::ExternalPtr::new(__result)
847                    )
848                }
849            }
850            ReturnHandling::SelfHandle => {
851                // In-place builder: the `&mut self` method mutated the value
852                // pointed to by `self_sexp`. Evaluate the call only for that
853                // side effect, drop the returned `&Self`/`&mut Self` borrow
854                // immediately (the trailing `;` ends its lifetime), and hand
855                // back the SAME ExternalPtr handle. No clone, no rewrap.
856                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_underscore(&mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::ToTokens::to_tokens(&self_sexp, &mut _s);
    _s
}quote! {
857                    let _ = #call_expr;
858                    #self_sexp
859                }
860            }
861            ReturnHandling::SelfHandleResult => {
862                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "result");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Result");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_comma(&mut _s);
    ::quote::__private::push_underscore(&mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "result");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Result");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Err");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "e");
            _s
        });
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    ::quote::ToTokens::to_tokens(&self_sexp, &mut _s);
    _s
}quote! {
863                    let __result: ::core::result::Result<(), _> = #call_expr;
864                    if let ::core::result::Result::Err(e) = __result {
865                        return unsafe { ::miniextendr_api::error_value::result_err_condition_value(
866                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
867                        ) };
868                    }
869                    #self_sexp
870                }
871            }
872            ReturnHandling::SelfHandleOption => {
873                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "is_none");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    ::quote::ToTokens::to_tokens(&self_sexp, &mut _s);
    _s
}quote! {
874                    let __result: ::core::option::Option<()> = #call_expr;
875                    if __result.is_none() {
876                        return ::miniextendr_api::SEXP::nil();
877                    }
878                    #self_sexp
879                }
880            }
881            ReturnHandling::IntoR => {
882                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__result"))
            }), ::quote::__private::Option::None)format_ident!("__result");
883                let conversion = self.sexp_conversion_expr(&result_ident, true);
884                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
    _s
}quote! {
885                    let #result_ident = #call_expr;
886                    #conversion
887                }
888            }
889            ReturnHandling::OptionUnit => {
890                let error_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}()` returned no value",
                fn_name))
    })format!("`{fn_name}()` returned no value");
891                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "is_none");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "make_rust_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&error_msg, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "error_value");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "kind");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "NONE_ERR");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "None");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "nil");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
892                    let __result = #call_expr;
893                    if __result.is_none() {
894                        return unsafe { ::miniextendr_api::error_value::make_rust_condition_value(
895                            #error_msg, ::miniextendr_api::error_value::kind::NONE_ERR, ::core::option::Option::None, ::core::option::Option::Some(__miniextendr_call),
896                        ) };
897                    }
898                    ::miniextendr_api::SEXP::nil()
899                }
900            }
901            ReturnHandling::OptionSexp => {
902                let error_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}()` returned no value",
                fn_name))
    })format!("`{fn_name}()` returned no value");
903                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "None");
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "make_rust_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&error_msg, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "error_value");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "kind");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "NONE_ERR");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "None");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
904                    let __result = #call_expr;
905                    match __result {
906                        ::core::option::Option::Some(v) => v,
907                        ::core::option::Option::None => return unsafe { ::miniextendr_api::error_value::make_rust_condition_value(
908                            #error_msg, ::miniextendr_api::error_value::kind::NONE_ERR, ::core::option::Option::None, ::core::option::Option::Some(__miniextendr_call),
909                        ) },
910                    }
911                }
912            }
913            ReturnHandling::OptionIntoR => {
914                // For Option<T> where Option<T>: IntoR (e.g. Option<&T>, Option<Vec<T>>).
915                // Call into_sexp on the whole Option — IntoR impl handles None → NULL/NA.
916                // result_ident holds the full Option<T>, so the strict lookup must
917                // see the full type (checked_option_* helpers).
918                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__result"))
            }), ::quote::__private::Option::None)format_ident!("__result");
919                let conversion = self.sexp_conversion_expr(&result_ident, false);
920                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
    _s
}quote! {
921                    let #result_ident = #call_expr;
922                    #conversion
923                }
924            }
925            ReturnHandling::OptionClassPayload => {
926                // Option<Class> under an explicit class wrap: no `IntoR for Option<Class>`
927                // can exist, so convert Some's payload through `Class: IntoR`; None is NULL.
928                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__result"))
            }), ::quote::__private::Option::None)format_ident!("__result");
929                let conversion = self.sexp_conversion_expr(&result_ident, true);
930                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&conversion, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "None");
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
931                    match #call_expr {
932                        ::core::option::Option::Some(#result_ident) => #conversion,
933                        ::core::option::Option::None => ::miniextendr_api::SEXP::nil(),
934                    }
935                }
936            }
937            // Option<Self>: wrap Some(Self) in an ExternalPtr like the bare-Self path;
938            // the Option<ExternalPtr<Self>> gives NULL for None.
939            ReturnHandling::OptionExternalPtr => {
940                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "__result");
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "map");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "externalptr");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "ExternalPtr");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "new");
                    _s
                });
            _s
        });
    _s
}quote! {
941                    let __result = #call_expr;
942                    ::miniextendr_api::into_r::IntoR::into_sexp(
943                        __result.map(::miniextendr_api::externalptr::ExternalPtr::new)
944                    )
945                }
946            }
947            ReturnHandling::ResultUnit => {
948                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "result");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Result");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Err");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "e");
            _s
        });
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "nil");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
949                    let __result = #call_expr;
950                    if let ::core::result::Result::Err(e) = __result {
951                        return unsafe { ::miniextendr_api::error_value::result_err_condition_value(
952                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
953                        ) };
954                    }
955                    ::miniextendr_api::SEXP::nil()
956                }
957            }
958            ReturnHandling::ResultSexp => {
959                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
960                    let __result = #call_expr;
961                    match __result {
962                        ::core::result::Result::Ok(v) => v,
963                        ::core::result::Result::Err(e) => return unsafe { ::miniextendr_api::error_value::result_err_condition_value(
964                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
965                        ) },
966                    }
967                }
968            }
969            ReturnHandling::ResultIntoR => {
970                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__result"))
            }), ::quote::__private::Option::None)format_ident!("__result");
971                let conversion = self.sexp_conversion_expr(&result_ident, true);
972                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
    _s
}quote! {
973                    let __result = #call_expr;
974                    let #result_ident = match __result {
975                        ::core::result::Result::Ok(v) => v,
976                        ::core::result::Result::Err(e) => return unsafe { ::miniextendr_api::error_value::result_err_condition_value(
977                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
978                        ) },
979                    };
980                    #conversion
981                }
982            }
983            // Result<T, ()>: unit error is a deliberate sentinel — always return NULL on Err.
984            ReturnHandling::ResultNullOnErr => {
985                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__result"))
            }), ::quote::__private::Option::None)format_ident!("__result");
986                let conversion = self.sexp_conversion_expr(&result_ident, true);
987                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&conversion, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
988                    let __result = #call_expr;
989                    match __result {
990                        ::core::result::Result::Ok(#result_ident) => #conversion,
991                        ::core::result::Result::Err(()) => ::miniextendr_api::SEXP::nil(),
992                    }
993                }
994            }
995            // Result<Self, E>: raise on Err like ResultIntoR, but wrap Ok(Self) in an
996            // ExternalPtr like the bare-Self path rather than routing through IntoR.
997            ReturnHandling::ResultExternalPtr => {
998                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "externalptr");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExternalPtr");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "new");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__result");
                    _s
                });
            _s
        });
    _s
}quote! {
999                    let __result = #call_expr;
1000                    let __result = match __result {
1001                        ::core::result::Result::Ok(v) => v,
1002                        ::core::result::Result::Err(e) => return unsafe { ::miniextendr_api::error_value::result_err_condition_value(
1003                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
1004                        ) },
1005                    };
1006                    ::miniextendr_api::into_r::IntoR::into_sexp(
1007                        ::miniextendr_api::externalptr::ExternalPtr::new(__result)
1008                    )
1009                }
1010            }
1011            ReturnHandling::AsListOf => {
1012                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "convert");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "AsList");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__result");
                    _s
                });
            _s
        });
    _s
}quote! {
1013                    let __result = #call_expr;
1014                    ::miniextendr_api::into_r::IntoR::into_sexp(
1015                        ::miniextendr_api::convert::AsList(__result)
1016                    )
1017                }
1018            }
1019            ReturnHandling::AsExternalPtrOf => {
1020                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "convert");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "AsExternalPtr");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__result");
                    _s
                });
            _s
        });
    _s
}quote! {
1021                    let __result = #call_expr;
1022                    ::miniextendr_api::into_r::IntoR::into_sexp(
1023                        ::miniextendr_api::convert::AsExternalPtr(__result)
1024                    )
1025                }
1026            }
1027            ReturnHandling::AsNativeOf => {
1028                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__result");
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "convert");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "AsRNative");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "__result");
                    _s
                });
            _s
        });
    _s
}quote! {
1029                    let __result = #call_expr;
1030                    ::miniextendr_api::into_r::IntoR::into_sexp(
1031                        ::miniextendr_api::convert::AsRNative(__result)
1032                    )
1033                }
1034            }
1035        }
1036    }
1037
1038    /// Generates return-handling code split between worker and main threads.
1039    ///
1040    /// Returns `(worker_body, return_conversion)`:
1041    /// - `worker_body`: Runs inside the `run_on_worker` closure. Contains just the call
1042    ///   expression (the worker returns the raw `Option`/`Result` for the main thread
1043    ///   to inspect).
1044    /// - `return_conversion`: Runs back on the main thread after the worker returns.
1045    ///   Converts the Rust value to SEXP (via `with_r_unwind_protect`). For `Option`
1046    ///   and `Result` variants, error checking happens here and produces a tagged
1047    ///   condition SEXP that the R-side wrapper raises.
1048    fn generate_worker_return_handling(
1049        &self,
1050        call_expr: &TokenStream,
1051    ) -> (TokenStream, TokenStream) {
1052        let fn_name = self.message_name();
1053        let err_parts = self.err_parts.expr();
1054
1055        match &self.return_handling {
1056            ReturnHandling::Unit => {
1057                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
1058                    #call_expr;
1059                };
1060                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "nil");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
1061                    ::miniextendr_api::SEXP::nil()
1062                };
1063                (worker, convert)
1064            }
1065            ReturnHandling::RawSexp => {
1066                // Raw SEXP can't use worker thread - this shouldn't happen
1067                // but handle it gracefully
1068                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! {
1069                    #call_expr
1070                };
1071                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    _s
}quote! {
1072                    __miniextendr_result
1073                };
1074                (worker, convert)
1075            }
1076            ReturnHandling::ExternalPtr => {
1077                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! {
1078                    #call_expr
1079                };
1080                let unwind_fn = self.worker_conversion_unwind_fn();
1081                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "IntoR");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_sexp");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "externalptr");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "ExternalPtr");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "new");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_result");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1082                    #unwind_fn(
1083                        || ::miniextendr_api::into_r::IntoR::into_sexp(
1084                            ::miniextendr_api::externalptr::ExternalPtr::new(__miniextendr_result)
1085                        ),
1086                        ::core::option::Option::Some(__miniextendr_call),
1087                    )
1088                };
1089                (worker, convert)
1090            }
1091            ReturnHandling::IntoR => {
1092                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! {
1093                    #call_expr
1094                };
1095                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__miniextendr_result"))
            }), ::quote::__private::Option::None)format_ident!("__miniextendr_result");
1096                let conversion = self.sexp_conversion_expr(&result_ident, true);
1097                let unwind_fn = self.worker_conversion_unwind_fn();
1098                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::ToTokens::to_tokens(&conversion, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1099                    #unwind_fn(
1100                        || #conversion,
1101                        ::core::option::Option::Some(__miniextendr_call),
1102                    )
1103                };
1104                (worker, convert)
1105            }
1106            ReturnHandling::OptionUnit => {
1107                let error_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}()` returned no value",
                fn_name))
    })format!("`{fn_name}()` returned no value");
1108                // Return the Option from worker, check on main thread.
1109                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1110                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "is_none");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "make_rust_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&error_msg, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "error_value");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "kind");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "NONE_ERR");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "None");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::__private::push_ident(&mut _s, "else");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            _s
        });
    _s
}quote! {
1111                    if __miniextendr_result.is_none() {
1112                        unsafe { ::miniextendr_api::error_value::make_rust_condition_value(
1113                            #error_msg, ::miniextendr_api::error_value::kind::NONE_ERR, ::core::option::Option::None, ::core::option::Option::Some(__miniextendr_call),
1114                        ) }
1115                    } else {
1116                        ::miniextendr_api::SEXP::nil()
1117                    }
1118                };
1119                (worker, convert)
1120            }
1121            ReturnHandling::OptionSexp => {
1122                let error_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}()` returned no value",
                fn_name))
    })format!("`{fn_name}()` returned no value");
1123                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1124                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "None");
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "make_rust_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&error_msg, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "error_value");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "kind");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "NONE_ERR");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "None");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1125                    match __miniextendr_result {
1126                        ::core::option::Option::Some(v) => v,
1127                        ::core::option::Option::None => unsafe { ::miniextendr_api::error_value::make_rust_condition_value(
1128                            #error_msg, ::miniextendr_api::error_value::kind::NONE_ERR, ::core::option::Option::None, ::core::option::Option::Some(__miniextendr_call),
1129                        ) },
1130                    }
1131                };
1132                (worker, convert)
1133            }
1134            ReturnHandling::OptionIntoR => {
1135                // For Option<T> where Option<T>: IntoR, call into_sexp on the whole Option.
1136                // The worker returns the raw Option<T>; the main thread converts via IntoR.
1137                // None maps to whatever IntoR for Option<T> returns (NULL/NA) — not an error.
1138                // result_ident holds the full Option<T>, so the strict lookup must
1139                // see the full type (checked_option_* helpers).
1140                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1141                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__miniextendr_result"))
            }), ::quote::__private::Option::None)format_ident!("__miniextendr_result");
1142                let conversion = self.sexp_conversion_expr(&result_ident, false);
1143                let unwind_fn = self.worker_conversion_unwind_fn();
1144                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
            ::quote::__private::push_semi(&mut _s);
            ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or_or(&mut _s);
                    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Some");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_call");
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
1145                    {
1146                        let #result_ident = __miniextendr_result;
1147                        #unwind_fn(|| #conversion, ::core::option::Option::Some(__miniextendr_call))
1148                    }
1149                };
1150                (worker, convert)
1151            }
1152            ReturnHandling::OptionClassPayload => {
1153                // Option<Class> under an explicit class wrap: the worker returns the
1154                // Option; the main thread converts Some's payload, None is NULL.
1155                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1156                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__miniextendr_result"))
            }), ::quote::__private::Option::None)format_ident!("__miniextendr_result");
1157                let conversion = self.sexp_conversion_expr(&result_ident, true);
1158                let unwind_fn = self.worker_conversion_unwind_fn();
1159                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or_or(&mut _s);
                    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Some");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_call");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "None");
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1160                    match __miniextendr_result {
1161                        ::core::option::Option::Some(#result_ident) => #unwind_fn(|| #conversion, ::core::option::Option::Some(__miniextendr_call)),
1162                        ::core::option::Option::None => ::miniextendr_api::SEXP::nil(),
1163                    }
1164                };
1165                (worker, convert)
1166            }
1167            // Option<Self>: wrap Some(Self) in an ExternalPtr like the bare-Self path;
1168            // the Option<ExternalPtr<Self>> gives NULL for None.
1169            ReturnHandling::OptionExternalPtr => {
1170                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1171                let unwind_fn = self.worker_conversion_unwind_fn();
1172                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "IntoR");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_sexp");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_result");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "map");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "externalptr");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "ExternalPtr");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "new");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1173                    #unwind_fn(
1174                        || ::miniextendr_api::into_r::IntoR::into_sexp(
1175                            __miniextendr_result.map(::miniextendr_api::externalptr::ExternalPtr::new)
1176                        ),
1177                        ::core::option::Option::Some(__miniextendr_call),
1178                    )
1179                };
1180                (worker, convert)
1181            }
1182            ReturnHandling::ResultUnit => {
1183                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1184                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1185                    match __miniextendr_result {
1186                        ::core::result::Result::Ok(()) => ::miniextendr_api::SEXP::nil(),
1187                        ::core::result::Result::Err(e) => unsafe { ::miniextendr_api::error_value::result_err_condition_value(
1188                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
1189                        ) },
1190                    }
1191                };
1192                (worker, convert)
1193            }
1194            ReturnHandling::ResultSexp => {
1195                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1196                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1197                    match __miniextendr_result {
1198                        ::core::result::Result::Ok(v) => v,
1199                        ::core::result::Result::Err(e) => unsafe { ::miniextendr_api::error_value::result_err_condition_value(
1200                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
1201                        ) },
1202                    }
1203                };
1204                (worker, convert)
1205            }
1206            ReturnHandling::ResultIntoR => {
1207                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1208                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__miniextendr_result"))
            }), ::quote::__private::Option::None)format_ident!("__miniextendr_result");
1209                let conversion = self.sexp_conversion_expr(&result_ident, true);
1210                let unwind_fn = self.worker_conversion_unwind_fn();
1211                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or_or(&mut _s);
                    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Some");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_call");
                            _s
                        });
                    ::quote::__private::push_comma(&mut _s);
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1212                    match __miniextendr_result {
1213                        ::core::result::Result::Ok(#result_ident) => #unwind_fn(
1214                            || #conversion,
1215                            ::core::option::Option::Some(__miniextendr_call),
1216                        ),
1217                        ::core::result::Result::Err(e) => unsafe { ::miniextendr_api::error_value::result_err_condition_value(
1218                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
1219                        ) },
1220                    }
1221                };
1222                (worker, convert)
1223            }
1224            // Result<T, ()>: unit error is a deliberate sentinel — always map to NULL.
1225            // Convert via NullOnErr so IntoR returns R NULL on Err.
1226            ReturnHandling::ResultNullOnErr => {
1227                let result_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
                ::alloc::fmt::format(format_args!("__miniextendr_result"))
            }), ::quote::__private::Option::None)format_ident!("__miniextendr_result");
1228                let unwind_fn = self.worker_conversion_unwind_fn();
1229                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1230                let conversion = self.sexp_conversion_expr(&result_ident, true);
1231                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or_or(&mut _s);
                    ::quote::ToTokens::to_tokens(&conversion, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Some");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_call");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1232                    match __miniextendr_result {
1233                        ::core::result::Result::Ok(#result_ident) => #unwind_fn(|| #conversion, ::core::option::Option::Some(__miniextendr_call)),
1234                        ::core::result::Result::Err(()) => ::miniextendr_api::SEXP::nil(),
1235                    }
1236                };
1237                (worker, convert)
1238            }
1239            // Result<Self, E>: raise on Err like ResultIntoR, but wrap Ok(Self) in an
1240            // ExternalPtr like the bare-Self path rather than routing through IntoR.
1241            ReturnHandling::ResultExternalPtr => {
1242                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1243                let unwind_fn = self.worker_conversion_unwind_fn();
1244                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_ident(&mut _s, "__miniextendr_result");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Ok");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or_or(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "into_r");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "IntoR");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "into_sexp");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "externalptr");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "ExternalPtr");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "new");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "v");
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Option");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Some");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_call");
                            _s
                        });
                    ::quote::__private::push_comma(&mut _s);
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Result");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Err");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "e");
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "error_value");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "result_err_condition_value");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&err_parts, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Option");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Some");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s,
                                        "__miniextendr_call");
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1245                    match __miniextendr_result {
1246                        ::core::result::Result::Ok(v) => #unwind_fn(
1247                            || ::miniextendr_api::into_r::IntoR::into_sexp(
1248                                ::miniextendr_api::externalptr::ExternalPtr::new(v)
1249                            ),
1250                            ::core::option::Option::Some(__miniextendr_call),
1251                        ),
1252                        ::core::result::Result::Err(e) => unsafe { ::miniextendr_api::error_value::result_err_condition_value(
1253                            #err_parts, ::core::option::Option::Some(__miniextendr_call),
1254                        ) },
1255                    }
1256                };
1257                (worker, convert)
1258            }
1259            ReturnHandling::AsListOf => {
1260                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1261                let unwind_fn = self.worker_conversion_unwind_fn();
1262                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "IntoR");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_sexp");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "convert");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "AsList");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_result");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1263                    #unwind_fn(
1264                        || ::miniextendr_api::into_r::IntoR::into_sexp(
1265                            ::miniextendr_api::convert::AsList(__miniextendr_result)
1266                        ),
1267                        ::core::option::Option::Some(__miniextendr_call),
1268                    )
1269                };
1270                (worker, convert)
1271            }
1272            ReturnHandling::AsExternalPtrOf => {
1273                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1274                let unwind_fn = self.worker_conversion_unwind_fn();
1275                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "IntoR");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_sexp");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "convert");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "AsExternalPtr");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_result");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1276                    #unwind_fn(
1277                        || ::miniextendr_api::into_r::IntoR::into_sexp(
1278                            ::miniextendr_api::convert::AsExternalPtr(__miniextendr_result)
1279                        ),
1280                        ::core::option::Option::Some(__miniextendr_call),
1281                    )
1282                };
1283                (worker, convert)
1284            }
1285            ReturnHandling::AsNativeOf => {
1286                let worker = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&call_expr, &mut _s);
    _s
}quote! { #call_expr };
1287                let unwind_fn = self.worker_conversion_unwind_fn();
1288                let convert = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&unwind_fn, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or_or(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_r");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "IntoR");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into_sexp");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "convert");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "AsRNative");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s,
                                "__miniextendr_result");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s,
                        "__miniextendr_call");
                    _s
                });
            ::quote::__private::push_comma(&mut _s);
            _s
        });
    _s
}quote! {
1289                    #unwind_fn(
1290                        || ::miniextendr_api::into_r::IntoR::into_sexp(
1291                            ::miniextendr_api::convert::AsRNative(__miniextendr_result)
1292                        ),
1293                        ::core::option::Option::Some(__miniextendr_call),
1294                    )
1295                };
1296                (worker, convert)
1297            }
1298            ReturnHandling::SelfHandle
1299            | ReturnHandling::SelfHandleResult
1300            | ReturnHandling::SelfHandleOption => {
1301                // The self-handle strategies are only assigned to instance
1302                // methods, which always run on the main thread (the receiver
1303                // borrow / moved value can't cross to the worker). They never
1304                // reach the worker return-handling path.
1305                {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("ReturnHandling::SelfHandle* is instance-only and always uses the main thread")));
}unreachable!(
1306                    "ReturnHandling::SelfHandle* is instance-only and always uses the main thread"
1307                )
1308            }
1309        }
1310    }
1311
1312    /// Returns the unwind protection function for worker-thread conversion steps.
1313    /// Always returns tagged condition SEXP on conversion panics; the R-side wrapper raises.
1314    fn worker_conversion_unwind_fn(&self) -> TokenStream {
1315        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "unwind_protect");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "with_r_unwind_protect");
    _s
}quote! { ::miniextendr_api::unwind_protect::with_r_unwind_protect }
1316    }
1317
1318    /// Returns the SEXP conversion expression for `result_ident`, using strict
1319    /// checked conversion if strict mode is on and the inner return type is lossy,
1320    /// otherwise falling back to `IntoR::into_sexp()`.
1321    ///
1322    /// `result_holds_unwrapped` says what `result_ident` is bound to at runtime:
1323    /// `true` when the arm already unwrapped the declared `Option<T>` /
1324    /// `Result<T, E>` wrapper (so the strict lookup must see the inner `T`),
1325    /// `false` when `result_ident` holds the full declared return type (so
1326    /// `Option<lossy>` must resolve to the `checked_option_*` helpers — passing
1327    /// the stripped inner type there emits a scalar helper call on an `Option`
1328    /// value, which does not compile; caught by the strict-default CI leg).
1329    fn sexp_conversion_expr(
1330        &self,
1331        result_ident: &syn::Ident,
1332        result_holds_unwrapped: bool,
1333    ) -> TokenStream {
1334        if self.strict {
1335            // Extract the type `result_ident` actually holds from the output type
1336            let inner_ty = match &self.output {
1337                syn::ReturnType::Type(_, ty) => {
1338                    let ty = ty.as_ref();
1339                    // Strip an Option<T> / Result<T, E> wrapper only when the
1340                    // calling arm bound the unwrapped value.
1341                    if result_holds_unwrapped
1342                        && let syn::Type::Path(p) = ty
1343                        && let Some(seg) = p.path.segments.last()
1344                    {
1345                        let name = seg.ident.to_string();
1346                        if (name == "Option" || name == "Result")
1347                            && let Some(inner) = first_type_argument(seg)
1348                        {
1349                            Some(inner)
1350                        } else {
1351                            Some(ty)
1352                        }
1353                    } else {
1354                        Some(ty)
1355                    }
1356                }
1357                syn::ReturnType::Default => None,
1358            };
1359
1360            if let Some(inner_ty) = inner_ty.and_then(|ty| {
1361                crate::return_type_analysis::strict_conversion_for_type(ty, result_ident)
1362            }) {
1363                return inner_ty;
1364            }
1365        }
1366
1367        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_r");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IntoR");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into_sexp");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&result_ident, &mut _s);
            _s
        });
    _s
}quote! { ::miniextendr_api::into_r::IntoR::into_sexp(#result_ident) }
1368    }
1369
1370    /// Generates the `R_CallMethodDef` constant for R's `.Call` interface registration.
1371    ///
1372    /// The constant contains the C symbol name, a `DL_FUNC` pointer to the wrapper
1373    /// (obtained via `transmute`), and the argument count. R uses this at package load
1374    /// time (via `R_registerRoutines`) to register the native routine.
1375    fn generate_call_method_def(&self) -> TokenStream {
1376        let fn_ident = &self.fn_ident;
1377        let c_ident = &self.c_ident;
1378        // When skip_wrapper is set, the user-written fn doesn't have the synthetic
1379        // __miniextendr_call SEXP param — use the actual input count. Otherwise
1380        // use build_c_params() which includes __miniextendr_call + self_sexp.
1381        let num_args = if self.skip_wrapper {
1382            self.inputs
1383                .iter()
1384                .filter(|arg| #[allow(non_exhaustive_omitted_patterns)] match arg {
    syn::FnArg::Typed(_) => true,
    _ => false,
}matches!(arg, syn::FnArg::Typed(_)))
1385                .count()
1386        } else {
1387            let (c_params, _, _) = self.build_c_params();
1388            c_params.len()
1389        };
1390        // Use custom call_method_def_ident if set, otherwise use default naming
1391        let call_method_def_ident = self.call_method_def_ident.clone().unwrap_or_else(|| {
1392            if let Some(ref type_ident) = self.type_context {
1393                match ::quote::__private::IdentFragmentAdapter(&type_ident) {
    arg =>
        match ::quote::__private::IdentFragmentAdapter(&fn_ident) {
            arg =>
                ::quote::__private::mk_ident(&::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("call_method_def_{0}_{1}",
                                        arg, arg))
                            }),
                    ::quote::__private::Option::None.or(arg.span()).or(arg.span())),
        },
}format_ident!("call_method_def_{}_{}", type_ident, fn_ident)
1394            } else {
1395                match ::quote::__private::IdentFragmentAdapter(&fn_ident) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("call_method_def_{0}",
                                arg))
                    }), ::quote::__private::Option::None.or(arg.span())),
}format_ident!("call_method_def_{}", fn_ident)
1396            }
1397        });
1398
1399        let registration =
1400            crate::call_method_def::call_method_def(&call_method_def_ident, c_ident, num_args);
1401
1402        let item_label = if let Some(ref type_ident) = self.type_context {
1403            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}::{1}`", type_ident, fn_ident))
    })format!("`{}::{}`", type_ident, fn_ident)
1404        } else {
1405            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", fn_ident))
    })format!("`{}`", fn_ident)
1406        };
1407        let doc = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("R call method definition for {0} (C wrapper: [`{1}`]).",
                item_label, c_ident))
    })format!(
1408            "R call method definition for {} (C wrapper: [`{}`]).",
1409            item_label, c_ident
1410        );
1411        let doc_example = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Value: `R_CallMethodDef {{ name: \"{0}\", numArgs: {1}, fun: <DL_FUNC> }}`",
                c_ident, num_args))
    })format!(
1412            "Value: `R_CallMethodDef {{ name: \"{}\", numArgs: {}, fun: <DL_FUNC> }}`",
1413            c_ident, num_args
1414        );
1415        let source_loc_doc = crate::source_location_doc(self.fn_ident.span());
1416
1417        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&doc_example, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&source_loc_doc, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "concat");
            ::quote::__private::push_bang(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::parse(&mut _s,
                        "\"Generated from source file `\"");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "file");
                    ::quote::__private::push_bang(&mut _s);
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::parse(&mut _s, "\"`.\"");
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&registration, &mut _s);
    _s
}quote! {
1418            #[doc = #doc]
1419            #[doc = #doc_example]
1420            #[doc = #source_loc_doc]
1421            #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
1422            #registration
1423        }
1424    }
1425
1426    /// Generates a rustdoc comment string for the C wrapper function.
1427    ///
1428    /// Includes the original function/method name, thread strategy label, and a
1429    /// cross-reference to the R wrapper constant when there is one.
1430    fn generate_doc_comment(&self, thread_info: &str) -> String {
1431        let item = match self.type_context {
1432            Some(ref type_ident) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1}", type_ident,
                self.fn_ident))
    })format!("{}::{}", type_ident, self.fn_ident),
1433            None => self.fn_ident.to_string(),
1434        };
1435        match self.r_wrapper_const {
1436            Some(ref r_wrapper_const) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("C wrapper for [`{0}`] ({1}). See [`{2}`] for R wrapper.",
                item, thread_info, r_wrapper_const))
    })format!(
1437                "C wrapper for [`{item}`] ({thread_info}). See [`{r_wrapper_const}`] for R wrapper."
1438            ),
1439            None => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("C wrapper for [`{0}`] ({1}).",
                item, thread_info))
    })format!("C wrapper for [`{item}`] ({thread_info})."),
1440        }
1441    }
1442}
1443
1444/// Builder for [`CWrapperContext`].
1445///
1446/// Created via [`CWrapperContext::builder`]. All fields except `fn_ident` and `c_ident`
1447/// (provided at construction) default to empty/false/None. The required `call_expr`
1448/// must be set before calling [`build`](Self::build) or it will panic.
1449///
1450/// Optional fields like `thread_strategy` and `return_handling` are auto-detected from
1451/// the function signature if not explicitly set.
1452pub struct CWrapperContextBuilder {
1453    /// Rust function/method identifier (set at construction).
1454    fn_ident: syn::Ident,
1455    /// R-facing name for raised messages. Defaults to `fn_ident`.
1456    r_name: Option<String>,
1457    /// C wrapper function identifier (set at construction).
1458    c_ident: syn::Ident,
1459    /// R wrapper constant identifier for doc cross-references, if the wrapper has one.
1460    r_wrapper_const: Option<syn::Ident>,
1461    /// Function parameters (excluding `self`). Defaults to empty.
1462    inputs: syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]>,
1463    inferred_signature: Option<TokenStream>,
1464    /// Rust return type. Defaults to `()` (no return type annotation).
1465    output: syn::ReturnType,
1466    /// Pre-call statements emitted before the call expression. Defaults to empty.
1467    pre_call: Vec<TokenStream>,
1468    /// Statements after argument conversion, on R's main thread.
1469    post_conversion: Vec<TokenStream>,
1470    /// The Rust call expression. **Required.**
1471    call_expr: Option<TokenStream>,
1472    /// Thread strategy override. If `None`, defaults to [`ThreadStrategy::MainThread`].
1473    thread_strategy: Option<ThreadStrategy>,
1474    /// Return handling override. If `None`, auto-detected from `output` via [`detect_return_handling`].
1475    return_handling: Option<ReturnHandling>,
1476    /// Enable coercing conversion for all parameters.
1477    coerce_all: bool,
1478    /// Names of individual parameters with coercing conversion enabled.
1479    coerce_params: Vec<String>,
1480    /// Emit `R_CheckUserInterrupt()` before the call.
1481    check_interrupt: bool,
1482    /// Wrap call in `GetRNGstate()`/`PutRNGstate()`.
1483    rng: bool,
1484    /// `#[cfg(...)]` attributes to propagate to generated items.
1485    cfg_attrs: Vec<syn::Attribute>,
1486    /// Type identifier for method context (e.g., `MyStruct`). `None` for standalone functions.
1487    type_context: Option<syn::Ident>,
1488    /// Whether the original method has a `self` receiver.
1489    has_self: bool,
1490    /// Custom `call_method_def` constant name override.
1491    call_method_def_ident: Option<syn::Ident>,
1492    /// Enable strict checked conversions for lossy return types.
1493    strict: bool,
1494    /// How `Err` values become condition parts.
1495    err_parts: ErrPartsMode,
1496    /// Parameter names with `match_arg + several_ok` — forwarded to
1497    /// `RustConversionBuilder::with_match_arg_several_ok` so each element of the
1498    /// Vec is decoded via `match_arg_vec_from_sexp` (enum's `MatchArg::CHOICES`).
1499    match_arg_several_ok_params: Vec<String>,
1500    /// Layered choice parameters — forwarded to
1501    /// `RustConversionBuilder::with_layered_choice`.
1502    layered_choice_params: Vec<(String, crate::rust_conversion_builder::ChoiceLeaf)>,
1503    /// `no_na` parameters, forwarded to `RustConversionBuilder::with_no_na`.
1504    no_na_params: Vec<(String, Option<String>)>,
1505    /// Marked parameters, forwarded to
1506    /// `RustConversionBuilder::with_param_markers`.
1507    param_markers: Vec<(String, Vec<crate::type_inspect::ParamMarker>)>,
1508    /// The parameters' R formals, forwarded to
1509    /// `RustConversionBuilder::with_formals`.
1510    formals: crate::r_wrapper_builder::Formals,
1511    /// When `true`, use original parameter names in C wrapper signature (for rustdoc).
1512    preserve_param_names: bool,
1513    /// Visibility of the generated `extern "C-unwind"` wrapper.
1514    vis: syn::Visibility,
1515    /// Generic parameters for the C wrapper signature.
1516    generics: syn::Generics,
1517    /// When `true`, skip wrapper body but still emit `R_CallMethodDef`.
1518    skip_wrapper: bool,
1519}
1520
1521impl CWrapperContextBuilder {
1522    /// Sets the name R calls the item by, used in the messages the wrapper
1523    /// raises in place of the Rust identifier. Share the resolved name with
1524    /// the R wrapper generator, including renames and postfixes.
1525    pub fn r_name(mut self, r_name: String) -> Self {
1526        self.r_name = Some(r_name);
1527        self
1528    }
1529
1530    /// Sets the R wrapper constant identifier (e.g., `R_WRAPPER_my_func`) the
1531    /// wrapper's rustdoc links to.
1532    pub fn r_wrapper_const(mut self, ident: syn::Ident) -> Self {
1533        self.r_wrapper_const = Some(ident);
1534        self
1535    }
1536
1537    /// Sets the function parameters (excluding `self` receiver).
1538    /// Each input becomes a `SEXP` argument in the C wrapper.
1539    pub fn inputs(
1540        mut self,
1541        inputs: syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]>,
1542    ) -> Self {
1543        self.inputs = inputs;
1544        self
1545    }
1546
1547    /// Infer inherited parameter types from this concrete method item.
1548    pub fn inferred_signature(mut self, callable: TokenStream) -> Self {
1549        self.inferred_signature = Some(callable);
1550        self
1551    }
1552
1553    /// Sets the Rust return type. Used for auto-detecting [`ReturnHandling`]
1554    /// and for strict-mode type inspection.
1555    pub fn output(mut self, output: syn::ReturnType) -> Self {
1556        self.output = output;
1557        self
1558    }
1559
1560    /// Sets pre-call statements emitted before the call expression.
1561    /// Typically used for self-extraction in instance methods.
1562    pub fn pre_call(mut self, stmts: Vec<TokenStream>) -> Self {
1563        self.pre_call = stmts;
1564        self
1565    }
1566
1567    /// Statements that need converted arguments, without shortening their scope.
1568    pub fn post_conversion(mut self, stmts: Vec<TokenStream>) -> Self {
1569        self.post_conversion = stmts;
1570        self
1571    }
1572
1573    /// Sets the Rust call expression (e.g., `my_func(arg0)` or `self_ref.method(arg0)`).
1574    /// **Required** -- [`build`](Self::build) panics if not set.
1575    pub fn call_expr(mut self, expr: TokenStream) -> Self {
1576        self.call_expr = Some(expr);
1577        self
1578    }
1579
1580    /// Overrides the thread strategy. If not called, defaults to [`ThreadStrategy::MainThread`].
1581    pub fn thread_strategy(mut self, strategy: ThreadStrategy) -> Self {
1582        self.thread_strategy = Some(strategy);
1583        self
1584    }
1585
1586    /// Overrides the return handling strategy. If not called, auto-detected from `output`
1587    /// via [`detect_return_handling`].
1588    pub fn return_handling(mut self, handling: ReturnHandling) -> Self {
1589        self.return_handling = Some(handling);
1590        self
1591    }
1592
1593    /// Enables coercing conversion for all parameters via `Rf_coerceVector`.
1594    pub fn coerce_all(mut self) -> Self {
1595        self.coerce_all = true;
1596        self
1597    }
1598
1599    /// Enables coercing conversion for a specific named parameter.
1600    pub fn with_coerce_param(mut self, param_name: String) -> Self {
1601        self.coerce_params.push(param_name);
1602        self
1603    }
1604
1605    /// Enables `R_CheckUserInterrupt()` before the call expression.
1606    pub fn check_interrupt(mut self) -> Self {
1607        self.check_interrupt = true;
1608        self
1609    }
1610
1611    /// Enable RNG state management (GetRNGstate/PutRNGstate).
1612    pub fn rng(mut self) -> Self {
1613        self.rng = true;
1614        self
1615    }
1616
1617    /// Sets `#[cfg(...)]` attributes to propagate to the C wrapper and `call_method_def`.
1618    pub fn cfg_attrs(mut self, attrs: Vec<syn::Attribute>) -> Self {
1619        self.cfg_attrs = attrs;
1620        self
1621    }
1622
1623    /// Sets the type context for methods (e.g., `MyStruct`). Used in doc comments
1624    /// and default `call_method_def` naming.
1625    pub fn type_context(mut self, type_ident: syn::Ident) -> Self {
1626        self.type_context = Some(type_ident);
1627        self
1628    }
1629
1630    /// Marks this as an instance method with a `self` receiver.
1631    /// Causes the C wrapper to include a `self_sexp` parameter.
1632    pub fn has_self(mut self) -> Self {
1633        self.has_self = true;
1634        self
1635    }
1636
1637    /// Enables strict checked conversions for lossy return types (`i64`, `u64`, `isize`,
1638    /// `usize` and their `Vec` variants).
1639    pub fn strict(mut self) -> Self {
1640        self.strict = true;
1641        self
1642    }
1643
1644    /// Choose how `Err` values become condition parts (default: the
1645    /// `RConditionData`/`Debug` probe). See [`ErrPartsMode`].
1646    pub fn err_parts(mut self, mode: ErrPartsMode) -> Self {
1647        self.err_parts = mode;
1648        self
1649    }
1650
1651    /// Record a parameter as `match_arg + several_ok`.
1652    ///
1653    /// Passed through to `RustConversionBuilder::with_match_arg_several_ok`, which
1654    /// switches that parameter's conversion from `TryFromSexp` to
1655    /// `match_arg_vec_from_sexp::<Inner>` so each STRSXP element is validated against
1656    /// the enum's `MatchArg::CHOICES`.
1657    pub fn match_arg_several_ok(mut self, param_name: String) -> Self {
1658        self.match_arg_several_ok_params.push(param_name);
1659        self
1660    }
1661
1662    /// Record a choice parameter whose type wraps the choice in `Missing` /
1663    /// `Option` layers (#1473, #1551).
1664    ///
1665    /// Passed through to `RustConversionBuilder::with_layered_choice`, which
1666    /// decodes the layers outermost first (an omitted argument is
1667    /// `Missing::Absent`, `NULL` is `None`) and the choice itself from `leaf`.
1668    pub fn layered_choice(
1669        mut self,
1670        param_name: String,
1671        leaf: crate::rust_conversion_builder::ChoiceLeaf,
1672    ) -> Self {
1673        self.layered_choice_params.push((param_name, leaf));
1674        self
1675    }
1676
1677    /// Record a `#[miniextendr(no_na)]` parameter (its Rust name) and the
1678    /// author's `no_na(message = "...")`, if any.
1679    ///
1680    /// Passed through to `RustConversionBuilder::with_no_na`, which checks the
1681    /// converted value (`TryFromSexp::__mx_has_na`) right after its binding,
1682    /// for what the type reads as `NA` beyond the R guard's `anyNA()`. An
1683    /// `Either` has no R guard, and its value checks the input instead
1684    /// (`TryFromSexp::__mx_input_has_na`).
1685    pub fn no_na(mut self, param_name: String, message: Option<String>) -> Self {
1686        self.no_na_params.push((param_name, message));
1687        self
1688    }
1689
1690    /// Record a parameter (its Rust name) whose declared type carries the
1691    /// parameter `markers` (`Checked<T>` / `Unchecked<T>`, #1566, outermost
1692    /// first). The inputs hold the inner type; the converted value is wrapped
1693    /// in the markers before the call.
1694    pub fn param_markers(
1695        mut self,
1696        param_name: String,
1697        markers: Vec<crate::type_inspect::ParamMarker>,
1698    ) -> Self {
1699        self.param_markers.push((param_name, markers));
1700        self
1701    }
1702
1703    /// Name each parameter by its R formal (#1842) in the conversion errors
1704    /// (their message and `e$param`); without it, the Rust name without
1705    /// leading underscores.
1706    pub fn formals(mut self, formals: crate::r_wrapper_builder::Formals) -> Self {
1707        self.formals = formals;
1708        self
1709    }
1710
1711    /// Set a custom call_method_def identifier.
1712    ///
1713    /// If not set, the default naming is used:
1714    /// - With type_context: `call_method_def_{type}_{method}`
1715    /// - Without: `call_method_def_{method}`
1716    pub fn call_method_def_ident(mut self, ident: syn::Ident) -> Self {
1717        self.call_method_def_ident = Some(ident);
1718        self
1719    }
1720
1721    /// Preserve original parameter names in the C wrapper signature.
1722    ///
1723    /// When `true`, `build_c_params` uses the original identifier from `inputs` instead
1724    /// of renaming to `arg_N`. Enables rustdoc to show descriptive parameter names.
1725    /// Used by the standalone-fn path; impl methods use the default `arg_N` form.
1726    pub fn preserve_param_names(mut self) -> Self {
1727        self.preserve_param_names = true;
1728        self
1729    }
1730
1731    /// Set the visibility of the generated `extern "C-unwind"` wrapper.
1732    ///
1733    /// Defaults to [`syn::Visibility::Inherited`]. Standalone fns forward the user's
1734    /// declared visibility (`pub`, `pub(crate)`, etc.).
1735    pub fn vis(mut self, vis: syn::Visibility) -> Self {
1736        self.vis = vis;
1737        self
1738    }
1739
1740    /// Set the generic parameters for the C wrapper function signature.
1741    ///
1742    /// Defaults to empty generics. Standalone fns with generic parameters
1743    /// must forward them so the generated wrapper is also generic.
1744    pub fn generics(mut self, generics: syn::Generics) -> Self {
1745        self.generics = generics;
1746        self
1747    }
1748
1749    /// Skip generating the wrapper body and only emit the `R_CallMethodDef`.
1750    ///
1751    /// Use this when the Rust fn is already `extern "C-unwind"` with `#[no_mangle]` or
1752    /// `#[unsafe(no_mangle)]` (the user wrote the C symbol directly). The function still
1753    /// needs to be registered with R via `R_CallMethodDef`.
1754    ///
1755    /// When set, `numArgs` is computed from `inputs` directly (no synthetic
1756    /// `__miniextendr_call` param).
1757    pub fn skip_wrapper(mut self) -> Self {
1758        self.skip_wrapper = true;
1759        self
1760    }
1761
1762    /// Consumes the builder and returns a fully configured [`CWrapperContext`].
1763    ///
1764    /// If `thread_strategy` was not set, defaults to [`ThreadStrategy::MainThread`].
1765    /// If `return_handling` was not set, auto-detects from the `output` type via
1766    /// [`detect_return_handling`].
1767    ///
1768    /// # Panics
1769    ///
1770    /// Panics if `call_expr` was not set.
1771    pub fn build(self) -> CWrapperContext {
1772        let call_expr = self
1773            .call_expr
1774            .expect("call_expr is required for CWrapperContext");
1775
1776        // Detect thread strategy if not explicitly set.
1777        // Main thread is the default for all methods (safer, simpler execution model).
1778        let thread_strategy = self.thread_strategy.unwrap_or(ThreadStrategy::MainThread);
1779
1780        // Detect return handling if not explicitly set
1781        let return_handling = self
1782            .return_handling
1783            .unwrap_or_else(|| detect_return_handling(&self.output, None));
1784
1785        CWrapperContext {
1786            fn_ident: self.fn_ident,
1787            r_name: self.r_name,
1788            c_ident: self.c_ident,
1789            r_wrapper_const: self.r_wrapper_const,
1790            inputs: self.inputs,
1791            inferred_signature: self.inferred_signature,
1792            output: self.output,
1793            pre_call: self.pre_call,
1794            post_conversion: self.post_conversion,
1795            call_expr,
1796            thread_strategy,
1797            return_handling,
1798            coerce_all: self.coerce_all,
1799            coerce_params: self.coerce_params,
1800            check_interrupt: self.check_interrupt,
1801            rng: self.rng,
1802            cfg_attrs: self.cfg_attrs,
1803            type_context: self.type_context,
1804            has_self: self.has_self,
1805            call_method_def_ident: self.call_method_def_ident,
1806            strict: self.strict,
1807            err_parts: self.err_parts,
1808            match_arg_several_ok_params: self.match_arg_several_ok_params,
1809            layered_choice_params: self.layered_choice_params,
1810            no_na_params: self.no_na_params,
1811            param_markers: self.param_markers,
1812            formals: self.formals,
1813            preserve_param_names: self.preserve_param_names,
1814            vis: self.vis,
1815            generics: self.generics,
1816            skip_wrapper: self.skip_wrapper,
1817        }
1818    }
1819}
1820
1821/// Detects the [`ReturnHandling`] strategy from a return type: the one rule for
1822/// standalone functions, inherent methods and trait methods.
1823///
1824/// - No return type annotation (`Default`) maps to [`ReturnHandling::Unit`].
1825/// - An explicit type is analyzed by [`detect_return_handling_from_type`].
1826/// - `wrap` is the explicit class wrap (`WrapAs*<T>` marker or `wrap = "..."`
1827///   attribute) when there is one: an `Option<Class>` under it converts its payload
1828///   ([`ReturnHandling::OptionClassPayload`]), since no `IntoR for Option<Class>`
1829///   can exist.
1830pub fn detect_return_handling(
1831    output: &syn::ReturnType,
1832    wrap: Option<&crate::return_wrap::ReturnWrap>,
1833) -> ReturnHandling {
1834    match output {
1835        syn::ReturnType::Default => ReturnHandling::Unit,
1836        syn::ReturnType::Type(_, ty) => match detect_return_handling_from_type(ty) {
1837            ReturnHandling::OptionIntoR if wrap.is_some_and(|wrap| wrap.is_optional_class()) => {
1838                ReturnHandling::OptionClassPayload
1839            }
1840            handling => handling,
1841        },
1842    }
1843}
1844
1845/// Determines the [`ReturnHandling`] variant for a concrete `syn::Type`.
1846///
1847/// Recognition rules:
1848/// - `()` -> [`Unit`](ReturnHandling::Unit)
1849/// - `Self` -> [`ExternalPtr`](ReturnHandling::ExternalPtr)
1850/// - `SEXP` -> [`RawSexp`](ReturnHandling::RawSexp)
1851/// - `Option<T>` -> [`OptionUnit`](ReturnHandling::OptionUnit) for `T = ()`,
1852///   [`OptionSexp`](ReturnHandling::OptionSexp) for `T = SEXP`,
1853///   [`OptionExternalPtr`](ReturnHandling::OptionExternalPtr) for `T = Self`, and
1854///   [`OptionIntoR`](ReturnHandling::OptionIntoR) for every other `T`
1855/// - `Result<T, E>` -> recurses into `T` for `ResultUnit`, `ResultSexp`, `ResultExternalPtr`
1856///   (`T = Self`), or `ResultIntoR`
1857/// - Anything else -> [`IntoR`](ReturnHandling::IntoR)
1858fn detect_return_handling_from_type(ty: &syn::Type) -> ReturnHandling {
1859    match ty {
1860        // Unit tuple ()
1861        syn::Type::Tuple(t) if t.elems.is_empty() => ReturnHandling::Unit,
1862
1863        // Self - wrap in ExternalPtr
1864        syn::Type::Path(p)
1865            if p.path
1866                .segments
1867                .last()
1868                .map(|s| s.ident == "Self")
1869                .unwrap_or(false) =>
1870        {
1871            ReturnHandling::ExternalPtr
1872        }
1873
1874        // SEXP - pass through
1875        syn::Type::Path(p)
1876            if p.path
1877                .segments
1878                .last()
1879                .map(|s| s.ident == "SEXP")
1880                .unwrap_or(false) =>
1881        {
1882            ReturnHandling::RawSexp
1883        }
1884
1885        // Option<T>
1886        syn::Type::Path(p)
1887            if p.path
1888                .segments
1889                .last()
1890                .map(|s| s.ident == "Option")
1891                .unwrap_or(false) =>
1892        {
1893            if let Some(inner_ty) = first_type_argument(p.path.segments.last().unwrap()) {
1894                match inner_ty {
1895                    syn::Type::Tuple(t) if t.elems.is_empty() => ReturnHandling::OptionUnit,
1896                    syn::Type::Path(ip)
1897                        if ip
1898                            .path
1899                            .segments
1900                            .last()
1901                            .map(|s| s.ident == "SEXP")
1902                            .unwrap_or(false) =>
1903                    {
1904                        ReturnHandling::OptionSexp
1905                    }
1906                    // Option<Self>: a lookup-shaped fallible constructor. Wrap
1907                    // `Some(Self)` in an ExternalPtr like the bare-`Self` path, rather
1908                    // than routing it through `IntoR` (which `Self` generally lacks).
1909                    // Symmetric with `Result<Self, E>` -> `ResultExternalPtr` below.
1910                    syn::Type::Path(ip)
1911                        if ip
1912                            .path
1913                            .segments
1914                            .last()
1915                            .map(|s| s.ident == "Self")
1916                            .unwrap_or(false) =>
1917                    {
1918                        ReturnHandling::OptionExternalPtr
1919                    }
1920                    _ => ReturnHandling::OptionIntoR,
1921                }
1922            } else {
1923                ReturnHandling::OptionIntoR
1924            }
1925        }
1926
1927        // Result<T, E>
1928        syn::Type::Path(p)
1929            if p.path
1930                .segments
1931                .last()
1932                .map(|s| s.ident == "Result")
1933                .unwrap_or(false) =>
1934        {
1935            let seg = p.path.segments.last().unwrap();
1936            // Special case: Result<T, ()> — unit error is a deliberate sentinel that maps to
1937            // R NULL, not a failure.
1938            let err_is_unit = crate::second_type_argument(seg)
1939                .is_some_and(|ty| #[allow(non_exhaustive_omitted_patterns)] match ty {
    syn::Type::Tuple(t) if t.elems.is_empty() => true,
    _ => false,
}matches!(ty, syn::Type::Tuple(t) if t.elems.is_empty()));
1940            if err_is_unit {
1941                return ReturnHandling::ResultNullOnErr;
1942            }
1943            if let Some(ok_ty) = first_type_argument(seg) {
1944                match ok_ty {
1945                    syn::Type::Tuple(t) if t.elems.is_empty() => ReturnHandling::ResultUnit,
1946                    syn::Type::Path(ip)
1947                        if ip
1948                            .path
1949                            .segments
1950                            .last()
1951                            .map(|s| s.ident == "SEXP")
1952                            .unwrap_or(false) =>
1953                    {
1954                        ReturnHandling::ResultSexp
1955                    }
1956                    // Result<Self, E>: a fallible constructor-shaped method. Wrap
1957                    // `Ok(Self)` in an ExternalPtr like the bare-`Self` path, rather
1958                    // than routing it through `IntoR` (which `Self` generally lacks).
1959                    syn::Type::Path(ip)
1960                        if ip
1961                            .path
1962                            .segments
1963                            .last()
1964                            .map(|s| s.ident == "Self")
1965                            .unwrap_or(false) =>
1966                    {
1967                        ReturnHandling::ResultExternalPtr
1968                    }
1969                    _ => ReturnHandling::ResultIntoR,
1970                }
1971            } else {
1972                ReturnHandling::ResultIntoR
1973            }
1974        }
1975
1976        // Everything else - use IntoR
1977        _ => ReturnHandling::IntoR,
1978    }
1979}
1980
1981/// Extracts the first generic type argument from a path segment's angle-bracketed arguments.
1982///
1983/// For example, given `Option<String>`, returns `Some(&String)`.
1984/// Returns `None` if the segment has no angle-bracketed arguments or no type arguments.
1985fn first_type_argument(seg: &syn::PathSegment) -> Option<&syn::Type> {
1986    if let syn::PathArguments::AngleBracketed(ab) = &seg.arguments {
1987        for arg in ab.args.iter() {
1988            if let syn::GenericArgument::Type(ty) = arg {
1989                return Some(ty);
1990            }
1991        }
1992    }
1993    None
1994}
1995
1996#[cfg(test)]
1997mod tests;