diff --git a/crates/vm/src/builtins/dict.rs b/crates/vm/src/builtins/dict.rs index f9911ce033b..77126d4ee62 100644 --- a/crates/vm/src/builtins/dict.rs +++ b/crates/vm/src/builtins/dict.rs @@ -751,7 +751,7 @@ impl ExactSizeIterator for DictIter<'_> { #[pyclass] trait DictView: PyPayload + PyClassDef + Iterable + Representable { - type ReverseIter: PyPayload; + type ReverseIter: PyPayload + std::fmt::Debug; fn dict(&self) -> &PyDictRef; fn item(vm: &VirtualMachine, key: PyObjectRef, value: PyObjectRef) -> PyObjectRef; diff --git a/crates/vm/src/object/core.rs b/crates/vm/src/object/core.rs index fb2c5b6303e..6530abdbaba 100644 --- a/crates/vm/src/object/core.rs +++ b/crates/vm/src/object/core.rs @@ -13,7 +13,7 @@ use super::{ PyAtomicRef, ext::{AsObject, PyRefExact, PyResult}, - payload::PyObjectPayload, + payload::PyPayload, }; use crate::object::traverse::{MaybeTraverse, Traverse, TraverseFn}; use crate::object::traverse_object::PyObjVTable; @@ -76,10 +76,10 @@ use std::{ #[derive(Debug)] pub(super) struct Erased; -pub(super) unsafe fn drop_dealloc_obj(x: *mut PyObject) { +pub(super) unsafe fn drop_dealloc_obj(x: *mut PyObject) { drop(unsafe { Box::from_raw(x as *mut PyInner) }); } -pub(super) unsafe fn debug_obj( +pub(super) unsafe fn debug_obj( x: &PyObject, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { @@ -88,10 +88,7 @@ pub(super) unsafe fn debug_obj( } /// Call `try_trace` on payload -pub(super) unsafe fn try_trace_obj( - x: &PyObject, - tracer_fn: &mut TraverseFn<'_>, -) { +pub(super) unsafe fn try_trace_obj(x: &PyObject, tracer_fn: &mut TraverseFn<'_>) { let x = unsafe { &*(x as *const PyObject as *const PyInner) }; let payload = &x.payload; payload.try_traverse(tracer_fn) @@ -441,7 +438,7 @@ impl InstanceDict { } } -impl PyInner { +impl PyInner { fn new(payload: T, typ: PyTypeRef, dict: Option) -> Box { let member_count = typ.slots.member_count; Box::new(Self { @@ -531,7 +528,7 @@ impl PyObjectRef { /// If the downcast fails, the original ref is returned in as `Err` so /// another downcast can be attempted without unnecessary cloning. #[inline(always)] - pub fn downcast(self) -> Result, Self> { + pub fn downcast(self) -> Result, Self> { if self.downcastable::() { Ok(unsafe { self.downcast_unchecked() }) } else { @@ -539,7 +536,7 @@ impl PyObjectRef { } } - pub fn try_downcast(self, vm: &VirtualMachine) -> PyResult> { + pub fn try_downcast(self, vm: &VirtualMachine) -> PyResult> { T::try_downcast_from(&self, vm)?; Ok(unsafe { self.downcast_unchecked() }) } @@ -565,10 +562,7 @@ impl PyObjectRef { /// If the downcast fails, the original ref is returned in as `Err` so /// another downcast can be attempted without unnecessary cloning. #[inline] - pub fn downcast_exact( - self, - vm: &VirtualMachine, - ) -> Result, Self> { + pub fn downcast_exact(self, vm: &VirtualMachine) -> Result, Self> { if self.class().is(T::class(&vm.ctx)) { // TODO: is this always true? assert!( @@ -638,7 +632,7 @@ impl PyObject { #[deprecated(note = "use downcastable instead")] #[inline(always)] - pub fn payload_is(&self) -> bool { + pub fn payload_is(&self) -> bool { self.0.typeid == T::payload_type_id() } @@ -648,7 +642,7 @@ impl PyObject { /// The actual payload type must be T. #[deprecated(note = "use downcast_unchecked_ref instead")] #[inline(always)] - pub const unsafe fn payload_unchecked(&self) -> &T { + pub const unsafe fn payload_unchecked(&self) -> &T { // we cast to a PyInner first because we don't know T's exact offset because of // varying alignment, but once we get a PyInner the compiler can get it for us let inner = unsafe { &*(&self.0 as *const PyInner as *const PyInner) }; @@ -657,7 +651,7 @@ impl PyObject { #[deprecated(note = "use downcast_ref instead")] #[inline(always)] - pub fn payload(&self) -> Option<&T> { + pub fn payload(&self) -> Option<&T> { #[allow(deprecated)] if self.payload_is::() { #[allow(deprecated)] @@ -678,10 +672,7 @@ impl PyObject { #[deprecated(note = "use downcast_ref_if_exact instead")] #[inline(always)] - pub fn payload_if_exact( - &self, - vm: &VirtualMachine, - ) -> Option<&T> { + pub fn payload_if_exact(&self, vm: &VirtualMachine) -> Option<&T> { if self.class().is(T::class(&vm.ctx)) { #[allow(deprecated)] self.payload() @@ -730,12 +721,12 @@ impl PyObject { /// Check if this object can be downcast to T. #[inline(always)] - pub fn downcastable(&self) -> bool { + pub fn downcastable(&self) -> bool { T::downcastable_from(self) } /// Attempt to downcast this reference to a subclass. - pub fn try_downcast_ref<'a, T: PyObjectPayload>( + pub fn try_downcast_ref<'a, T: PyPayload>( &'a self, vm: &VirtualMachine, ) -> PyResult<&'a Py> { @@ -745,7 +736,7 @@ impl PyObject { /// Attempt to downcast this reference to a subclass. #[inline(always)] - pub fn downcast_ref(&self) -> Option<&Py> { + pub fn downcast_ref(&self) -> Option<&Py> { if self.downcastable::() { // SAFETY: just checked that the payload is T, and PyRef is repr(transparent) over // PyObjectRef @@ -756,10 +747,7 @@ impl PyObject { } #[inline(always)] - pub fn downcast_ref_if_exact( - &self, - vm: &VirtualMachine, - ) -> Option<&Py> { + pub fn downcast_ref_if_exact(&self, vm: &VirtualMachine) -> Option<&Py> { self.class() .is(T::class(&vm.ctx)) .then(|| unsafe { self.downcast_unchecked_ref::() }) @@ -768,7 +756,7 @@ impl PyObject { /// # Safety /// T must be the exact payload type #[inline(always)] - pub unsafe fn downcast_unchecked_ref(&self) -> &Py { + pub unsafe fn downcast_unchecked_ref(&self) -> &Py { debug_assert!(self.downcastable::()); // SAFETY: requirements forwarded from caller unsafe { &*(self as *const Self as *const Py) } @@ -875,7 +863,7 @@ impl AsRef for PyObjectRef { } } -impl<'a, T: PyObjectPayload> From<&'a Py> for &'a PyObject { +impl<'a, T: PyPayload> From<&'a Py> for &'a PyObject { #[inline(always)] fn from(py_ref: &'a Py) -> Self { py_ref.as_object() @@ -908,7 +896,7 @@ impl fmt::Debug for PyObjectRef { #[repr(transparent)] pub struct Py(PyInner); -impl Py { +impl Py { pub fn downgrade( &self, callback: Option, @@ -947,7 +935,7 @@ impl Deref for Py { } } -impl Borrow for Py { +impl Borrow for Py { #[inline(always)] fn borrow(&self) -> &PyObject { unsafe { &*(&self.0 as *const PyInner as *const PyObject) } @@ -956,7 +944,7 @@ impl Borrow for Py { impl std::hash::Hash for Py where - T: std::hash::Hash + PyObjectPayload, + T: std::hash::Hash + PyPayload, { #[inline] fn hash(&self, state: &mut H) { @@ -966,7 +954,7 @@ where impl PartialEq for Py where - T: PartialEq + PyObjectPayload, + T: PartialEq + PyPayload, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -974,11 +962,11 @@ where } } -impl Eq for Py where T: Eq + PyObjectPayload {} +impl Eq for Py where T: Eq + PyPayload {} impl AsRef for Py where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn as_ref(&self) -> &PyObject { @@ -986,7 +974,7 @@ where } } -impl fmt::Debug for Py { +impl fmt::Debug for Py { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } @@ -1035,7 +1023,7 @@ impl Clone for PyRef { } } -impl PyRef { +impl PyRef { // #[inline(always)] // pub(crate) const fn into_non_null(self) -> NonNull> { // let ptr = self.ptr; @@ -1065,6 +1053,14 @@ impl PyRef { } } + pub const fn leak(pyref: Self) -> &'static Py { + let ptr = pyref.ptr; + std::mem::forget(pyref); + unsafe { ptr.as_ref() } + } +} + +impl PyRef { #[inline(always)] pub fn new_ref(payload: T, typ: crate::builtins::PyTypeRef, dict: Option) -> Self { let inner = Box::into_raw(PyInner::new(payload, typ, dict)); @@ -1072,17 +1068,11 @@ impl PyRef { ptr: unsafe { NonNull::new_unchecked(inner.cast::>()) }, } } - - pub const fn leak(pyref: Self) -> &'static Py { - let ptr = pyref.ptr; - std::mem::forget(pyref); - unsafe { ptr.as_ref() } - } } impl Borrow for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn borrow(&self) -> &PyObject { @@ -1092,7 +1082,7 @@ where impl AsRef for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn as_ref(&self) -> &PyObject { @@ -1133,7 +1123,7 @@ impl Deref for PyRef { impl std::hash::Hash for PyRef where - T: std::hash::Hash + PyObjectPayload, + T: std::hash::Hash + PyPayload, { #[inline] fn hash(&self, state: &mut H) { @@ -1143,7 +1133,7 @@ where impl PartialEq for PyRef where - T: PartialEq + PyObjectPayload, + T: PartialEq + PyPayload, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -1151,15 +1141,15 @@ where } } -impl Eq for PyRef where T: Eq + PyObjectPayload {} +impl Eq for PyRef where T: Eq + PyPayload {} #[repr(transparent)] -pub struct PyWeakRef { +pub struct PyWeakRef { weak: PyRef, _marker: PhantomData, } -impl PyWeakRef { +impl PyWeakRef { pub fn upgrade(&self) -> Option> { self.weak .upgrade() diff --git a/crates/vm/src/object/ext.rs b/crates/vm/src/object/ext.rs index 1e2b78d9a9e..88f5fdc66d7 100644 --- a/crates/vm/src/object/ext.rs +++ b/crates/vm/src/object/ext.rs @@ -1,6 +1,6 @@ use super::{ core::{Py, PyObject, PyObjectRef, PyRef}, - payload::{PyObjectPayload, PyPayload}, + payload::PyPayload, }; use crate::common::{ atomic::{Ordering, PyAtomic, Radium}, @@ -41,7 +41,7 @@ pub type PyResult = Result; // A valid v impl fmt::Display for PyRef where - T: PyObjectPayload + fmt::Display, + T: PyPayload + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) @@ -50,7 +50,7 @@ where impl fmt::Display for Py where - T: PyObjectPayload + fmt::Display, + T: PyPayload + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) @@ -58,7 +58,7 @@ where } #[repr(transparent)] -pub struct PyExact { +pub struct PyExact { inner: Py, } @@ -80,28 +80,28 @@ impl Deref for PyExact { } } -impl Borrow for PyExact { +impl Borrow for PyExact { #[inline(always)] fn borrow(&self) -> &PyObject { self.inner.borrow() } } -impl AsRef for PyExact { +impl AsRef for PyExact { #[inline(always)] fn as_ref(&self) -> &PyObject { self.inner.as_ref() } } -impl Borrow> for PyExact { +impl Borrow> for PyExact { #[inline(always)] fn borrow(&self) -> &Py { &self.inner } } -impl AsRef> for PyExact { +impl AsRef> for PyExact { #[inline(always)] fn as_ref(&self) -> &Py { &self.inner @@ -134,11 +134,11 @@ impl PyRef { /// PyRef but guaranteed not to be a subtype instance #[derive(Debug)] #[repr(transparent)] -pub struct PyRefExact { +pub struct PyRefExact { inner: PyRef, } -impl PyRefExact { +impl PyRefExact { /// # Safety /// obj must have exact type for the payload pub const unsafe fn new_unchecked(obj: PyRef) -> Self { @@ -150,7 +150,7 @@ impl PyRefExact { } } -impl Clone for PyRefExact { +impl Clone for PyRefExact { fn clone(&self) -> Self { let inner = self.inner.clone(); Self { inner } @@ -191,28 +191,28 @@ impl Deref for PyRefExact { } } -impl Borrow for PyRefExact { +impl Borrow for PyRefExact { #[inline(always)] fn borrow(&self) -> &PyObject { self.inner.borrow() } } -impl AsRef for PyRefExact { +impl AsRef for PyRefExact { #[inline(always)] fn as_ref(&self) -> &PyObject { self.inner.as_ref() } } -impl Borrow> for PyRefExact { +impl Borrow> for PyRefExact { #[inline(always)] fn borrow(&self) -> &Py { self.inner.borrow() } } -impl AsRef> for PyRefExact { +impl AsRef> for PyRefExact { #[inline(always)] fn as_ref(&self) -> &Py { self.inner.as_ref() @@ -260,10 +260,10 @@ impl Drop for PyAtomicRef { cfg_if::cfg_if! { if #[cfg(feature = "threading")] { - unsafe impl Send for PyAtomicRef {} - unsafe impl Sync for PyAtomicRef {} - unsafe impl Send for PyAtomicRef> {} - unsafe impl Sync for PyAtomicRef> {} + unsafe impl Send for PyAtomicRef {} + unsafe impl Sync for PyAtomicRef {} + unsafe impl Send for PyAtomicRef> {} + unsafe impl Sync for PyAtomicRef> {} unsafe impl Send for PyAtomicRef {} unsafe impl Sync for PyAtomicRef {} unsafe impl Send for PyAtomicRef> {} @@ -285,7 +285,7 @@ impl fmt::Debug for PyAtomicRef { } } -impl From> for PyAtomicRef { +impl From> for PyAtomicRef { fn from(pyref: PyRef) -> Self { let py = PyRef::leak(pyref); Self { @@ -295,7 +295,7 @@ impl From> for PyAtomicRef { } } -impl Deref for PyAtomicRef { +impl Deref for PyAtomicRef { type Target = Py; fn deref(&self) -> &Self::Target { @@ -309,7 +309,7 @@ impl Deref for PyAtomicRef { } } -impl PyAtomicRef { +impl PyAtomicRef { /// # Safety /// The caller is responsible to keep the returned PyRef alive /// until no more reference can be used via PyAtomicRef::deref() @@ -328,7 +328,7 @@ impl PyAtomicRef { } } -impl From>> for PyAtomicRef> { +impl From>> for PyAtomicRef> { fn from(opt_ref: Option>) -> Self { let val = opt_ref .map(|x| PyRef::leak(x) as *const Py as *mut _) @@ -340,7 +340,7 @@ impl From>> for PyAtomicRef> { } } -impl PyAtomicRef> { +impl PyAtomicRef> { pub fn deref(&self) -> Option<&Py> { unsafe { self.inner.load(Ordering::Relaxed).cast::>().as_ref() } } @@ -521,25 +521,25 @@ impl PyObject { /// `PyObjectRef`, which isn't that cheap as that increments the atomic reference counter. // TODO: check if we still need this #[allow(dead_code)] -pub struct PyLease<'a, T: PyObjectPayload> { +pub struct PyLease<'a, T: PyPayload> { inner: PyRwLockReadGuard<'a, PyRef>, } -impl PyLease<'_, T> { +impl PyLease<'_, T> { #[inline(always)] pub fn into_owned(self) -> PyRef { self.inner.clone() } } -impl Borrow for PyLease<'_, T> { +impl Borrow for PyLease<'_, T> { #[inline(always)] fn borrow(&self) -> &PyObject { self.inner.as_ref() } } -impl Deref for PyLease<'_, T> { +impl Deref for PyLease<'_, T> { type Target = PyRef; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -556,7 +556,7 @@ where } } -impl ToPyObject for PyRef { +impl ToPyObject for PyRef { #[inline(always)] fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef { self.into() @@ -581,7 +581,7 @@ impl ToPyObject for &PyObject { // explicitly implementing `ToPyObject`. impl ToPyObject for T where - T: PyPayload + Sized, + T: PyPayload + std::fmt::Debug + Sized, { #[inline(always)] fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { diff --git a/crates/vm/src/object/payload.rs b/crates/vm/src/object/payload.rs index 0b7bfe0dc1a..7fc40ddba90 100644 --- a/crates/vm/src/object/payload.rs +++ b/crates/vm/src/object/payload.rs @@ -16,9 +16,7 @@ cfg_if::cfg_if! { } } -pub trait PyPayload: - std::fmt::Debug + MaybeTraverse + PyThreadingConstraint + Sized + 'static -{ +pub trait PyPayload: MaybeTraverse + PyThreadingConstraint + Sized + 'static { #[inline] fn payload_type_id() -> std::any::TypeId { std::any::TypeId::of::() @@ -51,12 +49,18 @@ pub trait PyPayload: fn class(ctx: &Context) -> &'static Py; #[inline] - fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { + fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef + where + Self: std::fmt::Debug, + { self.into_ref(&vm.ctx).into() } #[inline] - fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef { + fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef + where + Self: std::fmt::Debug, + { let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) { Some(ctx.new_dict()) } else { @@ -66,7 +70,10 @@ pub trait PyPayload: } #[inline] - fn into_exact_ref(self, ctx: &Context) -> PyRefExact { + fn into_exact_ref(self, ctx: &Context) -> PyRefExact + where + Self: std::fmt::Debug, + { unsafe { // Self::into_ref() always returns exact typed PyRef PyRefExact::new_unchecked(self.into_ref(ctx)) @@ -74,13 +81,19 @@ pub trait PyPayload: } #[inline] - fn into_ref(self, ctx: &Context) -> PyRef { + fn into_ref(self, ctx: &Context) -> PyRef + where + Self: std::fmt::Debug, + { let cls = Self::class(ctx); self._into_ref(cls.to_owned(), ctx) } #[inline] - fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> { + fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> + where + Self: std::fmt::Debug, + { let exact_class = Self::class(&vm.ctx); if cls.fast_issubclass(exact_class) { Ok(self._into_ref(cls, &vm.ctx)) @@ -108,7 +121,7 @@ pub trait PyObjectPayload: { } -impl PyObjectPayload for T {} +impl PyObjectPayload for T {} pub trait SlotOffset { fn offset() -> usize; diff --git a/crates/vm/src/types/slot.rs b/crates/vm/src/types/slot.rs index 0cdb3c7189b..834b3b5cb45 100644 --- a/crates/vm/src/types/slot.rs +++ b/crates/vm/src/types/slot.rs @@ -793,7 +793,7 @@ pub trait Constructor: PyPayload { fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult; } -pub trait DefaultConstructor: PyPayload + Default { +pub trait DefaultConstructor: PyPayload + Default + std::fmt::Debug { fn construct_and_init(args: Self::Args, vm: &VirtualMachine) -> PyResult> where Self: Initializer, diff --git a/crates/vm/src/vm/context.rs b/crates/vm/src/vm/context.rs index 3fc25f3b992..c75bfe18558 100644 --- a/crates/vm/src/vm/context.rs +++ b/crates/vm/src/vm/context.rs @@ -380,7 +380,7 @@ impl Context { pub fn new_pyref(&self, value: T) -> PyRef

where T: Into

, - P: PyPayload, + P: PyPayload + std::fmt::Debug, { value.into().into_ref(self) }