Skip to main content

Module sidecar

Module sidecar 

Source
Expand description

Typed sidecar fields: Sidecar<T> keeps a Rust-typed value in the external pointer’s prot list.

A Rust struct cannot root an R value: the GC doesn’t trace Rust memory, so a SEXP stored in a struct field is freed as soon as R drops its own references. A Sidecar<T> field holds no data of its own once the struct is wrapped. Its value lives in the external pointer’s protection list, after the type ID and the user slot, so the pointer roots it for as long as the pointer is reachable, and saveRDS() writes it with the pointer. The struct holds nothing that points back at its pointer: the value is read and written through the ExternalPtr<T> handle, which keeps the pointer alive for as long as it exists (#1856).

The type is named in one place (this module) and re-exported from crate::externalptr; its final name is #1857.

Structs§

Pending 🔒
A value on its way into a slot: its R object, rooted from the moment the Sidecar holds it until a slot owns the GC edge (#2216).
PendingRoot 🔒
Only the pool key crosses threads, as with an owning ExternalPtr. Cloning a pending value needs no R call; the last copy releases the root.
Sidecar
A sidecar field whose value R roots: it lives in the external pointer’s protection list, typed as T on the Rust side.

Enums§

Refused 🔒
What an R accessor’s receiver holds instead of a live T (#1920).

Constants§

SLOT_NAMES 🔒
Each type’s slot names, preserved for the session and shared by every protection list of the type: "" for the type ID and the user slot, then the Sidecar fields’ R names, in slot order.

Traits§

SidecarField 👻
A Sidecar<T> field, as the handle sees it through the TypedExternal::__mx_visit_sidecars hook the derive emits. Every method runs on R’s main thread.

Functions§

assert_main_thread 🔒
Panics unless this is R’s main thread. No R API: the message names the field and the owning type.
checked_prot 🔒 ⚠
The prot list of the external pointer x carries (sidecar_receiver), after checking that it points to a T, and the live T’s RefCell when it still has an address. Allocates nothing for a pointer, a list or an environment receiver.
convert_slot 🔒
The element of prot at at, the slot of Sidecar field name, converted to T.
copy_sidecar_slots 🔒 ⚠
Copies every Sidecar slot of the pointer source into the pointer target: the two share the R values until one side writes a field.
discard_pending_sidecars 🔒
Drops every pending value of value’s Sidecar fields.
flush_sidecars 🔒
Moves every pending value of value’s Sidecar fields into its slot of prot, the protection list of the pointer holding value. On R’s main thread.
has_slot_names 🔒
Whether the saved protection list prot carries slot names.
init_erased_sidecars 🔒 ⚠
Initializes the slots of a trait-ABI owner using the ordinary sidecar layout and visitation hook. The Rust allocation remains erased storage; it must never be wrapped as ExternalPtr<T> (which expects Any storage).
init_sidecars 🔒 ⚠
Flushes a freshly wrapped value’s pending values into its pointer’s protection list: the three construction sites and restore_after_consuming call this once the EXTPTRSXP exists.
is_type_id_symbol 🔒
Whether sym is the symbol of T’s type ID.
load_sidecars 🔒
Reads every slot of prot, the protection list of the pointer value is leaving, back into its Sidecar field as a pending value (unless one is pending already). On R’s main thread.
missing_slot 🔒
Raises the classed error for a read of Sidecar field name that a save of an O has no slot for.
name_slots 🔒 ⚠
Names prot’s slots after T’s Sidecar fields. A save then keeps the names, so the version that reads it finds each field by name (saved_slot), whatever fields it added, removed or reordered since. The names vector is the type’s own, built once; this allocates only the attribute’s cell.
no_handle_classes 🔒
The classes of refuse_no_handle: restored, then field_error, then NO_HANDLE_CLASS, each class once at its last place. The two lists usually end in the package’s one parent class (["pkg_saved", "pkg_error"] and ["pkg_field", "pkg_error"]), which then follows both specific classes, as a class vector goes from specific to general.
prot_index 🔒
The protection-list position of Sidecar field index.
refusal_message 🔒
The message of a receiver refusal (#1920): the type’s own (TypedExternal::FIELD_ERROR_MESSAGE), else one naming receiver’s R class, which is what the user sees (the field methods dispatched on it), else, for a receiver without a class, one naming the Rust type.
refuse_no_handle 🔒
Raises the error for a receiver that carries no external pointer (#1901): NO_HANDLE_CLASS, with the type’s field-error classes (TypedExternal::FIELD_ERROR_CLASS, #1899) in front, and for a list or an environment, the shape an earlier release of a package may have written to disk, its restored classes (TypedExternal::RESTORED_ERROR_CLASS) in front of those: a package refuses such a save as it refuses a restored pointer, with its restored message (TypedExternal::RESTORED_ERROR_MESSAGE) when it sets one. Another receiver (an atomic vector given the class) was never saved, so it gets neither (#1919).
refuse_other_type 🔒
Raises the error for a receiver whose pointer is not a T (a pointer of another type, or one without an address that T did not build), worded by refusal_message, with the type’s field-error classes (TypedExternal::FIELD_ERROR_CLASS, #1899) in front. A type without them gets the plain panic.
saved_slot 🔒
The position in the saved protection list prot of Sidecar field index, named name: found by name when the save carries slot names, else by position (a save by this version made before slots were named). None when the save has no slot for the field.
sidecar_get 👻
Reads T’s Sidecar field index of the object ptr holds, after moving the field’s pending value into the slot.
sidecar_r_cell 🔒 ⚠
The body of sidecar_r_struct and sidecar_r_struct_mut: the RefCell of the struct behind the pointer x carries (sidecar_receiver).
sidecar_r_check 👻 ⚠
Checks that x carries an external pointer to a T (sidecar_receiver), live or (without require_live) read back by readRDS(), before a setter validates its value.
sidecar_r_get 👻 ⚠
Reads T’s Sidecar field index from the external pointer x carries (sidecar_receiver).
sidecar_r_live 👻 ⚠
Whether the receiver x (a pointer, or an object carrying one) still has its Rust value, for the field methods of a type with #[externalptr(restored(refuse = "every_read"))] (#1901), which ask before a read that never reaches an accessor (names(), a name that is not a field).
sidecar_r_set 👻 ⚠
Stores value, which the caller validated with TryFromSexp::<T>, in T’s Sidecar field index of the external pointer x carries (sidecar_receiver).
sidecar_r_struct 👻 ⚠
The live T of the external pointer x carries (sidecar_receiver), borrowed shared, for the R getters of a struct field (a field that is not a Sidecar). A pointer without an address is refused: with the classed restored-object errors when T built it (refuse_restored), else as a null pointer (refusal_message).
sidecar_r_struct_mut 👻 ⚠
The live T of the external pointer x carries, borrowed mutably, for the R setters of a struct field; see sidecar_r_struct.
sidecar_receiver 🔒 ⚠
The external pointer an R accessor’s receiver x carries: x itself, or the pointer an R6 / S4 / S7 handle, an environment or a list holds in .ptr, the shapes an instance method’s receiver takes (unwrap_class_handle). So Type_get_f(x) and the $ / [[ field methods of r_data_accessors read a list that carries the handle (#1848). A bare pointer costs one TYPEOF compare; an S4 receiver reads its ptr slot through methods::slot(), which allocates. The pointer is reachable from x, which the caller’s .Call() frame roots.
sidecar_require_live 👻
Reads the require_live flag the R accessors’ .Call()s pass: TRUE from the $ / [[ / $<- / [[<- field methods, which refuse a restored pointer, FALSE from the standalone accessors, the R6 bindings and the S7 properties, which read a save (#1891). Anything but TRUE reads as false.
sidecar_set 👻
Stores value in T’s Sidecar field index of the object ptr holds, dropping the field’s pending value, which this write supersedes.
sidecar_try_saved 👻
T’s Sidecar field index, named name, as the save saved kept it, or None when the save has no slot for it: a field added after the version that saved the object.