diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 8fd7772f21..9c336718f2 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -339,10 +339,10 @@ pub fn new( let mros = bases.into_iter().map(|x| _mro(&x)).collect(); let mro = linearise_mro(mros).unwrap(); Ok(PyObject { - payload: Box::new(PyClass { + payload: PyClass { name: String::from(name), mro, - }), + }, dict: Some(RefCell::new(dict)), typ, } diff --git a/vm/src/obj/objweakref.rs b/vm/src/obj/objweakref.rs index ab9a5881b4..1dcdbe582c 100644 --- a/vm/src/obj/objweakref.rs +++ b/vm/src/obj/objweakref.rs @@ -1,13 +1,13 @@ use crate::obj::objtype::PyClassRef; use crate::pyobject::PyValue; -use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyRef, PyResult}; +use crate::pyobject::{PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult}; use crate::vm::VirtualMachine; use std::rc::{Rc, Weak}; #[derive(Debug)] pub struct PyWeak { - referent: Weak, + referent: Weak>, } impl PyWeak { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 9bd94ec707..5e7d568d1b 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -71,7 +71,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 @@ -82,7 +82,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::() { @@ -187,25 +187,25 @@ fn init_type_hierarchy() -> (PyObjectRef, PyObjectRef) { 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()); @@ -627,7 +627,7 @@ impl PyContext { PyObject { typ: class, dict: Some(RefCell::new(dict)), - payload: Box::new(objobject::PyInstance), + payload: objobject::PyInstance, } .into_ref() } @@ -690,10 +690,10 @@ 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 { pub typ: PyObjectRef, pub dict: Option>, // __dict__ member - pub payload: Box, + pub payload: T, } /// A reference to a Python object. @@ -706,7 +706,7 @@ pub struct PyObject { /// situations (such as when implementing in-place methods such as `__iadd__`) /// where a reference to the same object must be returned. #[derive(Clone, Debug)] -pub struct PyRef { +pub struct PyRef { // invariant: this obj must always have payload of type T obj: PyObjectRef, _payload: PhantomData, @@ -749,10 +749,7 @@ impl PyRef { } } -impl Deref for PyRef -where - T: PyValue, -{ +impl Deref for PyRef { type Target = T; fn deref(&self) -> &T { @@ -760,10 +757,7 @@ where } } -impl TryFromObject for PyRef -where - T: PyValue, -{ +impl TryFromObject for PyRef { fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult { if objtype::isinstance(&obj, &T::class(vm)) { Ok(PyRef { @@ -788,7 +782,7 @@ impl IntoPyObject for PyRef { } } -impl fmt::Display for PyRef { +impl fmt::Display for PyRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.obj.fmt(f) } @@ -806,7 +800,10 @@ pub trait IdProtocol { impl IdProtocol for PyObjectRef { fn get_id(&self) -> usize { - &*self as &PyObject as *const PyObject as usize + // This is kinda ridiculous... + // + // Rc -> (fat) shared ref -> (fat) pointer -> (thin) pointer -> usize + &*self as &_ as *const _ as *const PyObject<()> as usize } } @@ -830,7 +827,7 @@ impl TypeProtocol for PyObjectRef { } } -impl TypeProtocol for PyObject { +impl TypeProtocol for PyObject { fn type_ref(&self) -> &PyObjectRef { &self.typ } @@ -969,9 +966,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) } } @@ -1553,12 +1550,12 @@ impl PyValue for PyIteratorValue { } } -impl PyObject { - pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { +impl PyObject { + pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { typ, dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(payload), + payload, } .into_ref() } @@ -1567,7 +1564,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() diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 45b5d7d3d6..85692f0c6c 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -330,7 +330,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) } @@ -554,7 +554,7 @@ impl VirtualMachine { let cls = obj.typ(); match cls.get_attr(method_name) { Some(method) => self.call_get_descriptor(method, obj.clone()), - None => Err(self.new_type_error(format!("{} has no method {:?}", obj, method_name))), + None => Err(self.new_type_error(format!("{} has no method {:?}", &obj, method_name))), } } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 4ef2b664b7..38b6faada5 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -5,7 +5,7 @@ use js_sys::{Object, Reflect, SyntaxError, TypeError}; use rustpython_vm::{ compile, frame::{NameProtocol, Scope}, - pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult}, + pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult}, VirtualMachine, }; use std::cell::RefCell; @@ -13,16 +13,12 @@ use std::collections::HashMap; use std::rc::{Rc, Weak}; use wasm_bindgen::{prelude::*, JsCast}; -pub trait HeldRcInner {} - -impl HeldRcInner for T {} - pub(crate) struct StoredVirtualMachine { pub vm: VirtualMachine, pub scope: Scope, /// 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: Vec>, + held_rcs: Vec, } impl StoredVirtualMachine { @@ -222,10 +218,10 @@ 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> { + rc: PyObjectRef, + ) -> Result>, JsValue> { self.with(|stored_vm| { let weak = Rc::downgrade(&rc); stored_vm.held_rcs.push(rc);