1use crate::altrep_traits::{
33 AltComplex, AltInteger, AltList, AltLogical, AltRaw, AltReal, AltString, AltVec, Altrep,
34 AltrepGuard,
35};
36use crate::sys::altrep::R_altrep_class_t;
37use crate::{R_xlen_t, Rboolean, Rbyte, Rcomplex, SEXP, SEXPTYPE};
38use core::ffi::c_void;
39
40#[inline(always)]
51fn guarded_altrep_call<T: Altrep, F, R>(f: F) -> R
52where
53 F: FnOnce() -> R,
54{
55 match T::GUARD {
56 AltrepGuard::Unsafe => f(),
57 AltrepGuard::RustUnwind => crate::ffi_guard::guarded_ffi_call(
58 f,
59 crate::ffi_guard::GuardMode::CatchUnwind,
60 crate::panic_telemetry::PanicSource::Altrep,
61 ),
62 AltrepGuard::RUnwind => guarded_altrep_r_call(f),
63 }
64}
65
66#[inline(always)]
69fn guarded_altrep_r_call<R>(f: impl FnOnce() -> R) -> R {
70 crate::ffi_guard::guarded_ffi_call(
71 f,
72 crate::ffi_guard::GuardMode::RUnwind,
73 crate::panic_telemetry::PanicSource::Altrep,
74 )
75}
76
77#[inline(always)]
79fn guarded_altrep_sexp_call(f: impl FnOnce() -> SEXP) -> SEXP {
80 let (result, _root) = guarded_altrep_r_call(|| {
81 let result = f();
82 let root = (!result.is_null_ptr()).then(|| unsafe { crate::OwnedProtect::new(result) });
85 (result, root)
86 });
87 result
88}
89
90pub unsafe extern "C-unwind" fn t_length<T: Altrep>(x: SEXP) -> R_xlen_t {
96 guarded_altrep_call::<T, _, _>(|| T::length(x))
97}
98
99pub unsafe extern "C-unwind" fn t_duplicate<T: Altrep>(x: SEXP, deep: Rboolean) -> SEXP {
103 guarded_altrep_sexp_call(|| T::duplicate(x, #[allow(non_exhaustive_omitted_patterns)] match deep {
Rboolean::TRUE => true,
_ => false,
}matches!(deep, Rboolean::TRUE)))
104}
105
106pub unsafe extern "C-unwind" fn t_duplicate_ex<T: Altrep>(x: SEXP, deep: Rboolean) -> SEXP {
110 guarded_altrep_sexp_call(|| T::duplicate_ex(x, #[allow(non_exhaustive_omitted_patterns)] match deep {
Rboolean::TRUE => true,
_ => false,
}matches!(deep, Rboolean::TRUE)))
111}
112
113pub unsafe extern "C-unwind" fn t_inspect<T: Altrep>(
117 x: SEXP,
118 pre: i32,
119 deep: i32,
120 pvec: i32,
121 inspect_subtree: Option<unsafe extern "C-unwind" fn(SEXP, i32, i32, i32)>,
122) -> Rboolean {
123 guarded_altrep_call::<T, _, _>(|| {
124 if T::inspect(x, pre, deep, pvec, inspect_subtree) {
125 Rboolean::TRUE
126 } else {
127 Rboolean::FALSE
128 }
129 })
130}
131
132pub unsafe extern "C-unwind" fn t_serialized_state<T: Altrep>(x: SEXP) -> SEXP {
136 guarded_altrep_sexp_call(|| T::serialized_state(x))
137}
138
139pub unsafe extern "C-unwind" fn t_unserialize<T: Altrep>(class: SEXP, state: SEXP) -> SEXP {
143 guarded_altrep_sexp_call(|| T::unserialize(class, state))
144}
145
146pub unsafe extern "C-unwind" fn t_unserialize_ex<T: Altrep>(
150 class: SEXP,
151 state: SEXP,
152 attr: SEXP,
153 objf: ::std::os::raw::c_int,
154 levs: ::std::os::raw::c_int,
155) -> SEXP {
156 guarded_altrep_sexp_call(|| T::unserialize_ex(class, state, attr, objf, levs))
157}
158
159pub unsafe extern "C-unwind" fn t_coerce<T: Altrep>(x: SEXP, to_type: SEXPTYPE) -> SEXP {
163 guarded_altrep_sexp_call(|| T::coerce(x, to_type))
164}
165pub unsafe extern "C-unwind" fn t_dataptr<T: AltVec>(x: SEXP, w: Rboolean) -> *mut c_void {
173 guarded_altrep_r_call(|| T::dataptr(x, #[allow(non_exhaustive_omitted_patterns)] match w {
Rboolean::TRUE => true,
_ => false,
}matches!(w, Rboolean::TRUE)))
174}
175
176pub unsafe extern "C-unwind" fn t_dataptr_or_null<T: AltVec>(x: SEXP) -> *const c_void {
180 guarded_altrep_call::<T, _, _>(|| T::dataptr_or_null(x))
181}
182
183pub unsafe extern "C-unwind" fn t_extract_subset<T: AltVec>(
187 x: SEXP,
188 indx: SEXP,
189 call: SEXP,
190) -> SEXP {
191 guarded_altrep_sexp_call(|| T::extract_subset(x, indx, call))
192}
193pub unsafe extern "C-unwind" fn t_int_elt<T: AltInteger>(x: SEXP, i: R_xlen_t) -> i32 {
201 guarded_altrep_call::<T, _, _>(|| T::elt(x, i))
202}
203
204pub unsafe extern "C-unwind" fn t_int_get_region<T: AltInteger>(
208 x: SEXP,
209 i: R_xlen_t,
210 n: R_xlen_t,
211 out: *mut i32,
212) -> R_xlen_t {
213 if n <= 0 {
214 return 0;
215 }
216 let buf = unsafe { crate::altrep_impl::altrep_region_buf(out, n as usize) };
217 guarded_altrep_call::<T, _, _>(|| T::get_region(x, i, n, buf))
218}
219
220pub unsafe extern "C-unwind" fn t_int_is_sorted<T: AltInteger>(x: SEXP) -> i32 {
224 guarded_altrep_call::<T, _, _>(|| T::is_sorted(x))
225}
226
227pub unsafe extern "C-unwind" fn t_int_no_na<T: AltInteger>(x: SEXP) -> i32 {
231 guarded_altrep_call::<T, _, _>(|| T::no_na(x))
232}
233
234pub unsafe extern "C-unwind" fn t_int_sum<T: AltInteger>(x: SEXP, narm: Rboolean) -> SEXP {
238 guarded_altrep_sexp_call(|| T::sum(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
239}
240
241pub unsafe extern "C-unwind" fn t_int_min<T: AltInteger>(x: SEXP, narm: Rboolean) -> SEXP {
245 guarded_altrep_sexp_call(|| T::min(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
246}
247
248pub unsafe extern "C-unwind" fn t_int_max<T: AltInteger>(x: SEXP, narm: Rboolean) -> SEXP {
252 guarded_altrep_sexp_call(|| T::max(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
253}
254pub unsafe extern "C-unwind" fn t_real_elt<T: AltReal>(x: SEXP, i: R_xlen_t) -> f64 {
262 guarded_altrep_call::<T, _, _>(|| T::elt(x, i))
263}
264
265pub unsafe extern "C-unwind" fn t_real_get_region<T: AltReal>(
269 x: SEXP,
270 i: R_xlen_t,
271 n: R_xlen_t,
272 out: *mut f64,
273) -> R_xlen_t {
274 if n <= 0 {
275 return 0;
276 }
277 let buf = unsafe { crate::altrep_impl::altrep_region_buf(out, n as usize) };
278 guarded_altrep_call::<T, _, _>(|| T::get_region(x, i, n, buf))
279}
280
281pub unsafe extern "C-unwind" fn t_real_is_sorted<T: AltReal>(x: SEXP) -> i32 {
285 guarded_altrep_call::<T, _, _>(|| T::is_sorted(x))
286}
287
288pub unsafe extern "C-unwind" fn t_real_no_na<T: AltReal>(x: SEXP) -> i32 {
292 guarded_altrep_call::<T, _, _>(|| T::no_na(x))
293}
294
295pub unsafe extern "C-unwind" fn t_real_sum<T: AltReal>(x: SEXP, narm: Rboolean) -> SEXP {
299 guarded_altrep_sexp_call(|| T::sum(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
300}
301
302pub unsafe extern "C-unwind" fn t_real_min<T: AltReal>(x: SEXP, narm: Rboolean) -> SEXP {
306 guarded_altrep_sexp_call(|| T::min(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
307}
308
309pub unsafe extern "C-unwind" fn t_real_max<T: AltReal>(x: SEXP, narm: Rboolean) -> SEXP {
313 guarded_altrep_sexp_call(|| T::max(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
314}
315pub unsafe extern "C-unwind" fn t_lgl_elt<T: AltLogical>(x: SEXP, i: R_xlen_t) -> i32 {
323 guarded_altrep_call::<T, _, _>(|| T::elt(x, i))
324}
325
326pub unsafe extern "C-unwind" fn t_lgl_get_region<T: AltLogical>(
330 x: SEXP,
331 i: R_xlen_t,
332 n: R_xlen_t,
333 out: *mut i32,
334) -> R_xlen_t {
335 if n <= 0 {
336 return 0;
337 }
338 let buf = unsafe { crate::altrep_impl::altrep_region_buf(out, n as usize) };
339 guarded_altrep_call::<T, _, _>(|| T::get_region(x, i, n, buf))
340}
341
342pub unsafe extern "C-unwind" fn t_lgl_is_sorted<T: AltLogical>(x: SEXP) -> i32 {
346 guarded_altrep_call::<T, _, _>(|| T::is_sorted(x))
347}
348
349pub unsafe extern "C-unwind" fn t_lgl_no_na<T: AltLogical>(x: SEXP) -> i32 {
353 guarded_altrep_call::<T, _, _>(|| T::no_na(x))
354}
355
356pub unsafe extern "C-unwind" fn t_lgl_sum<T: AltLogical>(x: SEXP, narm: Rboolean) -> SEXP {
360 guarded_altrep_sexp_call(|| T::sum(x, #[allow(non_exhaustive_omitted_patterns)] match narm {
Rboolean::TRUE => true,
_ => false,
}matches!(narm, Rboolean::TRUE)))
361}
362
363pub unsafe extern "C-unwind" fn t_raw_elt<T: AltRaw>(x: SEXP, i: R_xlen_t) -> Rbyte {
372 guarded_altrep_call::<T, _, _>(|| T::elt(x, i))
373}
374
375pub unsafe extern "C-unwind" fn t_raw_get_region<T: AltRaw>(
379 x: SEXP,
380 i: R_xlen_t,
381 n: R_xlen_t,
382 out: *mut Rbyte,
383) -> R_xlen_t {
384 if n <= 0 {
385 return 0;
386 }
387 let buf = unsafe { crate::altrep_impl::altrep_region_buf(out, n as usize) };
388 guarded_altrep_call::<T, _, _>(|| T::get_region(x, i, n, buf))
389}
390pub unsafe extern "C-unwind" fn t_cplx_elt<T: AltComplex>(x: SEXP, i: R_xlen_t) -> Rcomplex {
398 guarded_altrep_call::<T, _, _>(|| T::elt(x, i))
399}
400
401pub unsafe extern "C-unwind" fn t_cplx_get_region<T: AltComplex>(
405 x: SEXP,
406 i: R_xlen_t,
407 n: R_xlen_t,
408 out: *mut Rcomplex,
409) -> R_xlen_t {
410 if n <= 0 {
411 return 0;
412 }
413 let buf = unsafe { crate::altrep_impl::altrep_region_buf(out, n as usize) };
414 guarded_altrep_call::<T, _, _>(|| T::get_region(x, i, n, buf))
415}
416pub unsafe extern "C-unwind" fn t_str_elt<T: AltString>(x: SEXP, i: R_xlen_t) -> SEXP {
424 guarded_altrep_sexp_call(|| T::elt(x, i))
425}
426
427pub unsafe extern "C-unwind" fn t_str_set_elt<T: AltString>(x: SEXP, i: R_xlen_t, v: SEXP) {
431 guarded_altrep_r_call(|| T::set_elt(x, i, v))
432}
433
434pub unsafe extern "C-unwind" fn t_str_is_sorted<T: AltString>(x: SEXP) -> i32 {
438 guarded_altrep_call::<T, _, _>(|| T::is_sorted(x))
439}
440
441pub unsafe extern "C-unwind" fn t_str_no_na<T: AltString>(x: SEXP) -> i32 {
445 guarded_altrep_call::<T, _, _>(|| T::no_na(x))
446}
447pub unsafe extern "C-unwind" fn t_list_elt<T: AltList>(x: SEXP, i: R_xlen_t) -> SEXP {
455 guarded_altrep_sexp_call(|| T::elt(x, i))
456}
457
458pub unsafe extern "C-unwind" fn t_list_set_elt<T: AltList>(x: SEXP, i: R_xlen_t, v: SEXP) {
462 guarded_altrep_r_call(|| T::set_elt(x, i, v))
463}
464pub unsafe fn install_base<T: Altrep>(cls: R_altrep_class_t) {
472 unsafe { cls.set_length_method(Some(t_length::<T>)) };
474
475 if T::HAS_SERIALIZED_STATE {
477 unsafe { cls.set_serialized_state_method(Some(t_serialized_state::<T>)) };
478 }
479 if T::HAS_UNSERIALIZE {
480 unsafe { cls.set_unserialize_method(Some(t_unserialize::<T>)) };
481 }
482 if T::HAS_UNSERIALIZE_EX {
483 unsafe { cls.set_unserialize_ex_method(Some(t_unserialize_ex::<T>)) };
484 }
485 if T::HAS_DUPLICATE {
486 unsafe { cls.set_duplicate_method(Some(t_duplicate::<T>)) };
487 }
488 if T::HAS_DUPLICATE_EX {
489 unsafe { cls.set_duplicate_ex_method(Some(t_duplicate_ex::<T>)) };
490 }
491 if T::HAS_COERCE {
492 unsafe { cls.set_coerce_method(Some(t_coerce::<T>)) };
493 }
494 if T::HAS_INSPECT {
495 unsafe { cls.set_inspect_method(Some(t_inspect::<T>)) };
496 }
497}
498
499pub unsafe fn install_vec<T: AltVec>(cls: R_altrep_class_t) {
503 if T::HAS_DATAPTR {
504 unsafe { cls.set_dataptr_method(Some(t_dataptr::<T>)) };
505 }
506 if T::HAS_DATAPTR_OR_NULL {
507 unsafe { cls.set_dataptr_or_null_method(Some(t_dataptr_or_null::<T>)) };
508 }
509 if T::HAS_EXTRACT_SUBSET {
510 unsafe { cls.set_extract_subset_method(Some(t_extract_subset::<T>)) };
511 }
512}
513
514macro_rules! def_installer {
519 (
520 $(#[$meta:meta])*
521 $fn_name:ident < T: $trait:ident > {
522 $( $has:ident => $method:ident, $tramp:ident; )*
523 }
524 ) => {
525 $(#[$meta])*
526 pub unsafe fn $fn_name<T: $trait>(cls: R_altrep_class_t) {
527 $(
528 if T::$has { unsafe { cls.$method(Some($tramp::<T>)) } }
529 )*
530 }
531 };
532 (
533 $(#[$meta:meta])*
534 $fn_name:ident < T: $trait:ident > {
535 $( $has:ident => $method:ident, $tramp:ident; )*
536 }
537 always { $( $always_method:ident, $always_tramp:ident; )* }
538 ) => {
539 $(#[$meta])*
540 pub unsafe fn $fn_name<T: $trait>(cls: R_altrep_class_t) {
541 $(
542 unsafe { cls.$always_method(Some($always_tramp::<T>)) }
543 )*
544 $(
545 if T::$has { unsafe { cls.$method(Some($tramp::<T>)) } }
546 )*
547 }
548 };
549}
550
551#[doc = r" Install integer-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
pub unsafe fn install_int<T: AltInteger>(cls: R_altrep_class_t) {
if T::HAS_ELT {
unsafe { cls.set_integer_elt_method(Some(t_int_elt::<T>)) }
}
if T::HAS_GET_REGION {
unsafe {
cls.set_integer_get_region_method(Some(t_int_get_region::<T>))
}
}
if T::HAS_IS_SORTED {
unsafe {
cls.set_integer_is_sorted_method(Some(t_int_is_sorted::<T>))
}
}
if T::HAS_NO_NA {
unsafe { cls.set_integer_no_na_method(Some(t_int_no_na::<T>)) }
}
if T::HAS_SUM {
unsafe { cls.set_integer_sum_method(Some(t_int_sum::<T>)) }
}
if T::HAS_MIN {
unsafe { cls.set_integer_min_method(Some(t_int_min::<T>)) }
}
if T::HAS_MAX {
unsafe { cls.set_integer_max_method(Some(t_int_max::<T>)) }
}
}def_installer! {
552 install_int<T: AltInteger> {
556 HAS_ELT => set_integer_elt_method, t_int_elt;
557 HAS_GET_REGION => set_integer_get_region_method, t_int_get_region;
558 HAS_IS_SORTED => set_integer_is_sorted_method, t_int_is_sorted;
559 HAS_NO_NA => set_integer_no_na_method, t_int_no_na;
560 HAS_SUM => set_integer_sum_method, t_int_sum;
561 HAS_MIN => set_integer_min_method, t_int_min;
562 HAS_MAX => set_integer_max_method, t_int_max;
563 }
564}
565
566#[doc = r" Install real-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
pub unsafe fn install_real<T: AltReal>(cls: R_altrep_class_t) {
if T::HAS_ELT {
unsafe { cls.set_real_elt_method(Some(t_real_elt::<T>)) }
}
if T::HAS_GET_REGION {
unsafe {
cls.set_real_get_region_method(Some(t_real_get_region::<T>))
}
}
if T::HAS_IS_SORTED {
unsafe { cls.set_real_is_sorted_method(Some(t_real_is_sorted::<T>)) }
}
if T::HAS_NO_NA {
unsafe { cls.set_real_no_na_method(Some(t_real_no_na::<T>)) }
}
if T::HAS_SUM {
unsafe { cls.set_real_sum_method(Some(t_real_sum::<T>)) }
}
if T::HAS_MIN {
unsafe { cls.set_real_min_method(Some(t_real_min::<T>)) }
}
if T::HAS_MAX {
unsafe { cls.set_real_max_method(Some(t_real_max::<T>)) }
}
}def_installer! {
567 install_real<T: AltReal> {
571 HAS_ELT => set_real_elt_method, t_real_elt;
572 HAS_GET_REGION => set_real_get_region_method, t_real_get_region;
573 HAS_IS_SORTED => set_real_is_sorted_method, t_real_is_sorted;
574 HAS_NO_NA => set_real_no_na_method, t_real_no_na;
575 HAS_SUM => set_real_sum_method, t_real_sum;
576 HAS_MIN => set_real_min_method, t_real_min;
577 HAS_MAX => set_real_max_method, t_real_max;
578 }
579}
580
581#[doc = r" Install logical-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
pub unsafe fn install_lgl<T: AltLogical>(cls: R_altrep_class_t) {
if T::HAS_ELT {
unsafe { cls.set_logical_elt_method(Some(t_lgl_elt::<T>)) }
}
if T::HAS_GET_REGION {
unsafe {
cls.set_logical_get_region_method(Some(t_lgl_get_region::<T>))
}
}
if T::HAS_IS_SORTED {
unsafe {
cls.set_logical_is_sorted_method(Some(t_lgl_is_sorted::<T>))
}
}
if T::HAS_NO_NA {
unsafe { cls.set_logical_no_na_method(Some(t_lgl_no_na::<T>)) }
}
if T::HAS_SUM {
unsafe { cls.set_logical_sum_method(Some(t_lgl_sum::<T>)) }
}
}def_installer! {
582 install_lgl<T: AltLogical> {
586 HAS_ELT => set_logical_elt_method, t_lgl_elt;
587 HAS_GET_REGION => set_logical_get_region_method, t_lgl_get_region;
588 HAS_IS_SORTED => set_logical_is_sorted_method, t_lgl_is_sorted;
589 HAS_NO_NA => set_logical_no_na_method, t_lgl_no_na;
590 HAS_SUM => set_logical_sum_method, t_lgl_sum;
591 }
592}
593
594#[doc = r" Install raw-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
pub unsafe fn install_raw<T: AltRaw>(cls: R_altrep_class_t) {
if T::HAS_ELT { unsafe { cls.set_raw_elt_method(Some(t_raw_elt::<T>)) } }
if T::HAS_GET_REGION {
unsafe { cls.set_raw_get_region_method(Some(t_raw_get_region::<T>)) }
}
}def_installer! {
595 install_raw<T: AltRaw> {
599 HAS_ELT => set_raw_elt_method, t_raw_elt;
600 HAS_GET_REGION => set_raw_get_region_method, t_raw_get_region;
601 }
602}
603
604#[doc = r" Install complex-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
pub unsafe fn install_cplx<T: AltComplex>(cls: R_altrep_class_t) {
if T::HAS_ELT {
unsafe { cls.set_complex_elt_method(Some(t_cplx_elt::<T>)) }
}
if T::HAS_GET_REGION {
unsafe {
cls.set_complex_get_region_method(Some(t_cplx_get_region::<T>))
}
}
}def_installer! {
605 install_cplx<T: AltComplex> {
609 HAS_ELT => set_complex_elt_method, t_cplx_elt;
610 HAS_GET_REGION => set_complex_get_region_method, t_cplx_get_region;
611 }
612}
613
614#[doc = r" Install string-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
#[doc = r" Note: Elt is always installed for ALTSTRING (required)."]
pub unsafe fn install_str<T: AltString>(cls: R_altrep_class_t) {
unsafe { cls.set_string_elt_method(Some(t_str_elt::<T>)) }
if T::HAS_SET_ELT {
unsafe { cls.set_string_set_elt_method(Some(t_str_set_elt::<T>)) }
}
if T::HAS_IS_SORTED {
unsafe { cls.set_string_is_sorted_method(Some(t_str_is_sorted::<T>)) }
}
if T::HAS_NO_NA {
unsafe { cls.set_string_no_na_method(Some(t_str_no_na::<T>)) }
}
}def_installer! {
615 install_str<T: AltString> {
620 HAS_SET_ELT => set_string_set_elt_method, t_str_set_elt;
621 HAS_IS_SORTED => set_string_is_sorted_method, t_str_is_sorted;
622 HAS_NO_NA => set_string_no_na_method, t_str_no_na;
623 }
624 always { set_string_elt_method, t_str_elt; }
625}
626
627#[doc = r" Install list-specific methods."]
#[doc = r" # Safety"]
#[doc =
r" Must be called during R initialization with a valid ALTREP class handle."]
#[doc = r" Note: Elt is always installed for ALTLIST (required)."]
pub unsafe fn install_list<T: AltList>(cls: R_altrep_class_t) {
unsafe { cls.set_list_elt_method(Some(t_list_elt::<T>)) }
if T::HAS_SET_ELT {
unsafe { cls.set_list_set_elt_method(Some(t_list_set_elt::<T>)) }
}
}def_installer! {
628 install_list<T: AltList> {
633 HAS_SET_ELT => set_list_set_elt_method, t_list_set_elt;
634 }
635 always { set_list_elt_method, t_list_elt; }
636}
637