rustpython_vm/object/
payload.rs1use crate::object::{MaybeTraverse, Py, PyObjectRef, PyRef, PyResult};
2use crate::{
3 PyObject, PyRefExact,
4 builtins::{PyBaseExceptionRef, PyType, PyTypeRef},
5 types::PyTypeFlags,
6 vm::{Context, VirtualMachine},
7};
8use core::ptr::NonNull;
9
10cfg_if::cfg_if! {
11 if #[cfg(feature = "threading")] {
12 pub trait PyThreadingConstraint: Send + Sync {}
13 impl<T: Send + Sync> PyThreadingConstraint for T {}
14 } else {
15 pub trait PyThreadingConstraint {}
16 impl<T> PyThreadingConstraint for T {}
17 }
18}
19
20#[cold]
21pub(crate) fn cold_downcast_type_error(
22 vm: &VirtualMachine,
23 class: &Py<PyType>,
24 obj: &PyObject,
25) -> PyBaseExceptionRef {
26 vm.new_downcast_type_error(class, obj)
27}
28
29pub trait PyPayload: MaybeTraverse + PyThreadingConstraint + Sized + 'static {
30 const PAYLOAD_TYPE_ID: core::any::TypeId = core::any::TypeId::of::<Self>();
31
32 #[inline]
35 unsafe fn validate_downcastable_from(_obj: &PyObject) -> bool {
36 true
37 }
38
39 fn try_downcast_from(obj: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
40 if obj.downcastable::<Self>() {
41 return Ok(());
42 }
43
44 let class = Self::class(&vm.ctx);
45 Err(cold_downcast_type_error(vm, class, obj))
46 }
47
48 fn class(ctx: &Context) -> &'static Py<PyType>;
49
50 const HAS_FREELIST: bool = false;
54
55 const MAX_FREELIST: usize = 0;
57
58 #[inline]
66 unsafe fn freelist_push(_obj: *mut PyObject) -> bool {
67 false
68 }
69
70 #[inline]
79 unsafe fn freelist_pop(_payload: &Self) -> Option<NonNull<PyObject>> {
80 None
81 }
82
83 #[inline]
84 fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef
85 where
86 Self: core::fmt::Debug,
87 {
88 self.into_ref(&vm.ctx).into()
89 }
90
91 #[inline]
92 fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef<Self>
93 where
94 Self: core::fmt::Debug,
95 {
96 let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
97 Some(ctx.new_dict())
98 } else {
99 None
100 };
101 PyRef::new_ref(self, cls, dict)
102 }
103
104 #[inline]
105 fn into_exact_ref(self, ctx: &Context) -> PyRefExact<Self>
106 where
107 Self: core::fmt::Debug,
108 {
109 unsafe {
110 PyRefExact::new_unchecked(self.into_ref(ctx))
112 }
113 }
114
115 #[inline]
116 fn into_ref(self, ctx: &Context) -> PyRef<Self>
117 where
118 Self: core::fmt::Debug,
119 {
120 let cls = Self::class(ctx);
121 self._into_ref(cls.to_owned(), ctx)
122 }
123
124 #[inline]
125 fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult<PyRef<Self>>
126 where
127 Self: core::fmt::Debug,
128 {
129 let exact_class = Self::class(&vm.ctx);
130 if cls.fast_issubclass(exact_class) {
131 if exact_class.slots.basicsize != cls.slots.basicsize {
132 #[cold]
133 #[inline(never)]
134 fn _into_ref_size_error(
135 vm: &VirtualMachine,
136 cls: &Py<PyType>,
137 exact_class: &Py<PyType>,
138 ) -> PyBaseExceptionRef {
139 vm.new_type_error(format!(
140 "cannot create '{}' instance: size differs from base type '{}'",
141 cls.name(),
142 exact_class.name()
143 ))
144 }
145 return Err(_into_ref_size_error(vm, &cls, exact_class));
146 }
147 Ok(self._into_ref(cls, &vm.ctx))
148 } else {
149 #[cold]
150 #[inline(never)]
151 fn _into_ref_with_type_error(
152 vm: &VirtualMachine,
153 cls: &Py<PyType>,
154 exact_class: &Py<PyType>,
155 ) -> PyBaseExceptionRef {
156 vm.new_type_error(format!(
157 "'{}' is not a subtype of '{}'",
158 &cls.name(),
159 exact_class.name()
160 ))
161 }
162 Err(_into_ref_with_type_error(vm, &cls, exact_class))
163 }
164 }
165}
166
167pub trait PyObjectPayload:
168 PyPayload + core::any::Any + core::fmt::Debug + MaybeTraverse + PyThreadingConstraint + 'static
169{
170}
171
172impl<T: PyPayload + core::fmt::Debug + 'static> PyObjectPayload for T {}
173
174pub trait SlotOffset {
175 fn offset() -> usize;
176}