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
Sidecarholds it until a slot owns the GC edge (#2216). - Pending
Root 🔒 - 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
Ton 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 theSidecarfields’ R names, in slot order.
Traits§
- Sidecar
Field 👻 - A
Sidecar<T>field, as the handle sees it through theTypedExternal::__mx_visit_sidecarshook 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
protlist of the external pointerxcarries (sidecar_receiver), after checking that it points to aT, and the liveT’sRefCellwhen it still has an address. Allocates nothing for a pointer, a list or an environment receiver. - convert_
slot 🔒 - The element of
protatat, the slot ofSidecarfieldname, converted toT. - copy_
sidecar_ 🔒 ⚠slots - Copies every
Sidecarslot of the pointersourceinto the pointertarget: the two share the R values until one side writes a field. - discard_
pending_ 🔒sidecars - Drops every pending value of
value’sSidecarfields. - flush_
sidecars 🔒 - Moves every pending value of
value’sSidecarfields into its slot ofprot, the protection list of the pointer holdingvalue. On R’s main thread. - has_
slot_ 🔒names - Whether the saved protection list
protcarries 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 expectsAnystorage). - init_
sidecars 🔒 ⚠ - Flushes a freshly wrapped value’s pending values into its pointer’s
protection list: the three construction sites and
restore_after_consumingcall this once theEXTPTRSXPexists. - is_
type_ 🔒id_ symbol - Whether
symis the symbol ofT’s type ID. - load_
sidecars 🔒 - Reads every slot of
prot, the protection list of the pointervalueis leaving, back into itsSidecarfield as a pending value (unless one is pending already). On R’s main thread. - missing_
slot 🔒 - Raises the classed error for a read of
Sidecarfieldnamethat a save of anOhas no slot for. - name_
slots 🔒 ⚠ - Names
prot’s slots afterT’sSidecarfields. 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, thenfield_error, thenNO_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
Sidecarfieldindex. - refusal_
message 🔒 - The message of a receiver refusal (#1920): the type’s own
(
TypedExternal::FIELD_ERROR_MESSAGE), else one namingreceiver’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 thatTdid not build), worded byrefusal_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
protofSidecarfieldindex, namedname: found by name when the save carries slot names, else by position (a save by this version made before slots were named).Nonewhen the save has no slot for the field. - sidecar_
get 👻 - Reads
T’sSidecarfieldindexof the objectptrholds, after moving the field’s pending value into the slot. - sidecar_
r_ 🔒 ⚠cell - The body of
sidecar_r_structandsidecar_r_struct_mut: theRefCellof the struct behind the pointerxcarries (sidecar_receiver). - sidecar_
r_ 👻 ⚠check - Checks that
xcarries an external pointer to aT(sidecar_receiver), live or (withoutrequire_live) read back byreadRDS(), before a setter validates its value. - sidecar_
r_ 👻 ⚠get - Reads
T’sSidecarfieldindexfrom the external pointerxcarries (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 withTryFromSexp::<T>, inT’sSidecarfieldindexof the external pointerxcarries (sidecar_receiver). - sidecar_
r_ 👻 ⚠struct - The live
Tof the external pointerxcarries (sidecar_receiver), borrowed shared, for the R getters of a struct field (a field that is not aSidecar). A pointer without an address is refused: with the classed restored-object errors whenTbuilt it (refuse_restored), else as a null pointer (refusal_message). - sidecar_
r_ 👻 ⚠struct_ mut - The live
Tof the external pointerxcarries, borrowed mutably, for the R setters of a struct field; seesidecar_r_struct. - sidecar_
receiver 🔒 ⚠ - The external pointer an R accessor’s receiver
xcarries:xitself, 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). SoType_get_f(x)and the$/[[field methods ofr_data_accessorsread a list that carries the handle (#1848). A bare pointer costs oneTYPEOFcompare; an S4 receiver reads itsptrslot throughmethods::slot(), which allocates. The pointer is reachable fromx, which the caller’s.Call()frame roots. - sidecar_
require_ 👻live - Reads the
require_liveflag the R accessors’.Call()s pass:TRUEfrom the$/[[/$<-/[[<-field methods, which refuse a restored pointer,FALSEfrom the standalone accessors, the R6 bindings and the S7 properties, which read a save (#1891). Anything butTRUEreads asfalse. - sidecar_
set 👻 - Stores
valueinT’sSidecarfieldindexof the objectptrholds, dropping the field’s pending value, which this write supersedes. - sidecar_
try_ 👻saved T’sSidecarfieldindex, namedname, as the savesavedkept it, orNonewhen the save has no slot for it: a field added after the version that saved the object.