forked from Rust-related/RustPython
Make PyObject.typ : Rc<PyObject<PyClass>>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use super::objbyteinner::try_as_byte;
|
||||
use super::objtype::{issubclass, PyClassRef};
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::pyobject::{
|
||||
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::stdlib::array::PyArray;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
@@ -26,12 +26,12 @@ impl PyMemoryView {
|
||||
bytes_object: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyMemoryViewRef> {
|
||||
let object_type = bytes_object.typ.borrow();
|
||||
let object_type = bytes_object.class();
|
||||
|
||||
if issubclass(object_type, &vm.ctx.types.memoryview_type)
|
||||
|| issubclass(object_type, &vm.ctx.types.bytes_type)
|
||||
|| issubclass(object_type, &vm.ctx.types.bytearray_type)
|
||||
|| issubclass(object_type, &PyArray::class(vm))
|
||||
if issubclass(&object_type, &vm.ctx.types.memoryview_type)
|
||||
|| issubclass(&object_type, &vm.ctx.types.bytes_type)
|
||||
|| issubclass(&object_type, &vm.ctx.types.bytearray_type)
|
||||
|| issubclass(&object_type, &PyArray::class(vm))
|
||||
{
|
||||
PyMemoryView {
|
||||
obj_ref: bytes_object.clone(),
|
||||
|
||||
@@ -526,7 +526,7 @@ pub fn new(
|
||||
slots: RefCell::default(),
|
||||
},
|
||||
dict: None,
|
||||
typ,
|
||||
typ: typ.into_generic_pyobj(),
|
||||
}
|
||||
.into_ref();
|
||||
|
||||
|
||||
@@ -571,7 +571,7 @@ impl PyContext {
|
||||
|
||||
pub fn new_base_object(&self, class: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
|
||||
PyObject {
|
||||
typ: class,
|
||||
typ: class.into_generic_pyobj(),
|
||||
dict: dict.map(RefCell::new),
|
||||
payload: objobject::PyBaseObject,
|
||||
}
|
||||
@@ -628,7 +628,7 @@ pub struct PyObject<T>
|
||||
where
|
||||
T: ?Sized + PyObjectPayload,
|
||||
{
|
||||
pub typ: PyClassRef,
|
||||
pub typ: Rc<PyObject<PyClass>>,
|
||||
pub dict: Option<RefCell<PyDictRef>>, // __dict__ member
|
||||
pub payload: T,
|
||||
}
|
||||
@@ -648,6 +648,21 @@ impl PyObject<dyn PyObjectPayload> {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Dowcast this PyObjectRef to an `Rc<PyObject<T>>`. The [`downcast`](#method.downcast) method
|
||||
/// is generally preferred, as the `PyRef<T>` it returns implements `Deref<Target=T>`, and
|
||||
/// therefore can be used similarly to an `&T`.
|
||||
pub fn downcast_generic<T: PyObjectPayload>(
|
||||
self: Rc<Self>,
|
||||
) -> Result<Rc<PyObject<T>>, PyObjectRef> {
|
||||
if self.payload_is::<T>() {
|
||||
let ptr = Rc::into_raw(self) as *const PyObject<T>;
|
||||
let ret = unsafe { Rc::from_raw(ptr) };
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a Python object.
|
||||
@@ -660,6 +675,7 @@ impl PyObject<dyn PyObjectPayload> {
|
||||
/// situations (such as when implementing in-place methods such as `__iadd__`)
|
||||
/// where a reference to the same object must be returned.
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyRef<T> {
|
||||
// invariant: this obj must always have payload of type T
|
||||
obj: PyObjectRef,
|
||||
@@ -705,6 +721,10 @@ impl<T: PyValue> PyRef<T> {
|
||||
pub fn typ(&self) -> PyClassRef {
|
||||
self.obj.class()
|
||||
}
|
||||
|
||||
pub fn into_generic_pyobj(self) -> Rc<PyObject<T>> {
|
||||
self.into_object().downcast_generic().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for PyRef<T>
|
||||
@@ -838,13 +858,13 @@ where
|
||||
T: ?Sized + PyObjectPayload,
|
||||
{
|
||||
fn class(&self) -> PyClassRef {
|
||||
self.typ.clone()
|
||||
self.typ.clone().into_pyref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TypeProtocol for PyRef<T> {
|
||||
fn class(&self) -> PyClassRef {
|
||||
self.obj.typ.clone()
|
||||
self.obj.class()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,7 +1123,7 @@ where
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new(payload: T, typ: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
|
||||
PyObject {
|
||||
typ,
|
||||
typ: typ.into_generic_pyobj(),
|
||||
dict: dict.map(RefCell::new),
|
||||
payload,
|
||||
}
|
||||
@@ -1114,6 +1134,13 @@ where
|
||||
pub fn into_ref(self) -> PyObjectRef {
|
||||
Rc::new(self)
|
||||
}
|
||||
|
||||
pub fn into_pyref(self: Rc<Self>) -> PyRef<T>
|
||||
where
|
||||
T: PyValue,
|
||||
{
|
||||
PyRef::new_ref_unchecked(self as PyObjectRef)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyObject<dyn PyObjectPayload> {
|
||||
|
||||
@@ -38,9 +38,9 @@ use crate::obj::objtype::{self, PyClass, PyClassRef};
|
||||
use crate::obj::objweakproxy;
|
||||
use crate::obj::objweakref;
|
||||
use crate::obj::objzip;
|
||||
use crate::pyobject::{PyAttributes, PyContext, PyObject, PyObjectPayload};
|
||||
use crate::pyobject::{PyAttributes, PyContext, PyObject};
|
||||
use std::cell::RefCell;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -312,41 +312,14 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
|
||||
let type_type_ptr =
|
||||
Rc::into_raw(type_type.clone()) as *mut MaybeUninit<PyClassObj> as *mut PyClassObj;
|
||||
|
||||
// same as std::raw::TraitObject (which is unstable, but accurate)
|
||||
#[repr(C)]
|
||||
struct TraitObject {
|
||||
data: *mut (),
|
||||
vtable: *mut (),
|
||||
}
|
||||
|
||||
let pyclass_vptr = {
|
||||
// dummy PyClass
|
||||
let cls = PyClass {
|
||||
name: Default::default(),
|
||||
bases: Default::default(),
|
||||
mro: Default::default(),
|
||||
subclasses: Default::default(),
|
||||
attributes: Default::default(),
|
||||
slots: Default::default(),
|
||||
};
|
||||
// so that we can get the vtable ptr of PyClass for PyObjectPayload
|
||||
mem::transmute::<_, TraitObject>(&cls as &dyn PyObjectPayload).vtable
|
||||
};
|
||||
|
||||
let write_typ_ptr = |ptr: *mut PyClassObj, type_type: UninitRef<PyClassObj>| {
|
||||
// turn type_type into a trait object, using the vtable for PyClass we got earlier
|
||||
let type_type = mem::transmute(TraitObject {
|
||||
data: mem::transmute(type_type),
|
||||
vtable: pyclass_vptr,
|
||||
});
|
||||
ptr::write(
|
||||
&mut (*ptr).typ as *mut PyClassRef as *mut MaybeUninit<PyClassRef>,
|
||||
type_type,
|
||||
);
|
||||
};
|
||||
|
||||
write_typ_ptr(object_type_ptr, type_type.clone());
|
||||
write_typ_ptr(type_type_ptr, type_type);
|
||||
ptr::write(
|
||||
&mut (*object_type_ptr).typ as *mut Rc<PyClassObj> as *mut UninitRef<PyClassObj>,
|
||||
type_type.clone(),
|
||||
);
|
||||
ptr::write(
|
||||
&mut (*type_type_ptr).typ as *mut Rc<PyClassObj> as *mut UninitRef<PyClassObj>,
|
||||
type_type,
|
||||
);
|
||||
|
||||
let type_type = PyClassRef::new_ref_unchecked(Rc::from_raw(type_type_ptr));
|
||||
let object_type = PyClassRef::new_ref_unchecked(Rc::from_raw(object_type_ptr));
|
||||
|
||||
Reference in New Issue
Block a user