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_select! {
11 feature = "threading" => {
12 pub trait PyThreadingConstraint: Send + Sync {}
13 impl<T: Send + Sync> PyThreadingConstraint for T {}
14 }
15 _ => {
16 pub trait PyThreadingConstraint {}
17 impl<T> PyThreadingConstraint for T {}
18 }
19}
20
21#[cold]
22pub(crate) fn cold_downcast_type_error(
23 vm: &VirtualMachine,
24 class: &Py<PyType>,
25 obj: &PyObject,
26) -> PyBaseExceptionRef {
27 vm.new_downcast_type_error(class, obj)
28}
29
30pub trait PyPayload: MaybeTraverse + PyThreadingConstraint + Sized + 'static {
67 const PAYLOAD_TYPE_ID: core::any::TypeId = core::any::TypeId::of::<Self>();
68
69 #[inline]
72 unsafe fn validate_downcastable_from(_obj: &PyObject) -> bool {
73 true
74 }
75
76 fn try_downcast_from(obj: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
77 if obj.downcastable::<Self>() {
78 return Ok(());
79 }
80
81 let class = Self::class(&vm.ctx);
82 Err(cold_downcast_type_error(vm, class, obj))
83 }
84
85 fn class(ctx: &Context) -> &'static Py<PyType>;
86
87 const NEW_REF_UNTRACKED: bool = false;
93
94 const HAS_FREELIST: bool = false;
98
99 const MAX_FREELIST: usize = 0;
101
102 #[inline]
112 unsafe fn freelist_push(_obj: *mut PyObject) -> bool {
113 false
114 }
115
116 #[inline]
125 unsafe fn freelist_pop(_payload: &Self) -> Option<NonNull<PyObject>> {
126 None
127 }
128
129 #[inline]
130 fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef
131 where
132 Self: core::fmt::Debug,
133 {
134 self.into_ref(&vm.ctx).into()
135 }
136
137 #[inline]
138 fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef<Self>
139 where
140 Self: core::fmt::Debug,
141 {
142 let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
143 Some(ctx.new_dict())
144 } else {
145 None
146 };
147 PyRef::new_ref(self, cls, dict)
148 }
149
150 #[inline]
151 fn into_exact_ref(self, ctx: &Context) -> PyRefExact<Self>
152 where
153 Self: core::fmt::Debug,
154 {
155 unsafe {
156 PyRefExact::new_unchecked(self.into_ref(ctx))
158 }
159 }
160
161 #[inline]
162 fn into_ref(self, ctx: &Context) -> PyRef<Self>
163 where
164 Self: core::fmt::Debug,
165 {
166 let cls = Self::class(ctx);
167 self._into_ref(cls.to_owned(), ctx)
168 }
169
170 #[inline]
171 fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult<PyRef<Self>>
172 where
173 Self: core::fmt::Debug,
174 {
175 self.into_ref_with_type_and_dict(vm, cls, true)
176 }
177
178 #[inline]
182 fn into_ref_with_type_lazy_dict(
183 self,
184 vm: &VirtualMachine,
185 cls: PyTypeRef,
186 ) -> PyResult<PyRef<Self>>
187 where
188 Self: core::fmt::Debug,
189 {
190 self.into_ref_with_type_and_dict(vm, cls, false)
191 }
192
193 #[inline]
194 fn into_ref_with_type_and_dict(
195 self,
196 vm: &VirtualMachine,
197 cls: PyTypeRef,
198 eager_dict: bool,
199 ) -> PyResult<PyRef<Self>>
200 where
201 Self: core::fmt::Debug,
202 {
203 let exact_class = Self::class(&vm.ctx);
204 if cls.fast_issubclass(exact_class) {
205 if exact_class.slots.basicsize != cls.slots.basicsize {
206 #[cold]
207 #[inline(never)]
208 fn _into_ref_size_error(
209 vm: &VirtualMachine,
210 cls: &Py<PyType>,
211 exact_class: &Py<PyType>,
212 ) -> PyBaseExceptionRef {
213 vm.new_type_error(format!(
214 "cannot create '{}' instance: size differs from base type '{}'",
215 cls.name(),
216 exact_class.name()
217 ))
218 }
219 return Err(_into_ref_size_error(vm, &cls, exact_class));
220 }
221 let dict = if eager_dict && cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
222 Some(vm.ctx.new_dict())
223 } else {
224 None
225 };
226 Ok(PyRef::new_ref(self, cls, dict))
227 } else {
228 #[cold]
229 #[inline(never)]
230 fn _into_ref_with_type_error(
231 vm: &VirtualMachine,
232 cls: &Py<PyType>,
233 exact_class: &Py<PyType>,
234 ) -> PyBaseExceptionRef {
235 vm.new_type_error(format!(
236 "'{}' is not a subtype of '{}'",
237 cls.name(),
238 exact_class.name()
239 ))
240 }
241 Err(_into_ref_with_type_error(vm, &cls, exact_class))
242 }
243 }
244}
245
246pub trait PyObjectPayload:
247 PyPayload + core::any::Any + core::fmt::Debug + MaybeTraverse + PyThreadingConstraint + 'static
248{
249}
250
251impl<T: PyPayload + core::fmt::Debug + 'static> PyObjectPayload for T {}
252
253pub trait SlotOffset {
254 fn offset() -> usize;
255}