rustpython_vm/object/
payload.rs

1use crate::object::{MaybeTraverse, Py, PyObjectRef, PyRef, PyResult};
2use crate::{
3    builtins::{PyBaseExceptionRef, PyType, PyTypeRef},
4    types::PyTypeFlags,
5    vm::{Context, VirtualMachine},
6    PyRefExact,
7};
8
9cfg_if::cfg_if! {
10    if #[cfg(feature = "threading")] {
11        pub trait PyThreadingConstraint: Send + Sync {}
12        impl<T: Send + Sync> PyThreadingConstraint for T {}
13    } else {
14        pub trait PyThreadingConstraint {}
15        impl<T> PyThreadingConstraint for T {}
16    }
17}
18
19pub trait PyPayload:
20    std::fmt::Debug + MaybeTraverse + PyThreadingConstraint + Sized + 'static
21{
22    fn class(ctx: &Context) -> &'static Py<PyType>;
23
24    #[inline]
25    fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
26        self.into_ref(&vm.ctx).into()
27    }
28
29    #[inline]
30    fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef<Self> {
31        let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
32            Some(ctx.new_dict())
33        } else {
34            None
35        };
36        PyRef::new_ref(self, cls, dict)
37    }
38
39    #[inline]
40    fn into_exact_ref(self, ctx: &Context) -> PyRefExact<Self> {
41        unsafe {
42            // Self::into_ref() always returns exact typed PyRef
43            PyRefExact::new_unchecked(self.into_ref(ctx))
44        }
45    }
46
47    #[inline]
48    fn into_ref(self, ctx: &Context) -> PyRef<Self> {
49        let cls = Self::class(ctx);
50        self._into_ref(cls.to_owned(), ctx)
51    }
52
53    #[inline]
54    fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult<PyRef<Self>> {
55        let exact_class = Self::class(&vm.ctx);
56        if cls.fast_issubclass(exact_class) {
57            Ok(self._into_ref(cls, &vm.ctx))
58        } else {
59            #[cold]
60            #[inline(never)]
61            fn _into_ref_with_type_error(
62                vm: &VirtualMachine,
63                cls: &PyTypeRef,
64                exact_class: &Py<PyType>,
65            ) -> PyBaseExceptionRef {
66                vm.new_type_error(format!(
67                    "'{}' is not a subtype of '{}'",
68                    &cls.name(),
69                    exact_class.name()
70                ))
71            }
72            Err(_into_ref_with_type_error(vm, &cls, exact_class))
73        }
74    }
75}
76
77pub trait PyObjectPayload:
78    std::any::Any + std::fmt::Debug + MaybeTraverse + PyThreadingConstraint + 'static
79{
80}
81
82impl<T: PyPayload + 'static> PyObjectPayload for T {}
83
84pub trait SlotOffset {
85    fn offset() -> usize;
86}