diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 9dbbb913b..1117a4df9 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -35,12 +35,6 @@ impl PyValue for PyClass { } } -impl IdProtocol for PyClassRef { - fn get_id(&self) -> usize { - self.as_object().get_id() - } -} - impl TypeProtocol for PyClassRef { fn type_ref(&self) -> &PyObjectRef { &self.as_object().type_ref() @@ -335,10 +329,7 @@ fn take_next_base(mut bases: Vec>) -> Option<(PyClassRef, Vec>) -> Option<(PyClassRef, Vec, + referent: Weak>, } impl PyWeak { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index a1b3078cc..59d185a48 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -72,7 +72,7 @@ Basically reference counting, but then done by rust. /// this reference counting is accounted for by this type. Use the `.clone()` /// method to create a new reference and increment the amount of references /// to the python object by 1. -pub type PyObjectRef = Rc; +pub type PyObjectRef = Rc>; /// Use this type for function which return a python object or and exception. /// Both the python object and the python exception are `PyObjectRef` types @@ -83,7 +83,7 @@ pub type PyResult = Result; // A valid value, o /// faster, unordered, and only supports strings as keys. pub type PyAttributes = HashMap; -impl fmt::Display for PyObject { +impl fmt::Display for PyObject { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::TypeProtocol; if let Some(PyClass { ref name, .. }) = self.payload::() { @@ -193,25 +193,25 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { let object_type = PyObject { typ: mem::uninitialized(), // ! dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(PyClass { + payload: PyClass { name: String::from("object"), mro: vec![], - }), + }, } .into_ref(); let type_type = PyObject { typ: mem::uninitialized(), // ! dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(PyClass { + payload: PyClass { name: String::from("type"), mro: vec![FromPyObjectRef::from_pyobj(&object_type)], - }), + }, } .into_ref(); - let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; - let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; + let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; + let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); @@ -639,7 +639,7 @@ impl PyContext { PyObject { typ: class.into_object(), dict: Some(RefCell::new(dict)), - payload: Box::new(objobject::PyInstance), + payload: objobject::PyInstance, } .into_ref() } @@ -708,10 +708,13 @@ impl Default for PyContext { /// This is an actual python object. It consists of a `typ` which is the /// python class, and carries some rust payload optionally. This rust /// payload can be a rust float or rust int in case of float and int objects. -pub struct PyObject { +pub struct PyObject +where + T: ?Sized + PyObjectPayload, +{ pub typ: PyObjectRef, pub dict: Option>, // __dict__ member - pub payload: Box, + pub payload: T, } /// A reference to a Python object. @@ -820,9 +823,30 @@ pub trait IdProtocol { } } -impl IdProtocol for PyObjectRef { +#[derive(Debug)] +enum Never {} + +impl PyValue for Never { + fn class(_vm: &VirtualMachine) -> PyObjectRef { + unreachable!() + } +} + +impl IdProtocol for PyObject { fn get_id(&self) -> usize { - &*self as &PyObject as *const PyObject as usize + self as *const _ as *const PyObject as usize + } +} + +impl IdProtocol for Rc { + fn get_id(&self) -> usize { + (**self).get_id() + } +} + +impl IdProtocol for PyRef { + fn get_id(&self) -> usize { + self.obj.get_id() } } @@ -846,7 +870,10 @@ impl TypeProtocol for PyObjectRef { } } -impl TypeProtocol for PyObject { +impl TypeProtocol for PyObject +where + T: ?Sized + PyObjectPayload, +{ fn type_ref(&self) -> &PyObjectRef { &self.typ } @@ -985,9 +1012,9 @@ impl BufferProtocol for PyObjectRef { } } -impl fmt::Debug for PyObject { +impl fmt::Debug for PyObject { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[PyObj {:?}]", self.payload) + write!(f, "[PyObj {:?}]", &self.payload) } } @@ -1159,21 +1186,24 @@ impl PyValue for PyIteratorValue { } } -impl PyObject { - pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { +impl PyObject +where + T: Sized + PyObjectPayload, +{ + pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { typ, dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(payload), + payload, } .into_ref() } - pub fn new_without_dict(payload: T, typ: PyObjectRef) -> PyObjectRef { + pub fn new_without_dict(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { typ, dict: None, - payload: Box::new(payload), + payload, } .into_ref() } @@ -1182,7 +1212,9 @@ impl PyObject { pub fn into_ref(self) -> PyObjectRef { Rc::new(self) } +} +impl PyObject { #[inline] pub fn payload(&self) -> Option<&T> { self.payload.as_any().downcast_ref() @@ -1245,7 +1277,7 @@ impl FromPyObjectRef for PyRef { #[cfg(test)] mod tests { - use super::PyContext; + use super::*; #[test] fn test_type_type() { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index fc7d01745..8268b1058 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -335,7 +335,7 @@ impl VirtualMachine { } // TODO: is it safe to just invoke __call__ otherwise? - trace!("invoke __call__ for: {:?}", func_ref.payload); + trace!("invoke __call__ for: {:?}", &func_ref.payload); self.call_method(&func_ref, "__call__", args) } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 9d80854f7..fd2181182 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -8,23 +8,19 @@ use wasm_bindgen::prelude::*; use rustpython_vm::compile; use rustpython_vm::frame::{NameProtocol, Scope}; use rustpython_vm::function::PyFuncArgs; -use rustpython_vm::pyobject::{PyContext, PyObjectRef, PyResult}; +use rustpython_vm::pyobject::{PyContext, PyObject, PyObjectPayload, PyObjectRef, PyResult}; use rustpython_vm::VirtualMachine; use crate::browser_module::setup_browser_module; use crate::convert; use crate::wasm_builtins; -pub trait HeldRcInner {} - -impl HeldRcInner for T {} - pub(crate) struct StoredVirtualMachine { pub vm: VirtualMachine, pub scope: RefCell, /// you can put a Rc in here, keep it as a Weak, and it'll be held only for /// as long as the StoredVM is alive - held_rcs: RefCell>>, + held_objects: RefCell>, } impl StoredVirtualMachine { @@ -38,7 +34,7 @@ impl StoredVirtualMachine { StoredVirtualMachine { vm, scope: RefCell::new(scope), - held_rcs: RefCell::new(Vec::new()), + held_objects: RefCell::new(Vec::new()), } } } @@ -178,13 +174,13 @@ impl WASMVirtualMachine { STORED_VMS.with(|cell| cell.borrow().contains_key(&self.id)) } - pub(crate) fn push_held_rc( + pub(crate) fn push_held_rc( &self, - rc: Rc, - ) -> Result, JsValue> { + obj: PyObjectRef, + ) -> Result>, JsValue> { self.with(|stored_vm| { - let weak = Rc::downgrade(&rc); - stored_vm.held_rcs.borrow_mut().push(rc); + let weak = Rc::downgrade(&obj); + stored_vm.held_objects.borrow_mut().push(obj); weak }) }