diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index 94f42c84f1..3ada08f7dc 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -270,8 +270,6 @@ def test_attrs(self): tb.tb_next = new_tb self.assertIs(tb.tb_next, new_tb) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_constructor(self): other_tb = get_tb() frame = sys._getframe() diff --git a/derive-impl/src/pyclass.rs b/derive-impl/src/pyclass.rs index b704e083c6..b0d75aa00f 100644 --- a/derive-impl/src/pyclass.rs +++ b/derive-impl/src/pyclass.rs @@ -303,13 +303,15 @@ pub(crate) fn impl_pyclass_impl(attr: PunctuatedNestedMeta, item: Item) -> Resul Ok(tokens) } +#[allow(clippy::too_many_arguments)] fn generate_class_def( ident: &Ident, name: &str, module_name: Option<&str>, - base: Option, + base: Option<&syn::ExprPath>, metaclass: Option, unhashable: bool, + is_pystruct: bool, attrs: &[Attribute], ) -> Result { let doc = attrs.doc().or_else(|| { @@ -340,26 +342,13 @@ fn generate_class_def( quote!(false) }; let basicsize = quote!(std::mem::size_of::<#ident>()); - let is_pystruct = attrs.iter().any(|attr| { - attr.path().is_ident("derive") - && if let Ok(Meta::List(l)) = attr.parse_meta() { - l.nested - .into_iter() - .any(|n| n.get_ident().is_some_and(|p| p == "PyStructSequence")) - } else { - false - } - }); if base.is_some() && is_pystruct { bail_span!(ident, "PyStructSequence cannot have `base` class attr",); } let base_class = if is_pystruct { Some(quote! { rustpython_vm::builtins::PyTuple }) } else { - base.as_ref().map(|typ| { - let typ = Ident::new(typ, ident.span()); - quote_spanned! { ident.span() => #typ } - }) + base.map(|typ| quote!(#typ)) } .map(|typ| { quote! { @@ -381,12 +370,21 @@ fn generate_class_def( }); let base_or_object = if let Some(base) = base { - let base = Ident::new(&base, ident.span()); quote! { #base } } else { quote! { ::rustpython_vm::builtins::PyBaseObject } }; + let type_id = if is_pystruct { + quote!(::std::option::Option::None) + } else { + quote! { + fn _check<__T: ::rustpython_vm::PyPayload>() {} + _check::(); + ::std::option::Option::Some(::std::any::TypeId::of::()) + } + }; + let tokens = quote! { impl ::rustpython_vm::class::PyClassDef for #ident { const NAME: &'static str = #name; @@ -399,7 +397,7 @@ fn generate_class_def( type Base = #base_or_object; } - impl ::rustpython_vm::class::StaticType for #ident { + unsafe impl ::rustpython_vm::class::StaticType for #ident { fn static_cell() -> &'static ::rustpython_vm::common::static_cell::StaticCell<::rustpython_vm::builtins::PyTypeRef> { ::rustpython_vm::common::static_cell! { static CELL: ::rustpython_vm::builtins::PyTypeRef; @@ -407,6 +405,10 @@ fn generate_class_def( &CELL } + fn type_id() -> ::std::option::Option<::std::any::TypeId> { + #type_id + } + #meta_class #base_class @@ -427,6 +429,18 @@ pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result Result Result::static_type()) + }; quote! { impl ::rustpython_vm::PyPayload for #ident { + type Super = #base_ty; fn class(ctx: &::rustpython_vm::vm::Context) -> &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType> { - ctx.types.#ctx_type_ident + #get_class } } } @@ -537,21 +561,12 @@ pub(crate) fn impl_pyexception(attr: PunctuatedNestedMeta, item: Item) -> Result let class_meta = ExceptionItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?; let class_name = class_meta.class_name()?; - let base_class_name = class_meta.base()?; - let impl_payload = if let Some(ctx_type_name) = class_meta.ctx_name()? { - let ctx_type_ident = Ident::new(&ctx_type_name, ident.span()); // FIXME span - - // We need this to make extend mechanism work: - quote! { - impl ::rustpython_vm::PyPayload for #ident { - fn class(ctx: &::rustpython_vm::vm::Context) -> &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType> { - ctx.exceptions.#ctx_type_ident - } - } - } - } else { - quote! {} - }; + let base_class_name = class_meta + .base()? + .ok_or_else(|| syn::Error::new(Span::call_site(), "pyexception must specify base"))?; + let ctx_type_ident = class_meta + .ctx_name()? + .ok_or_else(|| syn::Error::new(Span::call_site(), "pyexception must specify ctx"))?; let impl_pyclass = if class_meta.has_impl()? { quote! { #[pyexception] @@ -562,9 +577,8 @@ pub(crate) fn impl_pyexception(attr: PunctuatedNestedMeta, item: Item) -> Result }; let ret = quote! { - #[pyclass(module = false, name = #class_name, base = #base_class_name)] + #[pyclass(module = false, name = #class_name, base = #base_class_name, exception_ctx = #ctx_type_ident)] #item - #impl_payload #impl_pyclass }; Ok(ret) diff --git a/derive-impl/src/pypayload.rs b/derive-impl/src/pypayload.rs index a72c36148a..29377fd296 100644 --- a/derive-impl/src/pypayload.rs +++ b/derive-impl/src/pypayload.rs @@ -7,6 +7,7 @@ pub(crate) fn impl_pypayload(input: DeriveInput) -> Result { let ret = quote! { impl ::rustpython_vm::PyPayload for #ty { + type Super = ::rustpython_vm::builtins::PyBaseObject; fn class(_ctx: &::rustpython_vm::vm::Context) -> &'static rustpython_vm::Py<::rustpython_vm::builtins::PyType> { ::static_type() } diff --git a/derive-impl/src/util.rs b/derive-impl/src/util.rs index 7e0eb96fb0..d589615ad8 100644 --- a/derive-impl/src/util.rs +++ b/derive-impl/src/util.rs @@ -187,6 +187,51 @@ impl ItemMetaInner { Ok(value) } + pub fn _optional_path(&self, key: &str) -> Result> { + let value = if let Some((_, meta)) = self.meta_map.get(key) { + let Meta::NameValue(syn::MetaNameValue { + value: syn::Expr::Path(path), + .. + }) = meta + else { + bail_span!( + meta, + "#[{}({} = ...)] must exist as a path", + self.meta_name(), + key + ) + }; + Some(path) + } else { + None + }; + Ok(value) + } + + pub fn _optional_ident(&self, key: &str) -> Result> { + let Some((_, meta)) = self.meta_map.get(key) else { + return Ok(None); + }; + if let Meta::NameValue(syn::MetaNameValue { + value: + syn::Expr::Path(syn::ExprPath { + qself: None, path, .. + }), + .. + }) = meta + { + if let Some(ident) = path.get_ident() { + return Ok(Some(ident)); + } + } + bail_span!( + meta, + "#[{}({} = ...)] must exist as an ident", + self.meta_name(), + key + ) + } + pub fn _has_key(&self, key: &str) -> Result { Ok(matches!(self.meta_map.get(key), Some((_, _)))) } @@ -336,7 +381,9 @@ impl ItemMeta for ClassItemMeta { "base", "metaclass", "unhashable", + "manual_payload", "ctx", + "exception_ctx", "impl", "traverse", ]; @@ -375,18 +422,26 @@ impl ClassItemMeta { ) } - pub fn ctx_name(&self) -> Result> { - self.inner()._optional_str("ctx") + pub fn ctx_name(&self) -> Result> { + self.inner()._optional_ident("ctx") } - pub fn base(&self) -> Result> { - self.inner()._optional_str("base") + pub fn exception_ctx_name(&self) -> Result> { + self.inner()._optional_ident("exception_ctx") + } + + pub fn base(&self) -> Result> { + self.inner()._optional_path("base") } pub fn unhashable(&self) -> Result { self.inner()._bool("unhashable") } + pub fn manual_payload(&self) -> Result { + self.inner()._bool("manual_payload") + } + pub fn metaclass(&self) -> Result> { self.inner()._optional_str("metaclass") } diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 2a7b3d68fc..ae6c615798 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -34,7 +34,7 @@ pub fn derive_from_args(input: TokenStream) -> TokenStream { /// - `IMMUTABLETYPE`: class attributes are immutable. /// - `with`: which trait implementations are to be included in the python class. /// ```rust, ignore -/// #[pyclass(module = "my_module", name = "MyClass", base = "BaseClass")] +/// #[pyclass(module = "my_module", name = "MyClass", base = BaseClass)] /// struct MyStruct { /// x: i32, /// } diff --git a/examples/call_between_rust_and_python.rs b/examples/call_between_rust_and_python.rs index 576390d059..e4314ba90a 100644 --- a/examples/call_between_rust_and_python.rs +++ b/examples/call_between_rust_and_python.rs @@ -1,5 +1,5 @@ use rustpython::vm::{ - PyObject, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine, pyclass, pymodule, + PyObject, PyResult, TryFromBorrowedObject, VirtualMachine, pyclass, pymodule, }; pub fn main() { @@ -64,7 +64,7 @@ python_person.name: {}", #[pyattr] #[pyclass(module = "rust_py_module", name = "RustStruct")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct RustStruct { numbers: NumVec, } diff --git a/extra_tests/snippets/stdlib_ctypes.py b/extra_tests/snippets/stdlib_ctypes.py index 95ee9900fb..47b436dc4e 100644 --- a/extra_tests/snippets/stdlib_ctypes.py +++ b/extra_tests/snippets/stdlib_ctypes.py @@ -266,8 +266,8 @@ def LoadLibrary(self, name): cdll = LibraryLoader(CDLL) -test_byte_array = create_string_buffer(b"Hello, World!\n") -assert test_byte_array._length_ == 15 +# test_byte_array = create_string_buffer(b"Hello, World!\n") +# assert test_byte_array._length_ == 15 if _os.name == "posix" or _sys.platform == "darwin": pass @@ -279,8 +279,8 @@ def LoadLibrary(self, name): i = c_int(1) print("start srand") print(libc.srand(i)) - print(test_byte_array) - print(test_byte_array._type_) + # print(test_byte_array) + # print(test_byte_array._type_) # print("start printf") # libc.printf(test_byte_array) diff --git a/stdlib/src/array.rs b/stdlib/src/array.rs index db4394e44f..ab47b2e57c 100644 --- a/stdlib/src/array.rs +++ b/stdlib/src/array.rs @@ -622,7 +622,7 @@ mod array { #[pyattr] #[pyattr(name = "ArrayType")] #[pyclass(name = "array")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub struct PyArray { array: PyRwLock, exports: AtomicUsize, @@ -1387,7 +1387,7 @@ mod array { #[pyattr] #[pyclass(name = "arrayiterator", traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub struct PyArrayIter { internal: PyMutex>, } diff --git a/stdlib/src/bz2.rs b/stdlib/src/bz2.rs index ba74a38db1..fca23642c8 100644 --- a/stdlib/src/bz2.rs +++ b/stdlib/src/bz2.rs @@ -27,7 +27,7 @@ mod _bz2 { #[pyattr] #[pyclass(name = "BZ2Decompressor")] - #[derive(PyPayload)] + #[derive()] struct BZ2Decompressor { state: PyMutex, } @@ -172,7 +172,7 @@ mod _bz2 { #[pyattr] #[pyclass(name = "BZ2Compressor")] - #[derive(PyPayload)] + #[derive()] struct BZ2Compressor { state: PyMutex, } diff --git a/stdlib/src/contextvars.rs b/stdlib/src/contextvars.rs index 4fd45842b9..b71f99c513 100644 --- a/stdlib/src/contextvars.rs +++ b/stdlib/src/contextvars.rs @@ -43,7 +43,7 @@ mod _contextvars { type Hamt = IndexMap, PyObjectRef, ahash::RandomState>; #[pyclass(no_attr, name = "Hamt", module = "contextvars")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(crate) struct HamtObject { hamt: RefCell, } @@ -73,7 +73,7 @@ mod _contextvars { #[pyattr] #[pyclass(name = "Context")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(crate) struct PyContext { // not to confuse with vm::Context inner: ContextInner, @@ -287,7 +287,7 @@ mod _contextvars { #[pyattr] #[pyclass(name, traverse)] - #[derive(PyPayload)] + #[derive()] struct ContextVar { #[pytraverse(skip)] name: String, @@ -537,7 +537,7 @@ mod _contextvars { #[pyattr] #[pyclass(name = "Token")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct ContextToken { ctx: PyRef, // tok_ctx in CPython var: PyRef, // tok_var in CPython @@ -585,7 +585,7 @@ mod _contextvars { } #[pyclass(no_attr, name = "Token.MISSING")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(super) struct ContextTokenMissing {} #[pyclass(with(Representable))] diff --git a/stdlib/src/csv.rs b/stdlib/src/csv.rs index 730d3b2feb..105ab48da0 100644 --- a/stdlib/src/csv.rs +++ b/stdlib/src/csv.rs @@ -53,7 +53,7 @@ mod _csv { #[pyattr] #[pyclass(module = "csv", name = "Dialect")] - #[derive(Debug, PyPayload, Clone, Copy)] + #[derive(Debug, Clone, Copy)] struct PyDialect { delimiter: u8, quotechar: Option, @@ -900,7 +900,7 @@ mod _csv { } #[pyclass(no_attr, module = "_csv", name = "reader", traverse)] - #[derive(PyPayload)] + #[derive()] pub(super) struct Reader { iter: PyIter, #[pytraverse(skip)] @@ -1054,7 +1054,7 @@ mod _csv { } #[pyclass(no_attr, module = "_csv", name = "writer", traverse)] - #[derive(PyPayload)] + #[derive()] pub(super) struct Writer { write: PyObjectRef, #[pytraverse(skip)] diff --git a/stdlib/src/hashlib.rs b/stdlib/src/hashlib.rs index 586d825b2c..7941744e81 100644 --- a/stdlib/src/hashlib.rs +++ b/stdlib/src/hashlib.rs @@ -84,7 +84,7 @@ pub mod _hashlib { #[pyattr] #[pyclass(module = "_hashlib", name = "HASH")] - #[derive(PyPayload)] + #[derive()] pub struct PyHasher { pub name: String, pub ctx: PyRwLock, @@ -148,7 +148,7 @@ pub mod _hashlib { #[pyattr] #[pyclass(module = "_hashlib", name = "HASHXOF")] - #[derive(PyPayload)] + #[derive()] pub struct PyHasherXof { name: String, ctx: PyRwLock, diff --git a/stdlib/src/json.rs b/stdlib/src/json.rs index f970ef5dc2..7c94bc3a67 100644 --- a/stdlib/src/json.rs +++ b/stdlib/src/json.rs @@ -18,7 +18,7 @@ mod _json { #[pyattr(name = "make_scanner")] #[pyclass(name = "Scanner", traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct JsonScanner { #[pytraverse(skip)] strict: bool, diff --git a/stdlib/src/mmap.rs b/stdlib/src/mmap.rs index bca367ae4d..d1087a278f 100644 --- a/stdlib/src/mmap.rs +++ b/stdlib/src/mmap.rs @@ -173,7 +173,7 @@ mod mmap { #[pyattr] #[pyclass(name = "mmap")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyMmap { closed: AtomicCell, mmap: PyMutex>, diff --git a/stdlib/src/overlapped.rs b/stdlib/src/overlapped.rs index 6fd8a1516d..1b2fb392e4 100644 --- a/stdlib/src/overlapped.rs +++ b/stdlib/src/overlapped.rs @@ -43,7 +43,7 @@ mod _overlapped { #[pyattr] #[pyclass(name)] - #[derive(PyPayload)] + #[derive()] struct Overlapped { inner: PyMutex, } diff --git a/stdlib/src/pyexpat.rs b/stdlib/src/pyexpat.rs index 2363e6bed4..c19aa363db 100644 --- a/stdlib/src/pyexpat.rs +++ b/stdlib/src/pyexpat.rs @@ -44,7 +44,7 @@ mod _pyexpat { #[pyattr] #[pyclass(name = "xmlparser", module = false, traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub struct PyExpatLikeXmlParser { start_element: MutableObject, end_element: MutableObject, diff --git a/stdlib/src/pystruct.rs b/stdlib/src/pystruct.rs index 9426470911..2820ed5d97 100644 --- a/stdlib/src/pystruct.rs +++ b/stdlib/src/pystruct.rs @@ -153,7 +153,7 @@ pub(crate) mod _struct { #[pyattr] #[pyclass(name = "unpack_iterator", traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct UnpackIterator { #[pytraverse(skip)] format_spec: FormatSpec, @@ -232,7 +232,7 @@ pub(crate) mod _struct { #[pyattr] #[pyclass(name = "Struct", traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyStruct { #[pytraverse(skip)] spec: FormatSpec, diff --git a/stdlib/src/random.rs b/stdlib/src/random.rs index a2aaff2612..bef6aa4c41 100644 --- a/stdlib/src/random.rs +++ b/stdlib/src/random.rs @@ -6,7 +6,7 @@ pub(crate) use _random::make_module; mod _random { use crate::common::lock::PyMutex; use crate::vm::{ - PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + PyObjectRef, PyRef, PyResult, VirtualMachine, builtins::{PyInt, PyTupleRef}, convert::ToPyException, function::OptionalOption, @@ -21,7 +21,7 @@ mod _random { #[pyattr] #[pyclass(name = "Random")] - #[derive(Debug, PyPayload, Default)] + #[derive(Debug, Default)] struct PyRandom { rng: PyMutex, } diff --git a/stdlib/src/re.rs b/stdlib/src/re.rs index 647f4c69ad..8a38113712 100644 --- a/stdlib/src/re.rs +++ b/stdlib/src/re.rs @@ -22,7 +22,7 @@ mod re { #[pyattr] #[pyclass(module = "re", name = "Pattern")] - #[derive(Debug, PyPayload)] + #[derive(Debug, )] struct PyPattern { regex: Regex, pattern: String, @@ -78,7 +78,7 @@ mod re { /// Inner data for a match object. #[pyattr] #[pyclass(module = "re", name = "Match", traverse)] - #[derive(PyPayload, Traverse)] + #[derive(, Traverse)] struct PyMatch { haystack: PyStrRef, #[pytraverse(skip)] diff --git a/stdlib/src/select.rs b/stdlib/src/select.rs index f89a6c4f03..6e4ddfe586 100644 --- a/stdlib/src/select.rs +++ b/stdlib/src/select.rs @@ -329,7 +329,7 @@ mod decl { pub(super) mod poll { use super::*; use crate::vm::{ - AsObject, PyPayload, + AsObject, builtins::PyFloat, common::lock::PyMutex, convert::{IntoPyException, ToPyObject}, @@ -384,7 +384,7 @@ mod decl { } #[pyclass(module = "select", name = "poll")] - #[derive(Default, Debug, PyPayload)] + #[derive(Default, Debug)] pub struct PyPoll { // keep sorted fds: PyMutex>, @@ -522,7 +522,7 @@ mod decl { use std::time::{Duration, Instant}; #[pyclass(module = "select", name = "epoll")] - #[derive(Debug, rustpython_vm::PyPayload)] + #[derive(Debug)] pub struct PyEpoll { epoll_fd: PyRwLock>, } diff --git a/stdlib/src/socket.rs b/stdlib/src/socket.rs index f4f90a5dc4..0606fbcd13 100644 --- a/stdlib/src/socket.rs +++ b/stdlib/src/socket.rs @@ -14,7 +14,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyRef { mod _socket { use crate::common::lock::{PyMappedRwLockReadGuard, PyRwLock, PyRwLockReadGuard}; use crate::vm::{ - AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Py, PyObjectRef, PyRef, PyResult, VirtualMachine, builtins::{PyBaseExceptionRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef}, common::os::ErrorExt, convert::{IntoPyException, ToPyObject, TryFromBorrowedObject, TryFromObject}, @@ -783,7 +783,7 @@ mod _socket { #[pyattr(name = "socket")] #[pyattr(name = "SocketType")] #[pyclass(name = "socket")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub struct PySocket { kind: AtomicCell, family: AtomicCell, diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 00ebec75a9..55b9b844bb 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -807,7 +807,7 @@ mod _sqlite { #[pyattr] #[pyclass(name)] - #[derive(PyPayload)] + #[derive()] struct Connection { db: PyMutex>, detect_types: c_int, @@ -1395,7 +1395,7 @@ mod _sqlite { #[pyattr] #[pyclass(name, traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Cursor { connection: PyRef, #[pytraverse(skip)] @@ -1852,7 +1852,7 @@ mod _sqlite { #[pyattr] #[pyclass(name, traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Row { data: PyTupleRef, description: PyTupleRef, @@ -1983,7 +1983,7 @@ mod _sqlite { #[pyattr] #[pyclass(name, traverse)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Blob { connection: PyRef, #[pytraverse(skip)] @@ -2244,7 +2244,7 @@ mod _sqlite { #[pyattr] #[pyclass(name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PrepareProtocol {} #[pyclass()] @@ -2252,7 +2252,7 @@ mod _sqlite { #[pyattr] #[pyclass(name)] - #[derive(PyPayload)] + #[derive()] struct Statement { st: PyMutex, pub is_dml: bool, diff --git a/stdlib/src/ssl.rs b/stdlib/src/ssl.rs index 6cc7f3ed32..3bab33101a 100644 --- a/stdlib/src/ssl.rs +++ b/stdlib/src/ssl.rs @@ -450,7 +450,7 @@ mod _ssl { #[pyattr] #[pyclass(module = "ssl", name = "_SSLContext")] - #[derive(PyPayload)] + #[derive()] struct PySslContext { ctx: PyRwLock, check_hostname: AtomicCell, @@ -944,7 +944,7 @@ mod _ssl { #[pyattr] #[pyclass(module = "ssl", name = "_SSLSocket", traverse)] - #[derive(PyPayload)] + #[derive()] struct PySslSocket { ctx: PyRef, #[pytraverse(skip)] diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 242570b410..997011513a 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -75,7 +75,7 @@ mod _tkinter { #[pyattr] #[pyclass(name = "tkapp")] - #[derive(PyPayload)] + #[derive()] struct TkApp { // Tcl_Interp *interp; interpreter: *mut tk_sys::Tcl_Interp, diff --git a/stdlib/src/unicodedata.rs b/stdlib/src/unicodedata.rs index 9af921d360..c31df7193b 100644 --- a/stdlib/src/unicodedata.rs +++ b/stdlib/src/unicodedata.rs @@ -75,7 +75,7 @@ mod unicodedata { #[pyattr] #[pyclass(name = "UCD")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(super) struct Ucd { unic_version: UnicodeVersion, } diff --git a/stdlib/src/zlib.rs b/stdlib/src/zlib.rs index 9c19b74066..d39bcca9fd 100644 --- a/stdlib/src/zlib.rs +++ b/stdlib/src/zlib.rs @@ -338,7 +338,7 @@ mod zlib { #[pyattr] #[pyclass(name = "Decompress")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyDecompress { inner: PyMutex, } @@ -492,7 +492,7 @@ mod zlib { #[pyattr] #[pyclass(name = "Compress")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyCompress { inner: PyMutex, } @@ -624,7 +624,7 @@ mod zlib { #[pyattr] #[pyclass(name = "_ZlibDecompressor")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct ZlibDecompressor { inner: PyMutex, } diff --git a/vm/src/builtins/asyncgenerator.rs b/vm/src/builtins/asyncgenerator.rs index 3aee327e5b..5107eb82d7 100644 --- a/vm/src/builtins/asyncgenerator.rs +++ b/vm/src/builtins/asyncgenerator.rs @@ -1,6 +1,6 @@ -use super::{PyCode, PyGenericAlias, PyStrRef, PyType, PyTypeRef}; +use super::{PyCode, PyGenericAlias, PyStrRef, PyTypeRef}; use crate::{ - AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObjectRef, PyRef, PyResult, VirtualMachine, builtins::PyBaseExceptionRef, class::PyClassImpl, coroutine::Coro, @@ -12,7 +12,7 @@ use crate::{ use crossbeam_utils::atomic::AtomicCell; -#[pyclass(name = "async_generator", module = false)] +#[pyclass(name = "async_generator", module = false, ctx = async_generator)] #[derive(Debug)] pub struct PyAsyncGen { inner: Coro, @@ -20,12 +20,6 @@ pub struct PyAsyncGen { } type PyAsyncGenRef = PyRef; -impl PyPayload for PyAsyncGen { - fn class(ctx: &Context) -> &'static Py { - ctx.types.async_generator - } -} - #[pyclass(with(PyRef, Unconstructible, Representable))] impl PyAsyncGen { pub fn as_coro(&self) -> &Coro { @@ -137,14 +131,9 @@ impl Representable for PyAsyncGen { impl Unconstructible for PyAsyncGen {} -#[pyclass(module = false, name = "async_generator_wrapped_value")] +#[pyclass(module = false, name = "async_generator_wrapped_value", ctx = async_generator_wrapped_value)] #[derive(Debug)] pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef); -impl PyPayload for PyAsyncGenWrappedValue { - fn class(ctx: &Context) -> &'static Py { - ctx.types.async_generator_wrapped_value - } -} #[pyclass] impl PyAsyncGenWrappedValue {} @@ -181,7 +170,7 @@ enum AwaitableState { Closed, } -#[pyclass(module = false, name = "async_generator_asend")] +#[pyclass(module = false, name = "async_generator_asend", ctx = async_generator_asend)] #[derive(Debug)] pub(crate) struct PyAsyncGenASend { ag: PyAsyncGenRef, @@ -189,12 +178,6 @@ pub(crate) struct PyAsyncGenASend { value: PyObjectRef, } -impl PyPayload for PyAsyncGenASend { - fn class(ctx: &Context) -> &'static Py { - ctx.types.async_generator_asend - } -} - #[pyclass(with(IterNext, Iterable))] impl PyAsyncGenASend { #[pymethod(name = "__await__")] @@ -275,7 +258,7 @@ impl IterNext for PyAsyncGenASend { } } -#[pyclass(module = false, name = "async_generator_athrow")] +#[pyclass(module = false, name = "async_generator_athrow", ctx = async_generator_athrow)] #[derive(Debug)] pub(crate) struct PyAsyncGenAThrow { ag: PyAsyncGenRef, @@ -284,12 +267,6 @@ pub(crate) struct PyAsyncGenAThrow { value: (PyObjectRef, PyObjectRef, PyObjectRef), } -impl PyPayload for PyAsyncGenAThrow { - fn class(ctx: &Context) -> &'static Py { - ctx.types.async_generator_athrow - } -} - #[pyclass(with(IterNext, Iterable))] impl PyAsyncGenAThrow { #[pymethod(name = "__await__")] diff --git a/vm/src/builtins/bool.rs b/vm/src/builtins/bool.rs index 006fc4d1eb..dabf8e4309 100644 --- a/vm/src/builtins/bool.rs +++ b/vm/src/builtins/bool.rs @@ -1,8 +1,7 @@ -use super::{PyInt, PyStrRef, PyType, PyTypeRef}; +use super::{PyInt, PyStrRef, PyTypeRef}; use crate::common::format::FormatSpec; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject, - VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyResult, TryFromBorrowedObject, VirtualMachine, class::PyClassImpl, convert::{IntoPyException, ToPyObject, ToPyResult}, function::OptionalArg, @@ -77,15 +76,9 @@ impl PyObjectRef { } } -#[pyclass(name = "bool", module = false, base = "PyInt")] +#[pyclass(name = "bool", module = false, base = PyInt, ctx = bool_type)] pub struct PyBool; -impl PyPayload for PyBool { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bool_type - } -} - impl Debug for PyBool { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { todo!() diff --git a/vm/src/builtins/builtin_func.rs b/vm/src/builtins/builtin_func.rs index ff3ef38d3a..27ebc69e32 100644 --- a/vm/src/builtins/builtin_func.rs +++ b/vm/src/builtins/builtin_func.rs @@ -1,6 +1,6 @@ use super::{PyStrInterned, PyStrRef, PyType, type_}; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyRef, PyResult, VirtualMachine, class::PyClassImpl, convert::TryFromObject, function::{FuncArgs, PyComparisonValue, PyMethodDef, PyMethodFlags, PyNativeFn}, @@ -9,19 +9,13 @@ use crate::{ use std::fmt; // PyCFunctionObject in CPython -#[pyclass(name = "builtin_function_or_method", module = false)] +#[pyclass(name = "builtin_function_or_method", module = false, ctx = builtin_function_or_method_type)] pub struct PyNativeFunction { pub(crate) value: &'static PyMethodDef, pub(crate) zelf: Option, pub(crate) module: Option<&'static PyStrInterned>, // None for bound method } -impl PyPayload for PyNativeFunction { - fn class(ctx: &Context) -> &'static Py { - ctx.types.builtin_function_or_method_type - } -} - impl fmt::Debug for PyNativeFunction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -140,9 +134,8 @@ impl Representable for PyNativeFunction { impl Unconstructible for PyNativeFunction {} // `PyCMethodObject` in CPython -#[pyclass(name = "builtin_method", module = false, base = "PyNativeFunction")] +#[pyclass(name = "builtin_method", module = false, base = PyNativeFunction, ctx = builtin_method_type)] pub struct PyNativeMethod { - pub(crate) func: PyNativeFunction, pub(crate) class: &'static Py, // TODO: the actual life is &'self } @@ -156,42 +149,34 @@ impl PyNativeMethod { let prefix = zelf.class.name().to_string(); Ok(vm .ctx - .new_str(format!("{}.{}", prefix, &zelf.func.value.name))) + .new_str(format!("{}.{}", prefix, &zelf.super_().value.name))) } #[pymethod(magic)] - fn reduce(&self, vm: &VirtualMachine) -> PyResult<(PyObjectRef, (PyObjectRef, &'static str))> { - // TODO: return (getattr, (self.object, self.name)) if this is a method + fn reduce( + zelf: &Py, + vm: &VirtualMachine, + ) -> PyResult<(PyObjectRef, (PyObjectRef, &'static str))> { + // TODO: return (getattr, (zelf.object, zelf.name)) if this is a method let getattr = vm.builtins.get_attr("getattr", vm)?; - let target = self - .func + let target = zelf + .super_() .zelf .clone() - .unwrap_or_else(|| self.class.to_owned().into()); - let name = self.func.value.name; + .unwrap_or_else(|| zelf.class.to_owned().into()); + let name = zelf.super_().value.name; Ok((getattr, (target, name))) } #[pygetset(name = "__self__")] fn __self__(zelf: PyRef, _vm: &VirtualMachine) -> Option { - zelf.func.zelf.clone() - } -} - -impl PyPayload for PyNativeMethod { - fn class(ctx: &Context) -> &'static Py { - ctx.types.builtin_method_type + zelf.super_().zelf.clone() } } impl fmt::Debug for PyNativeMethod { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "builtin method of {:?} with {:?}", - &*self.class.name(), - &self.func - ) + write!(f, "builtin method of {:?}", &*self.class.name(),) } } @@ -203,13 +188,13 @@ impl Comparable for PyNativeMethod { _vm: &VirtualMachine, ) -> PyResult { op.eq_only(|| { - if let Some(other) = other.payload::() { - let eq = match (zelf.func.zelf.as_ref(), other.func.zelf.as_ref()) { + if let Some(other) = other.downcast_ref::() { + let eq = match (zelf.super_().zelf.as_ref(), other.super_().zelf.as_ref()) { (Some(z), Some(o)) => z.is(o), (None, None) => true, _ => false, }; - let eq = eq && std::ptr::eq(zelf.func.value, other.func.value); + let eq = eq && std::ptr::eq(zelf.super_().value, other.super_().value); Ok(eq.into()) } else { Ok(PyComparisonValue::NotImplemented) @@ -222,10 +207,10 @@ impl Callable for PyNativeMethod { type Args = FuncArgs; #[inline] fn call(zelf: &Py, mut args: FuncArgs, vm: &VirtualMachine) -> PyResult { - if let Some(zelf) = &zelf.func.zelf { + if let Some(zelf) = &zelf.super_().zelf { args.prepend_arg(zelf.clone()); } - (zelf.func.value.func)(vm, args) + (zelf.super_().value.func)(vm, args) } } @@ -234,7 +219,7 @@ impl Representable for PyNativeMethod { fn repr_str(zelf: &Py, _vm: &VirtualMachine) -> PyResult { Ok(format!( "", - &zelf.func.value.name, + &zelf.super_().value.name, zelf.class.name() )) } diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index ce2232d8eb..5433c75d8b 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -39,7 +39,7 @@ use crate::{ use bstr::ByteSlice; use std::mem::size_of; -#[pyclass(module = false, name = "bytearray", unhashable = true)] +#[pyclass(module = false, name = "bytearray", unhashable = true, ctx = bytearray_type)] #[derive(Debug, Default)] pub struct PyByteArray { inner: PyRwLock, @@ -60,12 +60,6 @@ impl From> for PyByteArray { } } -impl PyPayload for PyByteArray { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bytearray_type - } -} - /// Fill bytearray class methods dictionary. pub(crate) fn init(context: &Context) { PyByteArray::extend_class(context, context.types.bytearray_type); @@ -871,18 +865,12 @@ impl Representable for PyByteArray { // obj.borrow_mut().kind = PyObjectPayload::Bytes { value }; // } -#[pyclass(module = false, name = "bytearray_iterator")] +#[pyclass(module = false, name = "bytearray_iterator", ctx = bytearray_iterator_type)] #[derive(Debug)] pub struct PyByteArrayIterator { internal: PyMutex>, } -impl PyPayload for PyByteArrayIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bytearray_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyByteArrayIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 77b9f9d526..b9104a700b 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -30,7 +30,7 @@ use bstr::ByteSlice; use std::sync::LazyLock; use std::{mem::size_of, ops::Deref}; -#[pyclass(module = false, name = "bytes")] +#[pyclass(module = false, name = "bytes", ctx = bytes_type)] #[derive(Clone, Debug)] pub struct PyBytes { inner: PyBytesInner, @@ -77,12 +77,6 @@ impl AsRef<[u8]> for PyBytesRef { } } -impl PyPayload for PyBytes { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bytes_type - } -} - pub(crate) fn init(context: &Context) { PyBytes::extend_class(context, context.types.bytes_type); PyBytesIterator::extend_class(context, context.types.bytes_iterator_type); @@ -676,18 +670,12 @@ impl Representable for PyBytes { } } -#[pyclass(module = false, name = "bytes_iterator")] +#[pyclass(module = false, name = "bytes_iterator", ctx = bytes_iterator_type)] #[derive(Debug)] pub struct PyBytesIterator { internal: PyMutex>, } -impl PyPayload for PyBytesIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bytes_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyBytesIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/classmethod.rs b/vm/src/builtins/classmethod.rs index 94b6e0ca9f..e4d7fe2969 100644 --- a/vm/src/builtins/classmethod.rs +++ b/vm/src/builtins/classmethod.rs @@ -1,4 +1,4 @@ -use super::{PyBoundMethod, PyStr, PyType, PyTypeRef}; +use super::{PyBoundMethod, PyStr, PyTypeRef}; use crate::{ AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, class::PyClassImpl, @@ -26,7 +26,7 @@ use crate::{ /// /// Class methods are different than C++ or Java static methods. /// If you want those, see the staticmethod builtin. -#[pyclass(module = false, name = "classmethod")] +#[pyclass(module = false, name = "classmethod", ctx = classmethod_type)] #[derive(Debug)] pub struct PyClassMethod { callable: PyMutex, @@ -40,12 +40,6 @@ impl From for PyClassMethod { } } -impl PyPayload for PyClassMethod { - fn class(ctx: &Context) -> &'static Py { - ctx.types.classmethod_type - } -} - impl GetDescriptor for PyClassMethod { fn descr_get( zelf: PyObjectRef, diff --git a/vm/src/builtins/code.rs b/vm/src/builtins/code.rs index 4bb209f6db..df612215be 100644 --- a/vm/src/builtins/code.rs +++ b/vm/src/builtins/code.rs @@ -2,9 +2,9 @@ */ -use super::{PyStrRef, PyTupleRef, PyType, PyTypeRef}; +use super::{PyStrRef, PyTupleRef, PyTypeRef}; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyResult, VirtualMachine, builtins::PyStrInterned, bytecode::{self, AsBag, BorrowedConstant, CodeFlags, Constant, ConstantBag}, class::{PyClassImpl, StaticType}, @@ -189,7 +189,7 @@ impl> IntoCodeObject for frozen::FrozenCodeObject { } } -#[pyclass(module = false, name = "code")] +#[pyclass(module = false, name = "code", ctx = code_type)] pub struct PyCode { pub code: CodeObject, } @@ -213,12 +213,6 @@ impl fmt::Debug for PyCode { } } -impl PyPayload for PyCode { - fn class(ctx: &Context) -> &'static Py { - ctx.types.code_type - } -} - impl Representable for PyCode { #[inline] fn repr_str(zelf: &Py, _vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/builtins/complex.rs b/vm/src/builtins/complex.rs index 02324704b3..8d211a1c49 100644 --- a/vm/src/builtins/complex.rs +++ b/vm/src/builtins/complex.rs @@ -1,4 +1,4 @@ -use super::{PyStr, PyType, PyTypeRef, float}; +use super::{PyStr, PyTypeRef, float}; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, class::PyClassImpl, @@ -21,7 +21,7 @@ use std::num::Wrapping; /// Create a complex number from a real part and an optional imaginary part. /// /// This is equivalent to (real + imag*1j) where imag defaults to 0. -#[pyclass(module = false, name = "complex")] +#[pyclass(module = false, name = "complex", ctx = complex_type)] #[derive(Debug, Copy, Clone, PartialEq)] pub struct PyComplex { value: Complex64, @@ -33,12 +33,6 @@ impl PyComplex { } } -impl PyPayload for PyComplex { - fn class(ctx: &Context) -> &'static Py { - ctx.types.complex_type - } -} - impl ToPyObject for Complex64 { fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { PyComplex::new_ref(self, &vm.ctx).into() diff --git a/vm/src/builtins/coroutine.rs b/vm/src/builtins/coroutine.rs index cca2db3293..472daafa66 100644 --- a/vm/src/builtins/coroutine.rs +++ b/vm/src/builtins/coroutine.rs @@ -1,6 +1,6 @@ -use super::{PyCode, PyStrRef, PyType}; +use super::{PyCode, PyStrRef}; use crate::{ - AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObjectRef, PyRef, PyResult, VirtualMachine, class::PyClassImpl, coroutine::Coro, frame::FrameRef, @@ -9,19 +9,13 @@ use crate::{ types::{IterNext, Iterable, Representable, SelfIter, Unconstructible}, }; -#[pyclass(module = false, name = "coroutine")] +#[pyclass(module = false, name = "coroutine", ctx = coroutine_type)] #[derive(Debug)] // PyCoro_Type in CPython pub struct PyCoroutine { inner: Coro, } -impl PyPayload for PyCoroutine { - fn class(ctx: &Context) -> &'static Py { - ctx.types.coroutine_type - } -} - #[pyclass(with(Py, Unconstructible, IterNext, Representable))] impl PyCoroutine { pub fn as_coro(&self) -> &Coro { @@ -119,19 +113,13 @@ impl IterNext for PyCoroutine { } } -#[pyclass(module = false, name = "coroutine_wrapper")] +#[pyclass(module = false, name = "coroutine_wrapper", ctx = coroutine_wrapper_type)] #[derive(Debug)] // PyCoroWrapper_Type in CPython pub struct PyCoroutineWrapper { coro: PyRef, } -impl PyPayload for PyCoroutineWrapper { - fn class(ctx: &Context) -> &'static Py { - ctx.types.coroutine_wrapper_type - } -} - #[pyclass(with(IterNext, Iterable))] impl PyCoroutineWrapper { #[pymethod] diff --git a/vm/src/builtins/descriptor.rs b/vm/src/builtins/descriptor.rs index 9da4e1d87a..a660d21d5e 100644 --- a/vm/src/builtins/descriptor.rs +++ b/vm/src/builtins/descriptor.rs @@ -1,6 +1,6 @@ use super::{PyStr, PyStrInterned, PyType}; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyRef, PyResult, VirtualMachine, builtins::{PyTypeRef, builtin_func::PyNativeMethod, type_}, class::PyClassImpl, function::{FuncArgs, PyMethodDef, PyMethodFlags, PySetterValue}, @@ -22,7 +22,7 @@ pub struct PyDescriptorOwned { pub qualname: PyRwLock>, } -#[pyclass(name = "method_descriptor", module = false)] +#[pyclass(name = "method_descriptor", module = false, ctx = method_descriptor_type)] pub struct PyMethodDescriptor { pub common: PyDescriptor, pub method: &'static PyMethodDef, @@ -44,12 +44,6 @@ impl PyMethodDescriptor { } } -impl PyPayload for PyMethodDescriptor { - fn class(ctx: &Context) -> &'static Py { - ctx.types.method_descriptor_type - } -} - impl std::fmt::Debug for PyMethodDescriptor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "method descriptor for '{}'", self.common.name) @@ -217,19 +211,13 @@ impl std::fmt::Debug for PyMemberDef { } // PyMemberDescrObject in CPython -#[pyclass(name = "member_descriptor", module = false)] +#[pyclass(name = "member_descriptor", module = false, ctx = member_descriptor_type)] #[derive(Debug)] pub struct PyMemberDescriptor { pub common: PyDescriptorOwned, pub member: PyMemberDef, } -impl PyPayload for PyMemberDescriptor { - fn class(ctx: &Context) -> &'static Py { - ctx.types.member_descriptor_type - } -} - fn calculate_qualname(descr: &PyDescriptorOwned, vm: &VirtualMachine) -> PyResult> { if let Some(qualname) = vm.get_attribute_opt(descr.typ.clone().into(), "__qualname__")? { let str = qualname.downcast::().map_err(|_| { diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index f78543a5f5..67dea323e7 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -15,6 +15,7 @@ use crate::{ dict_inner::{self, DictKey}, function::{ArgIterable, KwArgs, OptionalArg, PyArithmeticValue::*, PyComparisonValue}, iter::PyExactSizeIterator, + object::SuperDefault, protocol::{PyIterIter, PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods}, recursion::ReprGuard, types::{ @@ -29,7 +30,7 @@ use std::sync::LazyLock; pub type DictContentType = dict_inner::Dict; -#[pyclass(module = false, name = "dict", unhashable = true, traverse)] +#[pyclass(module = false, name = "dict", unhashable = true, traverse, ctx = dict_type)] #[derive(Default)] pub struct PyDict { entries: DictContentType, @@ -43,12 +44,6 @@ impl fmt::Debug for PyDict { } } -impl PyPayload for PyDict { - fn class(ctx: &Context) -> &'static Py { - ctx.types.dict_type - } -} - impl PyDict { pub fn new_ref(ctx: &Context) -> PyRef { PyRef::new_ref(Self::default(), ctx.types.dict_type.to_owned(), None) @@ -728,7 +723,7 @@ impl ExactSizeIterator for DictIter<'_> { #[pyclass] trait DictView: PyPayload + PyClassDef + Iterable + Representable { - type ReverseIter: PyPayload; + type ReverseIter: PyPayload; fn dict(&self) -> &PyDictRef; fn item(vm: &VirtualMachine, key: PyObjectRef, value: PyObjectRef) -> PyObjectRef; @@ -747,7 +742,7 @@ macro_rules! dict_view { $class: ident, $iter_class: ident, $reverse_iter_class: ident, $class_name: literal, $iter_class_name: literal, $reverse_iter_class_name: literal, $result_fn: expr) => { - #[pyclass(module = false, name = $class_name)] + #[pyclass(module = false, name = $class_name, ctx = $class)] #[derive(Debug)] pub(crate) struct $name { pub dict: PyDictRef, @@ -779,12 +774,6 @@ macro_rules! dict_view { } } - impl PyPayload for $name { - fn class(ctx: &Context) -> &'static Py { - ctx.types.$class - } - } - impl Representable for $name { #[inline] fn repr(zelf: &Py, vm: &VirtualMachine) -> PyResult { @@ -808,19 +797,13 @@ macro_rules! dict_view { } } - #[pyclass(module = false, name = $iter_class_name)] + #[pyclass(module = false, name = $iter_class_name, ctx = $iter_class)] #[derive(Debug)] pub(crate) struct $iter_name { pub size: dict_inner::DictSize, pub internal: PyMutex>, } - impl PyPayload for $iter_name { - fn class(ctx: &Context) -> &'static Py { - ctx.types.$iter_class - } - } - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl $iter_name { fn new(dict: PyDictRef) -> Self { @@ -881,19 +864,13 @@ macro_rules! dict_view { } } - #[pyclass(module = false, name = $reverse_iter_class_name)] + #[pyclass(module = false, name = $reverse_iter_class_name, ctx = $reverse_iter_class)] #[derive(Debug)] pub(crate) struct $reverse_iter_name { pub size: dict_inner::DictSize, internal: PyMutex>, } - impl PyPayload for $reverse_iter_name { - fn class(ctx: &Context) -> &'static Py { - ctx.types.$reverse_iter_class - } - } - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl $reverse_iter_name { fn new(dict: PyDictRef) -> Self { diff --git a/vm/src/builtins/enumerate.rs b/vm/src/builtins/enumerate.rs index aa84115074..9061d8b41a 100644 --- a/vm/src/builtins/enumerate.rs +++ b/vm/src/builtins/enumerate.rs @@ -1,6 +1,4 @@ -use super::{ - IterStatus, PositionIterInternal, PyGenericAlias, PyIntRef, PyTupleRef, PyType, PyTypeRef, -}; +use super::{IterStatus, PositionIterInternal, PyGenericAlias, PyIntRef, PyTupleRef, PyTypeRef}; use crate::common::lock::{PyMutex, PyRwLock}; use crate::{ AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, @@ -13,7 +11,7 @@ use crate::{ use malachite_bigint::BigInt; use num_traits::Zero; -#[pyclass(module = false, name = "enumerate", traverse)] +#[pyclass(module = false, name = "enumerate", traverse, ctx = enumerate_type)] #[derive(Debug)] pub struct PyEnumerate { #[pytraverse(skip)] @@ -21,12 +19,6 @@ pub struct PyEnumerate { iterator: PyIter, } -impl PyPayload for PyEnumerate { - fn class(ctx: &Context) -> &'static Py { - ctx.types.enumerate_type - } -} - #[derive(FromArgs)] pub struct EnumerateArgs { iterator: PyIter, @@ -85,18 +77,12 @@ impl IterNext for PyEnumerate { } } -#[pyclass(module = false, name = "reversed", traverse)] +#[pyclass(module = false, name = "reversed", traverse, ctx = reverse_iter_type)] #[derive(Debug)] pub struct PyReverseSequenceIterator { internal: PyMutex>, } -impl PyPayload for PyReverseSequenceIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.reverse_iter_type - } -} - #[pyclass(with(IterNext, Iterable))] impl PyReverseSequenceIterator { pub fn new(obj: PyObjectRef, len: usize) -> Self { diff --git a/vm/src/builtins/filter.rs b/vm/src/builtins/filter.rs index 009a1b3eab..84be0d2daa 100644 --- a/vm/src/builtins/filter.rs +++ b/vm/src/builtins/filter.rs @@ -1,4 +1,4 @@ -use super::{PyType, PyTypeRef}; +use super::PyTypeRef; use crate::{ Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, class::PyClassImpl, @@ -6,19 +6,13 @@ use crate::{ types::{Constructor, IterNext, Iterable, SelfIter}, }; -#[pyclass(module = false, name = "filter", traverse)] +#[pyclass(module = false, name = "filter", traverse, ctx = filter_type)] #[derive(Debug)] pub struct PyFilter { predicate: PyObjectRef, iterator: PyIter, } -impl PyPayload for PyFilter { - fn class(ctx: &Context) -> &'static Py { - ctx.types.filter_type - } -} - impl Constructor for PyFilter { type Args = (PyObjectRef, PyIter); diff --git a/vm/src/builtins/float.rs b/vm/src/builtins/float.rs index 85f2a07bb9..05ecc47da5 100644 --- a/vm/src/builtins/float.rs +++ b/vm/src/builtins/float.rs @@ -20,7 +20,7 @@ use num_complex::Complex64; use num_traits::{Signed, ToPrimitive, Zero}; use rustpython_common::int::float_to_ratio; -#[pyclass(module = false, name = "float")] +#[pyclass(module = false, name = "float", ctx = float_type)] #[derive(Debug, Copy, Clone, PartialEq)] pub struct PyFloat { value: f64, @@ -32,12 +32,6 @@ impl PyFloat { } } -impl PyPayload for PyFloat { - fn class(ctx: &Context) -> &'static Py { - ctx.types.float_type - } -} - impl ToPyObject for f64 { fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { vm.ctx.new_float(self).into() diff --git a/vm/src/builtins/function.rs b/vm/src/builtins/function.rs index e054ac4348..321320f3b3 100644 --- a/vm/src/builtins/function.rs +++ b/vm/src/builtins/function.rs @@ -2,7 +2,7 @@ mod jitfunc; use super::{ - PyAsyncGen, PyCode, PyCoroutine, PyDictRef, PyGenerator, PyStr, PyStrRef, PyTupleRef, PyType, + PyAsyncGen, PyCode, PyCoroutine, PyDictRef, PyGenerator, PyStr, PyStrRef, PyTupleRef, PyTypeRef, tuple::PyTupleTyped, }; #[cfg(feature = "jit")] @@ -26,7 +26,7 @@ use itertools::Itertools; #[cfg(feature = "jit")] use rustpython_jit::CompiledCode; -#[pyclass(module = false, name = "function", traverse = "manual")] +#[pyclass(module = false, name = "function", traverse = "manual", ctx = function_type)] #[derive(Debug)] pub struct PyFunction { code: PyRef, @@ -355,12 +355,6 @@ impl PyFunction { } } -impl PyPayload for PyFunction { - fn class(ctx: &Context) -> &'static Py { - ctx.types.function_type - } -} - #[pyclass( with(GetDescriptor, Callable, Representable), flags(HAS_DICT, METHOD_DESCRIPTOR) @@ -550,7 +544,7 @@ impl Representable for PyFunction { } } -#[pyclass(module = false, name = "method", traverse)] +#[pyclass(module = false, name = "method", traverse, ctx = bound_method_type)] #[derive(Debug)] pub struct PyBoundMethod { object: PyObjectRef, @@ -690,12 +684,6 @@ impl PyBoundMethod { } } -impl PyPayload for PyBoundMethod { - fn class(ctx: &Context) -> &'static Py { - ctx.types.bound_method_type - } -} - impl Representable for PyBoundMethod { #[inline] fn repr_str(zelf: &Py, vm: &VirtualMachine) -> PyResult { @@ -715,19 +703,13 @@ impl Representable for PyBoundMethod { } } -#[pyclass(module = false, name = "cell", traverse)] +#[pyclass(module = false, name = "cell", traverse, ctx = cell_type)] #[derive(Debug, Default)] pub(crate) struct PyCell { contents: PyMutex>, } pub(crate) type PyCellRef = PyRef; -impl PyPayload for PyCell { - fn class(ctx: &Context) -> &'static Py { - ctx.types.cell_type - } -} - impl Constructor for PyCell { type Args = OptionalArg; diff --git a/vm/src/builtins/generator.rs b/vm/src/builtins/generator.rs index db9c263cb2..880483e565 100644 --- a/vm/src/builtins/generator.rs +++ b/vm/src/builtins/generator.rs @@ -2,9 +2,9 @@ * The mythical generator. */ -use super::{PyCode, PyStrRef, PyType}; +use super::{PyCode, PyStrRef}; use crate::{ - AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObjectRef, PyRef, PyResult, VirtualMachine, class::PyClassImpl, coroutine::Coro, frame::FrameRef, @@ -13,18 +13,12 @@ use crate::{ types::{IterNext, Iterable, Representable, SelfIter, Unconstructible}, }; -#[pyclass(module = false, name = "generator")] +#[pyclass(module = false, name = "generator", ctx = generator_type)] #[derive(Debug)] pub struct PyGenerator { inner: Coro, } -impl PyPayload for PyGenerator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.generator_type - } -} - #[pyclass(with(Py, Unconstructible, IterNext, Iterable))] impl PyGenerator { pub fn as_coro(&self) -> &Coro { diff --git a/vm/src/builtins/genericalias.rs b/vm/src/builtins/genericalias.rs index 18649718dd..59a759f39e 100644 --- a/vm/src/builtins/genericalias.rs +++ b/vm/src/builtins/genericalias.rs @@ -28,7 +28,7 @@ static ATTR_EXCEPTIONS: [&str; 8] = [ "__deepcopy__", ]; -#[pyclass(module = "types", name = "GenericAlias")] +#[pyclass(module = "types", name = "GenericAlias", ctx = generic_alias_type)] pub struct PyGenericAlias { origin: PyTypeRef, args: PyTupleRef, @@ -41,12 +41,6 @@ impl fmt::Debug for PyGenericAlias { } } -impl PyPayload for PyGenericAlias { - fn class(ctx: &Context) -> &'static Py { - ctx.types.generic_alias_type - } -} - impl Constructor for PyGenericAlias { type Args = FuncArgs; diff --git a/vm/src/builtins/getset.rs b/vm/src/builtins/getset.rs index c2e11b770a..941daedc9e 100644 --- a/vm/src/builtins/getset.rs +++ b/vm/src/builtins/getset.rs @@ -9,7 +9,7 @@ use crate::{ types::{GetDescriptor, Unconstructible}, }; -#[pyclass(module = false, name = "getset_descriptor")] +#[pyclass(module = false, name = "getset_descriptor", ctx = getset_type)] pub struct PyGetSet { name: String, class: &'static Py, @@ -38,12 +38,6 @@ impl std::fmt::Debug for PyGetSet { } } -impl PyPayload for PyGetSet { - fn class(ctx: &Context) -> &'static Py { - ctx.types.getset_type - } -} - impl GetDescriptor for PyGetSet { fn descr_get( zelf: PyObjectRef, diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 80aaae03eb..a33327e969 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -24,7 +24,7 @@ use num_traits::{One, Pow, PrimInt, Signed, ToPrimitive, Zero}; use std::fmt; use std::ops::{Neg, Not}; -#[pyclass(module = false, name = "int")] +#[pyclass(module = false, name = "int", manual_payload)] #[derive(Debug)] pub struct PyInt { value: BigInt, @@ -48,6 +48,7 @@ where } impl PyPayload for PyInt { + type Super = crate::builtins::PyBaseObject; fn class(ctx: &Context) -> &'static Py { ctx.types.int_type } diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index 0bd1994801..bb3e74188d 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -2,7 +2,7 @@ * iterator types */ -use super::{PyInt, PyTupleRef, PyType}; +use super::{PyInt, PyTupleRef}; use crate::{ Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine, class::PyClassImpl, @@ -174,7 +174,7 @@ pub fn builtins_reversed(vm: &VirtualMachine) -> &PyObject { INSTANCE.get_or_init(|| vm.builtins.get_attr("reversed", vm).unwrap()) } -#[pyclass(module = false, name = "iterator", traverse)] +#[pyclass(module = false, name = "iterator", traverse, ctx = iter_type)] #[derive(Debug)] pub struct PySequenceIterator { // cached sequence methods @@ -183,12 +183,6 @@ pub struct PySequenceIterator { internal: PyMutex>, } -impl PyPayload for PySequenceIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.iter_type - } -} - #[pyclass(with(IterNext, Iterable))] impl PySequenceIterator { pub fn new(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { @@ -239,19 +233,13 @@ impl IterNext for PySequenceIterator { } } -#[pyclass(module = false, name = "callable_iterator", traverse)] +#[pyclass(module = false, name = "callable_iterator", traverse, ctx = callable_iterator)] #[derive(Debug)] pub struct PyCallableIterator { sentinel: PyObjectRef, status: PyRwLock>, } -impl PyPayload for PyCallableIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.callable_iterator - } -} - #[pyclass(with(IterNext, Iterable))] impl PyCallableIterator { pub fn new(callable: ArgCallable, sentinel: PyObjectRef) -> Self { diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 4962ae51e3..7c6b7559fd 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -1,4 +1,4 @@ -use super::{PositionIterInternal, PyGenericAlias, PyTupleRef, PyType, PyTypeRef}; +use super::{PositionIterInternal, PyGenericAlias, PyTupleRef, PyTypeRef}; use crate::atomic_func; use crate::common::lock::{ PyMappedRwLockReadGuard, PyMutex, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard, @@ -22,7 +22,7 @@ use crate::{ }; use std::{fmt, ops::DerefMut}; -#[pyclass(module = false, name = "list", unhashable = true, traverse)] +#[pyclass(module = false, name = "list", unhashable = true, traverse, ctx = list_type)] #[derive(Default)] pub struct PyList { elements: PyRwLock>, @@ -49,12 +49,6 @@ impl FromIterator for PyList { } } -impl PyPayload for PyList { - fn class(ctx: &Context) -> &'static Py { - ctx.types.list_type - } -} - impl ToPyObject for Vec { fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { PyList::new_ref(self, &vm.ctx).into() @@ -527,18 +521,12 @@ fn do_sort( Ok(()) } -#[pyclass(module = false, name = "list_iterator", traverse)] +#[pyclass(module = false, name = "list_iterator", traverse, ctx = list_iterator_type)] #[derive(Debug)] pub struct PyListIterator { internal: PyMutex>, } -impl PyPayload for PyListIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.list_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyListIterator { #[pymethod(magic)] @@ -572,18 +560,12 @@ impl IterNext for PyListIterator { } } -#[pyclass(module = false, name = "list_reverseiterator", traverse)] +#[pyclass(module = false, name = "list_reverseiterator", traverse, ctx = list_reverseiterator_type)] #[derive(Debug)] pub struct PyListReverseIterator { internal: PyMutex>, } -impl PyPayload for PyListReverseIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.list_reverseiterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyListReverseIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/map.rs b/vm/src/builtins/map.rs index 555e38c8b9..a358e4a6a1 100644 --- a/vm/src/builtins/map.rs +++ b/vm/src/builtins/map.rs @@ -1,4 +1,4 @@ -use super::{PyType, PyTypeRef}; +use super::PyTypeRef; use crate::{ Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, builtins::PyTupleRef, @@ -8,19 +8,13 @@ use crate::{ types::{Constructor, IterNext, Iterable, SelfIter}, }; -#[pyclass(module = false, name = "map", traverse)] +#[pyclass(module = false, name = "map", traverse, ctx = map_type)] #[derive(Debug)] pub struct PyMap { mapper: PyObjectRef, iterators: Vec, } -impl PyPayload for PyMap { - fn class(ctx: &Context) -> &'static Py { - ctx.types.map_type - } -} - impl Constructor for PyMap { type Args = (PyObjectRef, PosArgs); diff --git a/vm/src/builtins/mappingproxy.rs b/vm/src/builtins/mappingproxy.rs index 5dd31500fb..f6716a419a 100644 --- a/vm/src/builtins/mappingproxy.rs +++ b/vm/src/builtins/mappingproxy.rs @@ -1,4 +1,4 @@ -use super::{PyDict, PyDictRef, PyGenericAlias, PyList, PyTuple, PyType, PyTypeRef}; +use super::{PyDict, PyDictRef, PyGenericAlias, PyList, PyTuple, PyTypeRef}; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, atomic_func, @@ -14,7 +14,7 @@ use crate::{ }; use std::sync::LazyLock; -#[pyclass(module = false, name = "mappingproxy", traverse)] +#[pyclass(module = false, name = "mappingproxy", traverse, ctx = mappingproxy_type)] #[derive(Debug)] pub struct PyMappingProxy { mapping: MappingProxyInner, @@ -35,12 +35,6 @@ unsafe impl Traverse for MappingProxyInner { } } -impl PyPayload for PyMappingProxy { - fn class(ctx: &Context) -> &'static Py { - ctx.types.mappingproxy_type - } -} - impl From for PyMappingProxy { fn from(dict: PyTypeRef) -> Self { Self { diff --git a/vm/src/builtins/memory.rs b/vm/src/builtins/memory.rs index 801d94fb36..46294f2ba3 100644 --- a/vm/src/builtins/memory.rs +++ b/vm/src/builtins/memory.rs @@ -1,6 +1,6 @@ use super::{ PositionIterInternal, PyBytes, PyBytesRef, PyInt, PyListRef, PySlice, PyStr, PyStrRef, PyTuple, - PyTupleRef, PyType, PyTypeRef, + PyTupleRef, PyTypeRef, }; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, @@ -37,7 +37,7 @@ pub struct PyMemoryViewNewArgs { object: PyObjectRef, } -#[pyclass(module = false, name = "memoryview")] +#[pyclass(module = false, name = "memoryview", ctx = memoryview_type)] #[derive(Debug)] pub struct PyMemoryView { // avoid double release when memoryview had released the buffer before drop @@ -1048,12 +1048,6 @@ impl Hashable for PyMemoryView { } } -impl PyPayload for PyMemoryView { - fn class(ctx: &Context) -> &'static Py { - ctx.types.memoryview_type - } -} - impl Representable for PyMemoryView { #[inline] fn repr_str(zelf: &Py, _vm: &VirtualMachine) -> PyResult { @@ -1122,18 +1116,12 @@ impl Iterable for PyMemoryView { } } -#[pyclass(module = false, name = "memory_iterator")] +#[pyclass(module = false, name = "memory_iterator", ctx = memoryviewiterator_type)] #[derive(Debug, Traverse)] pub struct PyMemoryViewIterator { internal: PyMutex>>, } -impl PyPayload for PyMemoryViewIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.memoryviewiterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyMemoryViewIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/module.rs b/vm/src/builtins/module.rs index 2cdc13a59c..9cadaab8b1 100644 --- a/vm/src/builtins/module.rs +++ b/vm/src/builtins/module.rs @@ -1,4 +1,4 @@ -use super::{PyDictRef, PyStr, PyStrRef, PyType, PyTypeRef}; +use super::{PyDictRef, PyStr, PyStrRef, PyTypeRef}; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, builtins::{PyStrInterned, pystr::AsPyStr}, @@ -8,7 +8,7 @@ use crate::{ types::{GetAttr, Initializer, Representable}, }; -#[pyclass(module = false, name = "module")] +// #[pyclass(module = false, name = "module")] #[derive(Debug)] pub struct PyModuleDef { // pub index: usize, @@ -42,7 +42,7 @@ impl std::fmt::Debug for PyModuleSlots { } #[allow(clippy::new_without_default)] // avoid Default implementation -#[pyclass(module = false, name = "module")] +#[pyclass(module = false, name = "module", ctx = module_type)] #[derive(Debug)] pub struct PyModule { // PyObject *md_dict; @@ -53,12 +53,6 @@ pub struct PyModule { pub name: Option<&'static PyStrInterned>, } -impl PyPayload for PyModule { - fn class(ctx: &Context) -> &'static Py { - ctx.types.module_type - } -} - #[derive(FromArgs)] pub struct ModuleInitArgs { name: PyStrRef, diff --git a/vm/src/builtins/namespace.rs b/vm/src/builtins/namespace.rs index 38146baa72..319cfb7ff3 100644 --- a/vm/src/builtins/namespace.rs +++ b/vm/src/builtins/namespace.rs @@ -1,6 +1,6 @@ -use super::{PyTupleRef, PyType, tuple::IntoPyTuple}; +use super::{PyTupleRef, tuple::IntoPyTuple}; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyRef, PyResult, VirtualMachine, builtins::PyDict, class::PyClassImpl, function::{FuncArgs, PyComparisonValue}, @@ -13,16 +13,10 @@ use crate::{ /// A simple attribute-based namespace. /// /// SimpleNamespace(**kwargs) -#[pyclass(module = "types", name = "SimpleNamespace")] +#[pyclass(module = "types", name = "SimpleNamespace", ctx = namespace_type)] #[derive(Debug, Default)] pub struct PyNamespace {} -impl PyPayload for PyNamespace { - fn class(ctx: &Context) -> &'static Py { - ctx.types.namespace_type - } -} - impl DefaultConstructor for PyNamespace {} impl PyNamespace { diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index be14327542..9f3d42053d 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -17,11 +17,12 @@ use itertools::Itertools; /// /// When called, it accepts no arguments and returns a new featureless /// instance that has no instance attributes and cannot be given any. -#[pyclass(module = false, name = "object")] -#[derive(Debug)] +#[pyclass(module = false, name = "object", manual_payload)] +#[derive(Debug, Default)] pub struct PyBaseObject; impl PyPayload for PyBaseObject { + type Super = crate::object::PyObjHeader; fn class(ctx: &Context) -> &'static Py { ctx.types.object_type } @@ -422,10 +423,14 @@ impl PyBaseObject { .flags .has_feature(PyTypeFlags::IMMUTABLETYPE) && !cls.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE); - // FIXME(#1979) cls instances might have a payload if both_mutable || both_module { - instance.set_class(cls, vm); - Ok(()) + instance.set_class(cls, vm).map_err(|cls| { + vm.new_type_error(format!( + "__class__ assignment: '{}' object layout differs from '{}'", + cls.name(), + instance.class().name(), + )) + }) } else { Err(vm.new_type_error( "__class__ assignment only supported for mutable types or ModuleType subclasses" diff --git a/vm/src/builtins/property.rs b/vm/src/builtins/property.rs index 5bfae5a081..192de297cd 100644 --- a/vm/src/builtins/property.rs +++ b/vm/src/builtins/property.rs @@ -1,17 +1,17 @@ /*! Python `property` descriptor class. */ -use super::{PyStrRef, PyType, PyTypeRef}; +use super::{PyStrRef, PyTypeRef}; use crate::common::lock::PyRwLock; use crate::function::{IntoFuncArgs, PosArgs}; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, class::PyClassImpl, function::{FuncArgs, PySetterValue}, types::{Constructor, GetDescriptor, Initializer}, }; -#[pyclass(module = false, name = "property", traverse)] +#[pyclass(module = false, name = "property", traverse, ctx = property_type)] #[derive(Debug)] pub struct PyProperty { getter: PyRwLock>, @@ -21,12 +21,6 @@ pub struct PyProperty { name: PyRwLock>, } -impl PyPayload for PyProperty { - fn class(ctx: &Context) -> &'static Py { - ctx.types.property_type - } -} - #[derive(FromArgs)] pub struct PropertyArgs { #[pyarg(any, default)] diff --git a/vm/src/builtins/range.rs b/vm/src/builtins/range.rs index 55f9b814d0..743fa2d972 100644 --- a/vm/src/builtins/range.rs +++ b/vm/src/builtins/range.rs @@ -1,6 +1,4 @@ -use super::{ - PyInt, PyIntRef, PySlice, PyTupleRef, PyType, PyTypeRef, builtins_iter, tuple::tuple_hash, -}; +use super::{PyInt, PyIntRef, PySlice, PyTupleRef, PyTypeRef, builtins_iter, tuple::tuple_hash}; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, atomic_func, @@ -59,7 +57,7 @@ fn iter_search( } } -#[pyclass(module = false, name = "range")] +#[pyclass(module = false, name = "range", ctx = range_type)] #[derive(Debug, Clone)] pub struct PyRange { pub start: PyIntRef, @@ -67,12 +65,6 @@ pub struct PyRange { pub step: PyIntRef, } -impl PyPayload for PyRange { - fn class(ctx: &Context) -> &'static Py { - ctx.types.range_type - } -} - impl PyRange { #[inline] fn offset(&self, value: &BigInt) -> Option { @@ -523,7 +515,7 @@ impl Representable for PyRange { // // This doesn't preclude the range from containing large values, since start and step // can be BigInts, we can store any arbitrary range of values. -#[pyclass(module = false, name = "longrange_iterator")] +#[pyclass(module = false, name = "longrange_iterator", ctx = long_range_iterator_type)] #[derive(Debug)] pub struct PyLongRangeIterator { index: AtomicCell, @@ -532,12 +524,6 @@ pub struct PyLongRangeIterator { length: BigInt, } -impl PyPayload for PyLongRangeIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.long_range_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyLongRangeIterator { #[pymethod(magic)] @@ -588,7 +574,7 @@ impl IterNext for PyLongRangeIterator { // When start, stop, step are isize, we can use a faster more compact representation // that only operates using isize to track values. -#[pyclass(module = false, name = "range_iterator")] +#[pyclass(module = false, name = "range_iterator", ctx = range_iterator_type)] #[derive(Debug)] pub struct PyRangeIterator { index: AtomicCell, @@ -597,12 +583,6 @@ pub struct PyRangeIterator { length: usize, } -impl PyPayload for PyRangeIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.range_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyRangeIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index 43e6ee1f7d..a2c34d7a8e 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -2,11 +2,11 @@ * Builtin set type with a sequence of unique items. */ use super::{ - IterStatus, PositionIterInternal, PyDict, PyDictRef, PyGenericAlias, PyTupleRef, PyType, - PyTypeRef, builtins_iter, + IterStatus, PositionIterInternal, PyDict, PyDictRef, PyGenericAlias, PyTupleRef, PyTypeRef, + builtins_iter, }; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, + AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, atomic_func, class::PyClassImpl, common::{ascii, hash::PyHash, lock::PyMutex, rc::PyRc}, @@ -32,7 +32,7 @@ use std::{fmt, ops::Deref}; pub type SetContentType = dict_inner::Dict<()>; -#[pyclass(module = false, name = "set", unhashable = true, traverse)] +#[pyclass(module = false, name = "set", unhashable = true, traverse, ctx = set_type)] #[derive(Default)] pub struct PySet { pub(super) inner: PySetInner, @@ -74,7 +74,7 @@ impl PySet { } } -#[pyclass(module = false, name = "frozenset", unhashable = true)] +#[pyclass(module = false, name = "frozenset", unhashable = true, ctx = frozenset_type)] pub struct PyFrozenSet { inner: PySetInner, hash: PyAtomic, @@ -152,18 +152,6 @@ impl fmt::Debug for PyFrozenSet { } } -impl PyPayload for PySet { - fn class(ctx: &Context) -> &'static Py { - ctx.types.set_type - } -} - -impl PyPayload for PyFrozenSet { - fn class(ctx: &Context) -> &'static Py { - ctx.types.frozenset_type - } -} - #[derive(Default, Clone)] pub(super) struct PySetInner { content: PyRc, @@ -1257,7 +1245,7 @@ impl TryFromObject for AnySet { } } -#[pyclass(module = false, name = "set_iterator")] +#[pyclass(module = false, name = "set_iterator", ctx = set_iterator_type)] pub(crate) struct PySetIterator { size: DictSize, internal: PyMutex>>, @@ -1270,12 +1258,6 @@ impl fmt::Debug for PySetIterator { } } -impl PyPayload for PySetIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.set_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PySetIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/singletons.rs b/vm/src/builtins/singletons.rs index da0c718c46..2ff5066d18 100644 --- a/vm/src/builtins/singletons.rs +++ b/vm/src/builtins/singletons.rs @@ -1,22 +1,16 @@ -use super::{PyStrRef, PyType, PyTypeRef}; +use super::{PyStrRef, PyTypeRef}; use crate::{ - Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, + Context, Py, PyObjectRef, PyResult, VirtualMachine, class::PyClassImpl, convert::ToPyObject, protocol::PyNumberMethods, types::{AsNumber, Constructor, Representable}, }; -#[pyclass(module = false, name = "NoneType")] +#[pyclass(module = false, name = "NoneType", ctx = none_type)] #[derive(Debug)] pub struct PyNone; -impl PyPayload for PyNone { - fn class(ctx: &Context) -> &'static Py { - ctx.types.none_type - } -} - // This allows a built-in function to not return a value, mapping to // Python's behavior of returning `None` in this situation. impl ToPyObject for () { @@ -72,16 +66,10 @@ impl AsNumber for PyNone { } } -#[pyclass(module = false, name = "NotImplementedType")] +#[pyclass(module = false, name = "NotImplementedType", ctx = not_implemented_type)] #[derive(Debug)] pub struct PyNotImplemented; -impl PyPayload for PyNotImplemented { - fn class(ctx: &Context) -> &'static Py { - ctx.types.not_implemented_type - } -} - impl Constructor for PyNotImplemented { type Args = (); diff --git a/vm/src/builtins/slice.rs b/vm/src/builtins/slice.rs index 4194360f4a..6df4b6b5a0 100644 --- a/vm/src/builtins/slice.rs +++ b/vm/src/builtins/slice.rs @@ -1,6 +1,6 @@ // sliceobject.{h,c} in CPython // spell-checker:ignore sliceobject -use super::{PyStrRef, PyTupleRef, PyType, PyTypeRef}; +use super::{PyStrRef, PyTupleRef, PyTypeRef}; use crate::{ AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, class::PyClassImpl, @@ -13,7 +13,7 @@ use crate::{ use malachite_bigint::{BigInt, ToBigInt}; use num_traits::{One, Signed, Zero}; -#[pyclass(module = false, name = "slice", unhashable = true, traverse)] +#[pyclass(module = false, name = "slice", unhashable = true, traverse, ctx =slice_type)] #[derive(Debug)] pub struct PySlice { pub start: Option, @@ -21,12 +21,6 @@ pub struct PySlice { pub step: Option, } -impl PyPayload for PySlice { - fn class(ctx: &Context) -> &'static Py { - ctx.types.slice_type - } -} - #[pyclass(with(Comparable, Representable, Hashable))] impl PySlice { #[pygetset] @@ -299,16 +293,10 @@ impl Representable for PySlice { } } -#[pyclass(module = false, name = "EllipsisType")] +#[pyclass(module = false, name = "EllipsisType", ctx = ellipsis_type)] #[derive(Debug)] pub struct PyEllipsis; -impl PyPayload for PyEllipsis { - fn class(ctx: &Context) -> &'static Py { - ctx.types.ellipsis_type - } -} - impl Constructor for PyEllipsis { type Args = (); diff --git a/vm/src/builtins/staticmethod.rs b/vm/src/builtins/staticmethod.rs index 6c19a42a33..f9c8e06c6b 100644 --- a/vm/src/builtins/staticmethod.rs +++ b/vm/src/builtins/staticmethod.rs @@ -1,4 +1,4 @@ -use super::{PyStr, PyType, PyTypeRef}; +use super::{PyStr, PyTypeRef}; use crate::{ Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, class::PyClassImpl, @@ -7,18 +7,12 @@ use crate::{ types::{Callable, Constructor, GetDescriptor, Initializer, Representable}, }; -#[pyclass(module = false, name = "staticmethod", traverse)] +#[pyclass(module = false, name = "staticmethod", traverse, ctx = staticmethod_type)] #[derive(Debug)] pub struct PyStaticMethod { pub callable: PyMutex, } -impl PyPayload for PyStaticMethod { - fn class(ctx: &Context) -> &'static Py { - ctx.types.staticmethod_type - } -} - impl GetDescriptor for PyStaticMethod { fn descr_get( zelf: PyObjectRef, diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index 90c702a14d..95517a45b9 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -1,5 +1,5 @@ use super::{ - PositionIterInternal, PyBytesRef, PyDict, PyTupleRef, PyType, PyTypeRef, + PositionIterInternal, PyBytesRef, PyDict, PyTupleRef, PyTypeRef, int::{PyInt, PyIntRef}, iter::IterStatus::{self, Exhausted}, }; @@ -64,7 +64,7 @@ impl<'a> TryFromBorrowedObject<'a> for &'a Wtf8 { } } -#[pyclass(module = false, name = "str")] +#[pyclass(module = false, name = "str", ctx = str_type)] pub struct PyStr { data: StrData, hash: PyAtomic, @@ -262,7 +262,7 @@ impl<'a> AsPyStr<'a> for &'a PyStrInterned { } } -#[pyclass(module = false, name = "str_iterator", traverse = "manual")] +#[pyclass(module = false, name = "str_iterator", traverse = "manual", ctx = str_iterator_type)] #[derive(Debug)] pub struct PyStrIterator { internal: PyMutex<(PositionIterInternal, usize)>, @@ -275,12 +275,6 @@ unsafe impl Traverse for PyStrIterator { } } -impl PyPayload for PyStrIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.str_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyStrIterator { #[pymethod(magic)] @@ -1588,12 +1582,6 @@ pub(crate) fn encode_string( vm.state.codec_registry.encode_text(s, encoding, errors, vm) } -impl PyPayload for PyStr { - fn class(ctx: &Context) -> &'static Py { - ctx.types.str_type - } -} - impl ToPyObject for String { fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { vm.ctx.new_str(self).into() diff --git a/vm/src/builtins/super.rs b/vm/src/builtins/super.rs index 442d162c78..6de52c96ce 100644 --- a/vm/src/builtins/super.rs +++ b/vm/src/builtins/super.rs @@ -12,7 +12,7 @@ use crate::{ types::{Callable, Constructor, GetAttr, GetDescriptor, Initializer, Representable}, }; -#[pyclass(module = false, name = "super", traverse)] +#[pyclass(module = false, name = "super", ctx = super_type, traverse)] #[derive(Debug)] pub struct PySuper { inner: PyRwLock, @@ -36,12 +36,6 @@ impl PySuperInner { } } -impl PyPayload for PySuper { - fn class(ctx: &Context) -> &'static Py { - ctx.types.super_type - } -} - impl Constructor for PySuper { type Args = FuncArgs; diff --git a/vm/src/builtins/traceback.rs b/vm/src/builtins/traceback.rs index 6d88821ae7..edd84626c0 100644 --- a/vm/src/builtins/traceback.rs +++ b/vm/src/builtins/traceback.rs @@ -1,11 +1,12 @@ use rustpython_common::lock::PyMutex; -use super::PyType; -use crate::{ - Context, Py, PyPayload, PyRef, class::PyClassImpl, frame::FrameRef, source::LineNumber, -}; +use crate::types::Constructor; +use crate::{Context, PyRef, class::PyClassImpl, frame::FrameRef, source::LineNumber}; +use crate::{PyPayload, PyResult, VirtualMachine}; -#[pyclass(module = false, name = "traceback", traverse)] +use super::PyTypeRef; + +#[pyclass(module = false, name = "traceback", traverse, ctx = traceback_type)] #[derive(Debug)] pub struct PyTraceback { pub next: PyMutex>, @@ -18,13 +19,26 @@ pub struct PyTraceback { pub type PyTracebackRef = PyRef; -impl PyPayload for PyTraceback { - fn class(ctx: &Context) -> &'static Py { - ctx.types.traceback_type +impl Constructor for PyTraceback { + type Args = (Option>, FrameRef, u32, usize); + + fn py_new( + cls: PyTypeRef, + (next, frame, lasti, lineno): Self::Args, + vm: &VirtualMachine, + ) -> PyResult { + Self::new( + next, + frame, + lasti, + LineNumber::new(lineno).unwrap_or(LineNumber::MIN), + ) + .into_ref_with_type(vm, cls) + .map(Into::into) } } -#[pyclass] +#[pyclass(with(Constructor))] impl PyTraceback { pub fn new(next: Option>, frame: FrameRef, lasti: u32, lineno: LineNumber) -> Self { PyTraceback { @@ -51,19 +65,19 @@ impl PyTraceback { } #[pygetset] - fn tb_next(&self) -> Option> { - self.next.lock().as_ref().cloned() + pub fn tb_next(&self) -> Option> { + self.next.lock().clone() } #[pygetset(setter)] - fn set_tb_next(&self, value: Option>) { + pub fn set_tb_next(&self, value: Option>) { *self.next.lock() = value; } } impl PyTracebackRef { pub fn iter(&self) -> impl Iterator { - std::iter::successors(Some(self.clone()), |tb| tb.next.lock().clone()) + std::iter::successors(Some(self.clone()), |tb| tb.tb_next()) } } diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index 1dc7861071..318f8a251e 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -1,4 +1,4 @@ -use super::{PositionIterInternal, PyGenericAlias, PyStrRef, PyType, PyTypeRef}; +use super::{PositionIterInternal, PyGenericAlias, PyStrRef, PyTypeRef}; use crate::common::{hash::PyHash, lock::PyMutex}; use crate::object::{Traverse, TraverseFn}; use crate::{ @@ -21,7 +21,7 @@ use crate::{ }; use std::{fmt, marker::PhantomData, sync::LazyLock}; -#[pyclass(module = false, name = "tuple", traverse)] +#[pyclass(module = false, name = "tuple", traverse, ctx = tuple_type)] pub struct PyTuple { elements: Box<[PyObjectRef]>, } @@ -33,12 +33,6 @@ impl fmt::Debug for PyTuple { } } -impl PyPayload for PyTuple { - fn class(ctx: &Context) -> &'static Py { - ctx.types.tuple_type - } -} - pub trait IntoPyTuple { fn into_pytuple(self, vm: &VirtualMachine) -> PyTupleRef; } @@ -450,18 +444,12 @@ impl Representable for PyTuple { } } -#[pyclass(module = false, name = "tuple_iterator", traverse)] +#[pyclass(module = false, name = "tuple_iterator", traverse, ctx = tuple_iterator_type)] #[derive(Debug)] pub(crate) struct PyTupleIterator { internal: PyMutex>, } -impl PyPayload for PyTupleIterator { - fn class(ctx: &Context) -> &'static Py { - ctx.types.tuple_iterator_type - } -} - #[pyclass(with(Unconstructible, IterNext, Iterable))] impl PyTupleIterator { #[pymethod(magic)] diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index a0c7ee58ff..229aa49d57 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -31,11 +31,14 @@ use crate::{ }; use indexmap::{IndexMap, map::Entry}; use itertools::Itertools; -use std::{borrow::Borrow, collections::HashSet, fmt, ops::Deref, pin::Pin, ptr::NonNull}; +use std::{ + any::TypeId, borrow::Borrow, collections::HashSet, fmt, ops::Deref, pin::Pin, ptr::NonNull, +}; -#[pyclass(module = false, name = "type", traverse = "manual")] +#[pyclass(module = false, name = "type", traverse = "manual", ctx = type_type)] pub struct PyType { pub base: Option, + pub(crate) type_id: TypeId, pub bases: PyRwLock>, pub mro: PyRwLock>, pub subclasses: PyRwLock>>, @@ -136,12 +139,6 @@ impl fmt::Debug for PyType { } } -impl PyPayload for PyType { - fn class(ctx: &Context) -> &'static Py { - ctx.types.type_type - } -} - impl PyType { pub fn new_simple_heap( name: &str, @@ -226,6 +223,7 @@ impl PyType { let new_type = PyRef::new_ref( PyType { + type_id: base.type_id, base: Some(base), bases: PyRwLock::new(bases), mro: PyRwLock::new(mro), @@ -253,8 +251,12 @@ impl PyType { Ok(new_type) } - pub fn new_static( + /// # Safety + /// + /// `type_id` must be accurate. + pub unsafe fn new_static( base: PyRef, + type_id: TypeId, attrs: PyAttributes, mut slots: PyTypeSlots, metaclass: PyRef, @@ -271,6 +273,7 @@ impl PyType { let new_type = PyRef::new_ref( PyType { + type_id, base: Some(base), bases, mro: PyRwLock::new(mro), diff --git a/vm/src/builtins/union.rs b/vm/src/builtins/union.rs index 83e2c86f08..eb2defed73 100644 --- a/vm/src/builtins/union.rs +++ b/vm/src/builtins/union.rs @@ -15,7 +15,7 @@ use std::sync::LazyLock; const CLS_ATTRS: &[&str] = &["__module__"]; -#[pyclass(module = "types", name = "UnionType", traverse)] +#[pyclass(module = "types", name = "UnionType", traverse, ctx = union_type)] pub struct PyUnion { args: PyTupleRef, parameters: PyTupleRef, @@ -27,12 +27,6 @@ impl fmt::Debug for PyUnion { } } -impl PyPayload for PyUnion { - fn class(ctx: &Context) -> &'static Py { - ctx.types.union_type - } -} - impl PyUnion { pub fn new(args: PyTupleRef, vm: &VirtualMachine) -> Self { let parameters = make_parameters(&args, vm); diff --git a/vm/src/builtins/weakproxy.rs b/vm/src/builtins/weakproxy.rs index 49e38d2d66..5c9768b0d7 100644 --- a/vm/src/builtins/weakproxy.rs +++ b/vm/src/builtins/weakproxy.rs @@ -1,4 +1,4 @@ -use super::{PyStr, PyStrRef, PyType, PyTypeRef, PyWeak}; +use super::{PyStr, PyStrRef, PyTypeRef, PyWeak}; use crate::{ Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, atomic_func, class::PyClassImpl, @@ -13,18 +13,12 @@ use crate::{ }; use std::sync::LazyLock; -#[pyclass(module = false, name = "weakproxy", unhashable = true, traverse)] +#[pyclass(module = false, name = "weakproxy", unhashable = true, traverse, ctx = weakproxy_type)] #[derive(Debug)] pub struct PyWeakProxy { weak: PyRef, } -impl PyPayload for PyWeakProxy { - fn class(ctx: &Context) -> &'static Py { - ctx.types.weakproxy_type - } -} - #[derive(FromArgs)] pub struct WeakProxyNewArgs { #[pyarg(positional)] diff --git a/vm/src/builtins/weakref.rs b/vm/src/builtins/weakref.rs index 9b2f248aa9..0cae72529e 100644 --- a/vm/src/builtins/weakref.rs +++ b/vm/src/builtins/weakref.rs @@ -1,10 +1,10 @@ -use super::{PyGenericAlias, PyType, PyTypeRef}; +use super::{PyGenericAlias, PyTypeRef}; use crate::common::{ atomic::{Ordering, Radium}, hash::{self, PyHash}, }; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyResult, VirtualMachine, class::PyClassImpl, function::OptionalArg, types::{Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable}, @@ -20,12 +20,6 @@ pub struct WeakNewArgs { callback: OptionalArg, } -impl PyPayload for PyWeak { - fn class(ctx: &Context) -> &'static Py { - ctx.types.weakref_type - } -} - impl Callable for PyWeak { type Args = (); #[inline] diff --git a/vm/src/builtins/zip.rs b/vm/src/builtins/zip.rs index abd82b3ccb..f5d4413795 100644 --- a/vm/src/builtins/zip.rs +++ b/vm/src/builtins/zip.rs @@ -1,4 +1,4 @@ -use super::{PyType, PyTypeRef}; +use super::PyTypeRef; use crate::{ AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, builtins::PyTupleRef, @@ -9,7 +9,7 @@ use crate::{ }; use rustpython_common::atomic::{self, PyAtomic, Radium}; -#[pyclass(module = false, name = "zip", traverse)] +#[pyclass(module = false, name = "zip", traverse, ctx = zip_type)] #[derive(Debug)] pub struct PyZip { iterators: Vec, @@ -17,12 +17,6 @@ pub struct PyZip { strict: PyAtomic, } -impl PyPayload for PyZip { - fn class(ctx: &Context) -> &'static Py { - ctx.types.zip_type - } -} - #[derive(FromArgs)] pub struct PyZipNewArgs { #[pyarg(named, optional)] diff --git a/vm/src/class.rs b/vm/src/class.rs index bc38d6bd61..c117bf3fec 100644 --- a/vm/src/class.rs +++ b/vm/src/class.rs @@ -1,5 +1,7 @@ //! Utilities to define a new Python class +use std::any::TypeId; + use crate::{ builtins::{PyBaseObject, PyType, PyTypeRef}, function::PyMethodDef, @@ -10,9 +12,15 @@ use crate::{ }; use rustpython_common::static_cell; -pub trait StaticType { +/// A type that represents a statically-allocated Python class. +/// +/// # Safety +/// +/// `type_id` must be accurate. +pub unsafe trait StaticType { // Ideally, saving PyType is better than PyTypeRef fn static_cell() -> &'static static_cell::StaticCell; + fn type_id() -> Option; fn static_metaclass() -> &'static Py { PyType::static_type() } @@ -44,13 +52,19 @@ pub trait StaticType { where Self: PyClassImpl, { - PyType::new_static( - Self::static_baseclass().to_owned(), - Default::default(), - Self::make_slots(), - Self::static_metaclass().to_owned(), - ) - .unwrap() + let base = Self::static_baseclass(); + let type_id = Self::type_id().unwrap_or(base.type_id); + // SAFETY: TypeId is accurate + unsafe { + PyType::new_static( + base.to_owned(), + type_id, + Default::default(), + Self::make_slots(), + Self::static_metaclass().to_owned(), + ) + .unwrap() + } } } diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 708a93fe61..b5d3687c8a 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -37,12 +37,6 @@ impl std::fmt::Debug for PyBaseException { } } -impl PyPayload for PyBaseException { - fn class(ctx: &Context) -> &'static Py { - ctx.exceptions.base_exception_type - } -} - impl VirtualMachine { // Why `impl VirtualMachine`? // These functions are natively free function in CPython - not methods of PyException @@ -1190,31 +1184,31 @@ pub(super) mod types { pub(super) args: PyRwLock, } - #[pyexception(name, base = "PyBaseException", ctx = "system_exit", impl)] + #[pyexception(name, base = PyBaseException, ctx = system_exit, impl)] #[derive(Debug)] pub struct PySystemExit {} - #[pyexception(name, base = "PyBaseException", ctx = "base_exception_group", impl)] + #[pyexception(name, base = PyBaseException, ctx = base_exception_group, impl)] #[derive(Debug)] pub struct PyBaseExceptionGroup {} - #[pyexception(name, base = "PyBaseExceptionGroup", ctx = "exception_group", impl)] + #[pyexception(name, base = PyBaseExceptionGroup, ctx = exception_group, impl)] #[derive(Debug)] pub struct PyExceptionGroup {} - #[pyexception(name, base = "PyBaseException", ctx = "generator_exit", impl)] + #[pyexception(name, base = PyBaseException, ctx = generator_exit, impl)] #[derive(Debug)] pub struct PyGeneratorExit {} - #[pyexception(name, base = "PyBaseException", ctx = "keyboard_interrupt", impl)] + #[pyexception(name, base = PyBaseException, ctx = keyboard_interrupt, impl)] #[derive(Debug)] pub struct PyKeyboardInterrupt {} - #[pyexception(name, base = "PyBaseException", ctx = "exception_type", impl)] + #[pyexception(name, base = PyBaseException, ctx = exception_type, impl)] #[derive(Debug)] pub struct PyException {} - #[pyexception(name, base = "PyException", ctx = "stop_iteration")] + #[pyexception(name, base = PyException, ctx = stop_iteration)] #[derive(Debug)] pub struct PyStopIteration {} @@ -1232,43 +1226,43 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyException", ctx = "stop_async_iteration", impl)] + #[pyexception(name, base = PyException, ctx = stop_async_iteration, impl)] #[derive(Debug)] pub struct PyStopAsyncIteration {} - #[pyexception(name, base = "PyException", ctx = "arithmetic_error", impl)] + #[pyexception(name, base = PyException, ctx = arithmetic_error, impl)] #[derive(Debug)] pub struct PyArithmeticError {} - #[pyexception(name, base = "PyArithmeticError", ctx = "floating_point_error", impl)] + #[pyexception(name, base = PyArithmeticError, ctx = floating_point_error, impl)] #[derive(Debug)] pub struct PyFloatingPointError {} - #[pyexception(name, base = "PyArithmeticError", ctx = "overflow_error", impl)] + #[pyexception(name, base = PyArithmeticError, ctx = overflow_error, impl)] #[derive(Debug)] pub struct PyOverflowError {} - #[pyexception(name, base = "PyArithmeticError", ctx = "zero_division_error", impl)] + #[pyexception(name, base = PyArithmeticError, ctx = zero_division_error, impl)] #[derive(Debug)] pub struct PyZeroDivisionError {} - #[pyexception(name, base = "PyException", ctx = "assertion_error", impl)] + #[pyexception(name, base = PyException, ctx = assertion_error, impl)] #[derive(Debug)] pub struct PyAssertionError {} - #[pyexception(name, base = "PyException", ctx = "attribute_error", impl)] + #[pyexception(name, base = PyException, ctx = attribute_error, impl)] #[derive(Debug)] pub struct PyAttributeError {} - #[pyexception(name, base = "PyException", ctx = "buffer_error", impl)] + #[pyexception(name, base = PyException, ctx = buffer_error, impl)] #[derive(Debug)] pub struct PyBufferError {} - #[pyexception(name, base = "PyException", ctx = "eof_error", impl)] + #[pyexception(name, base = PyException, ctx = eof_error, impl)] #[derive(Debug)] pub struct PyEOFError {} - #[pyexception(name, base = "PyException", ctx = "import_error")] + #[pyexception(name, base = PyException, ctx = import_error)] #[derive(Debug)] pub struct PyImportError {} @@ -1309,19 +1303,19 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyImportError", ctx = "module_not_found_error", impl)] + #[pyexception(name, base = PyImportError, ctx = module_not_found_error, impl)] #[derive(Debug)] pub struct PyModuleNotFoundError {} - #[pyexception(name, base = "PyException", ctx = "lookup_error", impl)] + #[pyexception(name, base = PyException, ctx = lookup_error, impl)] #[derive(Debug)] pub struct PyLookupError {} - #[pyexception(name, base = "PyLookupError", ctx = "index_error", impl)] + #[pyexception(name, base = PyLookupError, ctx = index_error, impl)] #[derive(Debug)] pub struct PyIndexError {} - #[pyexception(name, base = "PyLookupError", ctx = "key_error")] + #[pyexception(name, base = PyLookupError, ctx = key_error)] #[derive(Debug)] pub struct PyKeyError {} @@ -1341,19 +1335,19 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyException", ctx = "memory_error", impl)] + #[pyexception(name, base = PyException, ctx = memory_error, impl)] #[derive(Debug)] pub struct PyMemoryError {} - #[pyexception(name, base = "PyException", ctx = "name_error", impl)] + #[pyexception(name, base = PyException, ctx = name_error, impl)] #[derive(Debug)] pub struct PyNameError {} - #[pyexception(name, base = "PyNameError", ctx = "unbound_local_error", impl)] + #[pyexception(name, base = PyNameError, ctx = unbound_local_error, impl)] #[derive(Debug)] pub struct PyUnboundLocalError {} - #[pyexception(name, base = "PyException", ctx = "os_error")] + #[pyexception(name, base = PyException, ctx = os_error)] #[derive(Debug)] pub struct PyOSError {} @@ -1483,26 +1477,26 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyOSError", ctx = "blocking_io_error", impl)] + #[pyexception(name, base = PyOSError, ctx = blocking_io_error, impl)] #[derive(Debug)] pub struct PyBlockingIOError {} - #[pyexception(name, base = "PyOSError", ctx = "child_process_error", impl)] + #[pyexception(name, base = PyOSError, ctx = child_process_error, impl)] #[derive(Debug)] pub struct PyChildProcessError {} - #[pyexception(name, base = "PyOSError", ctx = "connection_error", impl)] + #[pyexception(name, base = PyOSError, ctx = connection_error, impl)] #[derive(Debug)] pub struct PyConnectionError {} - #[pyexception(name, base = "PyConnectionError", ctx = "broken_pipe_error", impl)] + #[pyexception(name, base = PyConnectionError, ctx = broken_pipe_error, impl)] #[derive(Debug)] pub struct PyBrokenPipeError {} #[pyexception( name, - base = "PyConnectionError", - ctx = "connection_aborted_error", + base = PyConnectionError, + ctx = connection_aborted_error, impl )] #[derive(Debug)] @@ -1510,66 +1504,66 @@ pub(super) mod types { #[pyexception( name, - base = "PyConnectionError", - ctx = "connection_refused_error", + base = PyConnectionError, + ctx = connection_refused_error, impl )] #[derive(Debug)] pub struct PyConnectionRefusedError {} - #[pyexception(name, base = "PyConnectionError", ctx = "connection_reset_error", impl)] + #[pyexception(name, base = PyConnectionError, ctx = connection_reset_error, impl)] #[derive(Debug)] pub struct PyConnectionResetError {} - #[pyexception(name, base = "PyOSError", ctx = "file_exists_error", impl)] + #[pyexception(name, base = PyOSError, ctx = file_exists_error, impl)] #[derive(Debug)] pub struct PyFileExistsError {} - #[pyexception(name, base = "PyOSError", ctx = "file_not_found_error", impl)] + #[pyexception(name, base = PyOSError, ctx = file_not_found_error, impl)] #[derive(Debug)] pub struct PyFileNotFoundError {} - #[pyexception(name, base = "PyOSError", ctx = "interrupted_error", impl)] + #[pyexception(name, base = PyOSError, ctx = interrupted_error, impl)] #[derive(Debug)] pub struct PyInterruptedError {} - #[pyexception(name, base = "PyOSError", ctx = "is_a_directory_error", impl)] + #[pyexception(name, base = PyOSError, ctx = is_a_directory_error, impl)] #[derive(Debug)] pub struct PyIsADirectoryError {} - #[pyexception(name, base = "PyOSError", ctx = "not_a_directory_error", impl)] + #[pyexception(name, base = PyOSError, ctx = not_a_directory_error, impl)] #[derive(Debug)] pub struct PyNotADirectoryError {} - #[pyexception(name, base = "PyOSError", ctx = "permission_error", impl)] + #[pyexception(name, base = PyOSError, ctx = permission_error, impl)] #[derive(Debug)] pub struct PyPermissionError {} - #[pyexception(name, base = "PyOSError", ctx = "process_lookup_error", impl)] + #[pyexception(name, base = PyOSError, ctx = process_lookup_error, impl)] #[derive(Debug)] pub struct PyProcessLookupError {} - #[pyexception(name, base = "PyOSError", ctx = "timeout_error", impl)] + #[pyexception(name, base = PyOSError, ctx = timeout_error, impl)] #[derive(Debug)] pub struct PyTimeoutError {} - #[pyexception(name, base = "PyException", ctx = "reference_error", impl)] + #[pyexception(name, base = PyException, ctx = reference_error, impl)] #[derive(Debug)] pub struct PyReferenceError {} - #[pyexception(name, base = "PyException", ctx = "runtime_error", impl)] + #[pyexception(name, base = PyException, ctx = runtime_error, impl)] #[derive(Debug)] pub struct PyRuntimeError {} - #[pyexception(name, base = "PyRuntimeError", ctx = "not_implemented_error", impl)] + #[pyexception(name, base = PyRuntimeError, ctx = not_implemented_error, impl)] #[derive(Debug)] pub struct PyNotImplementedError {} - #[pyexception(name, base = "PyRuntimeError", ctx = "recursion_error", impl)] + #[pyexception(name, base = PyRuntimeError, ctx = recursion_error, impl)] #[derive(Debug)] pub struct PyRecursionError {} - #[pyexception(name, base = "PyException", ctx = "syntax_error")] + #[pyexception(name, base = PyException, ctx = syntax_error)] #[derive(Debug)] pub struct PySyntaxError {} @@ -1623,31 +1617,31 @@ pub(super) mod types { } } - #[pyexception(name, base = "PySyntaxError", ctx = "indentation_error", impl)] + #[pyexception(name, base = PySyntaxError, ctx = indentation_error, impl)] #[derive(Debug)] pub struct PyIndentationError {} - #[pyexception(name, base = "PyIndentationError", ctx = "tab_error", impl)] + #[pyexception(name, base = PyIndentationError, ctx = tab_error, impl)] #[derive(Debug)] pub struct PyTabError {} - #[pyexception(name, base = "PyException", ctx = "system_error", impl)] + #[pyexception(name, base = PyException, ctx = system_error, impl)] #[derive(Debug)] pub struct PySystemError {} - #[pyexception(name, base = "PyException", ctx = "type_error", impl)] + #[pyexception(name, base = PyException, ctx = type_error, impl)] #[derive(Debug)] pub struct PyTypeError {} - #[pyexception(name, base = "PyException", ctx = "value_error", impl)] + #[pyexception(name, base = PyException, ctx = value_error, impl)] #[derive(Debug)] pub struct PyValueError {} - #[pyexception(name, base = "PyValueError", ctx = "unicode_error", impl)] + #[pyexception(name, base = PyValueError, ctx = unicode_error, impl)] #[derive(Debug)] pub struct PyUnicodeError {} - #[pyexception(name, base = "PyUnicodeError", ctx = "unicode_decode_error")] + #[pyexception(name, base = PyUnicodeError, ctx = unicode_decode_error)] #[derive(Debug)] pub struct PyUnicodeDecodeError {} @@ -1697,7 +1691,7 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyUnicodeError", ctx = "unicode_encode_error")] + #[pyexception(name, base = PyUnicodeError, ctx = unicode_encode_error)] #[derive(Debug)] pub struct PyUnicodeEncodeError {} @@ -1748,7 +1742,7 @@ pub(super) mod types { } } - #[pyexception(name, base = "PyUnicodeError", ctx = "unicode_translate_error")] + #[pyexception(name, base = PyUnicodeError, ctx = unicode_translate_error)] #[derive(Debug)] pub struct PyUnicodeTranslateError {} @@ -1796,56 +1790,56 @@ pub(super) mod types { /// JIT error. #[cfg(feature = "jit")] - #[pyexception(name, base = "PyException", ctx = "jit_error", impl)] + #[pyexception(name, base = PyException, ctx = jit_error, impl)] #[derive(Debug)] pub struct PyJitError {} // Warnings - #[pyexception(name, base = "PyException", ctx = "warning", impl)] + #[pyexception(name, base = PyException, ctx = warning, impl)] #[derive(Debug)] pub struct PyWarning {} - #[pyexception(name, base = "PyWarning", ctx = "deprecation_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = deprecation_warning, impl)] #[derive(Debug)] pub struct PyDeprecationWarning {} - #[pyexception(name, base = "PyWarning", ctx = "pending_deprecation_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = pending_deprecation_warning, impl)] #[derive(Debug)] pub struct PyPendingDeprecationWarning {} - #[pyexception(name, base = "PyWarning", ctx = "runtime_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = runtime_warning, impl)] #[derive(Debug)] pub struct PyRuntimeWarning {} - #[pyexception(name, base = "PyWarning", ctx = "syntax_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = syntax_warning, impl)] #[derive(Debug)] pub struct PySyntaxWarning {} - #[pyexception(name, base = "PyWarning", ctx = "user_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = user_warning, impl)] #[derive(Debug)] pub struct PyUserWarning {} - #[pyexception(name, base = "PyWarning", ctx = "future_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = future_warning, impl)] #[derive(Debug)] pub struct PyFutureWarning {} - #[pyexception(name, base = "PyWarning", ctx = "import_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = import_warning, impl)] #[derive(Debug)] pub struct PyImportWarning {} - #[pyexception(name, base = "PyWarning", ctx = "unicode_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = unicode_warning, impl)] #[derive(Debug)] pub struct PyUnicodeWarning {} - #[pyexception(name, base = "PyWarning", ctx = "bytes_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = bytes_warning, impl)] #[derive(Debug)] pub struct PyBytesWarning {} - #[pyexception(name, base = "PyWarning", ctx = "resource_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = resource_warning, impl)] #[derive(Debug)] pub struct PyResourceWarning {} - #[pyexception(name, base = "PyWarning", ctx = "encoding_warning", impl)] + #[pyexception(name, base = PyWarning, ctx = encoding_warning, impl)] #[derive(Debug)] pub struct PyEncodingWarning {} } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 7976a5254f..25507ca258 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -3,7 +3,7 @@ use crate::{ AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, builtins::{ PyBaseExceptionRef, PyCode, PyCoroutine, PyDict, PyDictRef, PyGenerator, PyList, PySet, - PySlice, PyStr, PyStrInterned, PyStrRef, PyTraceback, PyType, + PySlice, PyStr, PyStrInterned, PyStrRef, PyTraceback, asyncgenerator::PyAsyncGenWrappedValue, function::{PyCell, PyCellRef, PyFunction}, tuple::{PyTuple, PyTupleRef, PyTupleTyped}, @@ -17,7 +17,7 @@ use crate::{ scope::Scope, source::SourceLocation, stdlib::{builtins, typing::_typing}, - vm::{Context, PyMethod}, + vm::PyMethod, }; use indexmap::IndexMap; use itertools::Itertools; @@ -93,7 +93,7 @@ type Lasti = atomic::AtomicU32; #[cfg(not(feature = "threading"))] type Lasti = std::cell::Cell; -#[pyclass(module = false, name = "frame")] +#[pyclass(module = false, name = "frame", ctx = frame_type)] pub struct Frame { pub code: PyRef, @@ -116,12 +116,6 @@ pub struct Frame { pub temporary_refs: PyMutex>, } -impl PyPayload for Frame { - fn class(ctx: &Context) -> &'static Py { - ctx.types.frame_type - } -} - // Running a frame can result in one of the below: pub enum ExecutionResult { Return(PyObjectRef), diff --git a/vm/src/function/method.rs b/vm/src/function/method.rs index d3d0b85fae..63309e4eb2 100644 --- a/vm/src/function/method.rs +++ b/vm/src/function/method.rs @@ -1,11 +1,12 @@ use crate::{ - Context, Py, PyObjectRef, PyPayload, PyRef, VirtualMachine, + Context, Py, PyObjectRef, PyRef, VirtualMachine, builtins::{ PyType, builtin_func::{PyNativeFunction, PyNativeMethod}, descriptor::PyMethodDescriptor, }, function::{IntoPyNativeFn, PyNativeFn}, + object::PyObjectBuilder, }; bitflags::bitflags! { @@ -131,20 +132,6 @@ impl PyMethodDef { ) -> PyMethodDescriptor { PyMethodDescriptor::new(self, class, ctx) } - pub fn to_bound_method( - &'static self, - obj: PyObjectRef, - class: &'static Py, - ) -> PyNativeMethod { - PyNativeMethod { - func: PyNativeFunction { - zelf: Some(obj), - value: self, - module: None, - }, - class, - } - } pub fn build_function(&'static self, ctx: &Context) -> PyRef { self.to_function().into_ref(ctx) } @@ -179,11 +166,13 @@ impl PyMethodDef { obj: PyObjectRef, class: &'static Py, ) -> PyRef { - PyRef::new_ref( - self.to_bound_method(obj, class), - ctx.types.builtin_method_type.to_owned(), - None, - ) + PyObjectBuilder::new(PyNativeFunction { + zelf: Some(obj), + value: self, + module: None, + }) + .subclass(PyNativeMethod { class }) + .build(ctx) } pub fn build_classmethod( &'static self, @@ -203,7 +192,9 @@ impl PyMethodDef { ) -> PyRef { debug_assert!(self.flags.contains(PyMethodFlags::STATIC)); let func = self.to_function(); - PyNativeMethod { func, class }.into_ref(ctx) + PyObjectBuilder::new(func) + .subclass(PyNativeMethod { class }) + .build(ctx) } #[doc(hidden)] @@ -260,7 +251,7 @@ impl std::fmt::Debug for PyMethodDef { // This is not a part of CPython API. // But useful to support dynamically generated methods -#[pyclass(name, module = false, ctx = "method_def")] +#[pyclass(name, module = false, ctx = method_def)] #[derive(Debug)] pub struct HeapMethodDef { method: PyMethodDef, diff --git a/vm/src/import.rs b/vm/src/import.rs index 90aadbdbf2..222f53aa1e 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -176,7 +176,7 @@ fn remove_importlib_frames_inner( let file_name = traceback.frame.code.source_path.as_str(); let (inner_tb, mut now_in_importlib) = - remove_importlib_frames_inner(vm, traceback.next.lock().clone(), always_trim); + remove_importlib_frames_inner(vm, traceback.tb_next(), always_trim); if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external" { if traceback.frame.code.obj_name.as_str() == "_call_with_frames_removed" { now_in_importlib = true; diff --git a/vm/src/object/core.rs b/vm/src/object/core.rs index 8edcb4dfd6..f148d56461 100644 --- a/vm/src/object/core.rs +++ b/vm/src/object/core.rs @@ -11,12 +11,15 @@ //! [`PyRef`] may looking like to be called as PyObjectWeak by the rule, //! but not to do to remember it is a PyRef object. use super::{ - PyAtomicRef, + PyAtomicRef, PyDefault, SuperDefault, SuperPyDefault, ext::{AsObject, PyRefExact, PyResult}, - payload::PyObjectPayload, + payload::PyPayload, +}; +use crate::{ + Context, + builtins::{PyBaseExceptionRef, PyBaseObject}, + object::traverse::{Traverse, TraverseFn}, }; -use crate::object::traverse::{Traverse, TraverseFn}; -use crate::object::traverse_object::PyObjVTable; use crate::{ builtins::{PyDictRef, PyType, PyTypeRef}, common::{ @@ -27,6 +30,7 @@ use crate::{ }, vm::VirtualMachine, }; +use crate::{object::traverse_object::PyObjVTable, types::PyTypeFlags}; use itertools::Itertools; use std::{ any::TypeId, @@ -39,7 +43,7 @@ use std::{ ptr::{self, NonNull}, }; -// so, PyObjectRef is basically equivalent to `PyRc>`, except it's +// so, PyObjectRef is basically equivalent to `PyRc>`, except it's // only one pointer in width rather than 2. We do that by manually creating a vtable, and putting // a &'static reference to it inside the `PyRc` rather than adjacent to it, like trait objects do. // This can lead to faster code since there's just less data to pass around, as well as because of @@ -54,16 +58,16 @@ use std::{ // | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | // +-------------+-------------+---------------------------+ // There has to be padding in the space between the 2 fields. But, if that field is a trait object -// (like `dyn PyObjectPayload`) we don't *know* how much padding there is between the `payload` +// (like `dyn PyPayload`) we don't *know* how much padding there is between the `payload` // field and the previous field. So, Rust has to consult the vtable to know the exact offset of -// `payload` in `PyInner`, which has a huge performance impact when *every +// `payload` in `PyInner`, which has a huge performance impact when *every // single payload access* requires a vtable lookup. Thankfully, we're able to avoid that because of // the way we use PyObjectRef, in that whenever we want to access the payload we (almost) always // access it from a generic function. So, rather than doing // // - check vtable for payload offset // - get offset in PyInner struct -// - call as_any() method of PyObjectPayload +// - call as_any() method of PyPayload // - call downcast_ref() method of Any // we can just do // - check vtable that typeid matches @@ -72,60 +76,188 @@ use std::{ // and at that point the compiler can know the offset of `payload` for us because **we've given it a // concrete type to work with before we ever access the `payload` field** -/// A type to just represent "we've erased the type of this object, cast it before you use it" -#[derive(Debug)] -pub(super) struct Erased; - -pub(super) unsafe fn drop_dealloc_obj(x: *mut PyObject) { - drop(unsafe { Box::from_raw(x as *mut PyInner) }); +pub(super) unsafe fn drop_dealloc_obj(x: *mut PyObject) { + drop(unsafe { Box::from_raw(x as *mut PyObjRepr) }); } -pub(super) unsafe fn debug_obj( +pub(super) unsafe fn debug_obj( x: &PyObject, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - let x = unsafe { &*(x as *const PyObject as *const PyInner) }; + let x = unsafe { &*(x as *const PyObject as *const PyObjRepr) }; fmt::Debug::fmt(x, f) } /// Call `try_trace` on payload -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) +pub(super) unsafe fn try_trace_obj(x: &PyObject, tracer_fn: &mut TraverseFn<'_>) { + let x = unsafe { &*(x as *const PyObject as *const PyObjRepr) }; + x.repr_try_traverse(tracer_fn) } -/// 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. +/// The header of a python object. +/// +/// Not public API; only `pub` because it's specified as +/// `::Super` but it shouldn't be reexported from +/// `crate::object`. +#[doc(hidden)] +pub struct PyObjHeader { + ref_count: RefCount, + vtable: &'static PyObjVTable, + + typ: PyAtomicRef, // __class__ member + dict: Option, + weak_list: WeakRefList, + slots: Box<[PyRwLock>]>, +} + +fn traverse_object_head(header: &PyObjHeader, tracer_fn: &mut TraverseFn<'_>) { + // 1. trace `dict` and `slots` field(`typ` can't trace for it's a AtomicRef while is leaked by design) + // 2. call vtable's trace function to trace payload + // self.typ.trace(tracer_fn); + header.dict.traverse(tracer_fn); + // weak_list keeps a *pointer* to a struct for maintaince weak ref, so no ownership, no trace + header.slots.traverse(tracer_fn); +} + +/// The layout of an object and its superclass. +/// +/// Is marked public, but is not public API. #[repr(C)] -pub(super) struct PyInner { - pub(super) ref_count: RefCount, - // TODO: move typeid into vtable once TypeId::of is const - pub(super) typeid: TypeId, - pub(super) vtable: &'static PyObjVTable, +pub struct PyObjRepr { + sup: ::Repr, + payload: T, +} + +impl Deref for PyObjRepr { + type Target = T; + #[inline] + fn deref(&self) -> &Self::Target { + &self.payload + } +} + +impl From for PyObjRepr +where + ::Repr: From, +{ + fn from(header: PyObjHeader) -> Self { + Self { + sup: header.into(), + payload: T::default(), + } + } +} + +impl> SuperPyDefault for T { + fn py_from_header(header: PyObjHeader, ctx: &Context) -> Self::Repr { + PyObjRepr { + sup: T::Super::py_from_header(header, ctx), + payload: T::py_default(ctx), + } + } +} + +impl SuperPyDefault for PyObjHeader { + fn py_from_header(header: PyObjHeader, _ctx: &Context) -> Self::Repr { + header + } +} + +impl> SuperDefault for T { + fn from_header(header: PyObjHeader) -> Self::Repr { + PyObjRepr { + sup: T::Super::from_header(header), + payload: T::default(), + } + } +} + +impl SuperDefault for PyObjHeader { + fn from_header(header: PyObjHeader) -> Self::Repr { + header + } +} - pub(super) typ: PyAtomicRef, // __class__ member - pub(super) dict: Option, - pub(super) weak_list: WeakRefList, - pub(super) slots: Box<[PyRwLock>]>, +impl PyObjRepr { + fn header(&self) -> &PyObjHeader { + self.sup.as_header() + } +} + +/// A type that can be the supertype of a `PyPayload`. +/// +/// This trait is a bit weird, as `PyPayload::Super` implies that every type +/// has a supertype, but obviously `object` does not. So, `PyBaseObject::Super` +/// is `ObjectHead`, which implements this trait but *not* `PyPayload`, and +/// thus stops that infinite chain. +#[doc(hidden)] +pub trait SuperPayload { + /// The actual in-memory layout of this type. `PyObjRepr` for + /// a `PyPayload`, and `ObjectHead` for `ObjectHead`. + type Repr: super::core::PayloadRepr; +} + +/// `PayloadRepr` represents the actual layout of a `SuperPayload`. +/// +/// Mainly exists to unify `PyObjtRepr` and `ObjectHead`. +/// +/// # Safety +/// +/// The implementing type's layout must have `ObjectHead` at the very start. +pub unsafe trait PayloadRepr { + /// Access the header of this payload. + /// + /// Should always compile down to a no-op, since `ObjectHead` should always + /// get laid out at the start of any given `PyObjRepr` + fn as_header(&self) -> &PyObjHeader; + + /// Like `MaybeTraverse::try_traverse`, except it doesn't traverse the + /// object header - that's done separately. Once dict and weak_ref_list + /// are no longer stored in the header, this can be simplified. + fn repr_try_traverse(&self, tracer_fn: &mut TraverseFn<'_>); +} + +impl SuperPayload for T { + type Repr = PyObjRepr; +} - pub(super) payload: T, +impl SuperPayload for PyObjHeader { + type Repr = Self; } -impl fmt::Debug for PyInner { +// SAFETY: layout must start with `ObjectHead`: +// `PyObjRepr` is `repr(C)`, and its first field also implements `PayloadRepr`. +unsafe impl PayloadRepr for PyObjRepr { + fn as_header(&self) -> &PyObjHeader { + self.sup.as_header() + } + + fn repr_try_traverse(&self, tracer_fn: &mut TraverseFn<'_>) { + self.sup.repr_try_traverse(tracer_fn); + self.payload.try_traverse(tracer_fn); + } +} + +// SAFETY: `ObjectHead` starts with `ObjectHead` +unsafe impl PayloadRepr for PyObjHeader { + fn as_header(&self) -> &PyObjHeader { + self + } + + fn repr_try_traverse(&self, _tracer_fn: &mut TraverseFn<'_>) {} +} + +impl fmt::Debug for PyObjRepr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[PyObject {:?}]", &self.payload) } } -unsafe impl Traverse for Py { +unsafe impl Traverse for Py { /// DO notice that call `trace` on `Py` means apply `tracer_fn` on `Py`'s children, /// not like call `trace` on `PyRef` which apply `tracer_fn` on `PyRef` itself fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) { - self.0.traverse(tracer_fn) + traverse_object_head(self.header(), tracer_fn); + self.0.repr_try_traverse(tracer_fn) } } @@ -133,7 +265,10 @@ unsafe impl Traverse for PyObject { /// DO notice that call `trace` on `PyObject` means apply `tracer_fn` on `PyObject`'s children, /// not like call `trace` on `PyObjectRef` which apply `tracer_fn` on `PyObjectRef` itself fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) { - self.0.traverse(tracer_fn) + traverse_object_head(&self.0, tracer_fn); + if let Some(f) = self.header().vtable.trace { + unsafe { f(self, tracer_fn) } + } } } @@ -195,7 +330,7 @@ impl WeakRefList { if is_generic { if let Some(generic_weakref) = inner.generic_weakref { let generic_weakref = unsafe { generic_weakref.as_ref() }; - if generic_weakref.0.ref_count.get() != 0 { + if generic_weakref.header().ref_count.get() != 0 { return generic_weakref.to_owned(); } } @@ -297,7 +432,9 @@ impl WeakRefList { impl WeakListInner { fn iter(&self) -> impl Iterator> { - self.list.iter().filter(|wr| wr.0.ref_count.get() > 0) + self.list + .iter() + .filter(|wr| wr.header().ref_count.get() > 0) } } @@ -331,7 +468,7 @@ unsafe impl Link for WeakLink { } } -#[pyclass(name = "weakref", module = false)] +#[pyclass(name = "weakref", module = false, ctx = weakref_type)] #[derive(Debug)] pub struct PyWeak { pointers: Pointers>, @@ -369,11 +506,11 @@ impl PyWeak { fn drop_inner(&self) { let dealloc = { let mut guard = unsafe { self.parent.as_ref().lock() }; - let offset = std::mem::offset_of!(PyInner, payload); + let offset = std::mem::offset_of!(PyObjRepr, payload); let py_inner = (self as *const Self) .cast::() .wrapping_sub(offset) - .cast::>(); + .cast::>(); let node_ptr = unsafe { NonNull::new_unchecked(py_inner as *mut Py) }; // the list doesn't have ownership over its PyRef! we're being dropped // right now so that should be obvious!! @@ -443,25 +580,137 @@ impl InstanceDict { } } -impl PyInner { - fn new(payload: T, typ: PyTypeRef, dict: Option) -> Box { +impl PyObjRepr { + fn new(payload: T, typ: PyTypeRef, dict: Option) -> Box + where + T::Super: SuperDefault, + { let member_count = typ.slots.member_count; - Box::new(PyInner { + let header = PyObjHeader { ref_count: RefCount::new(), - typeid: TypeId::of::(), vtable: PyObjVTable::of::(), typ: PyAtomicRef::from(typ), dict: dict.map(InstanceDict::new), weak_list: WeakRefList::new(), - payload, slots: std::iter::repeat_with(|| PyRwLock::new(None)) .take(member_count) .collect_vec() .into_boxed_slice(), + }; + Box::new(PyObjRepr { + sup: T::Super::from_header(header), + payload, }) } } +#[doc(hidden)] +pub trait Builder { + fn build_repr(self, header: PyObjHeader, ctx: &Context) -> T::Repr; +} + +pub struct PyDefaultBuilder; + +impl Builder for PyDefaultBuilder { + fn build_repr(self, header: PyObjHeader, ctx: &Context) -> T::Repr { + T::py_from_header(header, ctx) + } +} + +pub struct PyObjectBuilder, T: PyPayload> { + sup: Super, + payload: T, +} + +impl> PyObjectBuilder { + pub fn new(payload: T) -> Self { + Self { + sup: PyDefaultBuilder, + payload, + } + } +} + +impl Builder for PyObjectBuilder +where + T: PyPayload, + Super: Builder, +{ + fn build_repr(self, header: PyObjHeader, ctx: &Context) -> ::Repr { + let PyObjectBuilder { sup, payload } = self; + PyObjRepr { + sup: sup.build_repr(header, ctx), + payload, + } + } +} + +impl PyObjectBuilder +where + T: PyPayload, + Super: Builder, +{ + pub fn subclass>(self, payload: Sub) -> PyObjectBuilder { + PyObjectBuilder { sup: self, payload } + } + fn _build(self, typ: PyTypeRef, ctx: &Context) -> PyRef { + let member_count = typ.slots.member_count; + let dict = if typ.slots.flags.has_feature(PyTypeFlags::HAS_DICT) { + Some(ctx.new_dict()) + } else { + None + }; + let header = PyObjHeader { + ref_count: RefCount::new(), + vtable: PyObjVTable::of::(), + typ: PyAtomicRef::from(typ), + dict: dict.map(InstanceDict::new), + weak_list: WeakRefList::new(), + slots: std::iter::repeat_with(|| PyRwLock::new(None)) + .take(member_count) + .collect_vec() + .into_boxed_slice(), + }; + PyRef::from_repr(Box::new(self.build_repr(header, ctx))) + } + + pub fn build(self, ctx: &Context) -> PyRef { + self._build(T::class(ctx).to_owned(), ctx) + } + + pub fn build_exact(self, ctx: &Context) -> PyRefExact { + let obj = self.build(ctx); + // build() provides T::class as the type, so it's always exact + unsafe { PyRefExact::new_unchecked(obj) } + } + + #[inline] + pub fn build_with_type(self, cls: PyTypeRef, vm: &VirtualMachine) -> PyResult> { + let exact_class = T::class(&vm.ctx); + if cls.fast_issubclass(exact_class) { + // TODO: not checking this allows for unsoundness at the moment + // assert!(cls.type_id == exact_class.type_id); + Ok(self._build(cls, &vm.ctx)) + } else { + #[cold] + #[inline(never)] + fn _build_with_type_error( + vm: &VirtualMachine, + cls: PyTypeRef, + exact_class: &Py, + ) -> PyBaseExceptionRef { + vm.new_type_error(format!( + "'{}' is not a subtype of '{}'", + &cls.name(), + exact_class.name() + )) + } + + Err(_build_with_type_error(vm, cls, exact_class)) + } + } +} + /// The `PyObjectRef` is one of the most used types. It is a reference to a /// python object. A single python object can have multiple references, and /// this reference counting is accounted for by this type. Use the `.clone()` @@ -487,7 +736,7 @@ cfg_if::cfg_if! { } #[repr(transparent)] -pub struct PyObject(PyInner); +pub struct PyObject(PyObjHeader); impl Deref for PyObjectRef { type Target = PyObject; @@ -532,7 +781,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.payload_is::() { Ok(unsafe { self.downcast_unchecked() }) } else { @@ -541,7 +790,7 @@ impl PyObjectRef { } #[inline(always)] - pub fn downcast_ref(&self) -> Option<&Py> { + pub fn downcast_ref(&self) -> Option<&Py> { if self.payload_is::() { // SAFETY: just checked that the payload is T, and PyRef is repr(transparent) over // PyObjectRef @@ -556,7 +805,7 @@ impl PyObjectRef { /// # Safety /// T must be the exact payload type #[inline(always)] - pub unsafe fn downcast_unchecked(self) -> PyRef { + pub unsafe fn downcast_unchecked(self) -> PyRef { // PyRef::from_obj_unchecked(self) // manual impl to avoid assertion let obj = ManuallyDrop::new(self); @@ -565,15 +814,6 @@ impl PyObjectRef { } } - /// # Safety - /// T must be the exact payload type - #[inline(always)] - pub unsafe fn downcast_unchecked_ref(&self) -> &Py { - debug_assert!(self.payload_is::()); - // SAFETY: requirements forwarded from caller - unsafe { &*(self as *const PyObjectRef as *const PyRef) } - } - // ideally we'd be able to define these in pyobject.rs, but method visibility rules are weird /// Attempt to downcast this reference to the specific class that is associated `T`. @@ -581,7 +821,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( + pub fn downcast_exact( self, vm: &VirtualMachine, ) -> Result, Self> { @@ -600,6 +840,11 @@ impl PyObjectRef { } impl PyObject { + #[inline(always)] + fn header(&self) -> &PyObjHeader { + &self.0 + } + #[inline(always)] fn weak_ref_list(&self) -> Option<&WeakRefList> { Some(&self.0.weak_list) @@ -653,8 +898,10 @@ impl PyObject { } #[inline(always)] - pub fn payload_is(&self) -> bool { - self.0.typeid == TypeId::of::() + pub fn payload_is(&self) -> bool { + self.class() + .iter_base_chain() + .any(|t| t.type_id == TypeId::of::()) } /// Force to return payload as T. @@ -662,15 +909,15 @@ impl PyObject { /// # Safety /// The actual payload type must be T. #[inline(always)] - pub unsafe fn payload_unchecked(&self) -> &T { + pub 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) }; + let inner = unsafe { &*(&self.0 as *const PyObjHeader as *const PyObjRepr) }; &inner.payload } #[inline(always)] - pub fn payload(&self) -> Option<&T> { + pub fn payload(&self) -> Option<&T> { if self.payload_is::() { Some(unsafe { self.payload_unchecked() }) } else { @@ -683,12 +930,16 @@ impl PyObject { self.0.typ.deref() } - pub fn set_class(&self, typ: PyTypeRef, vm: &VirtualMachine) { + pub fn set_class(&self, typ: PyTypeRef, vm: &VirtualMachine) -> Result<(), PyTypeRef> { + if self.class().type_id != typ.type_id { + return Err(typ); + } self.0.typ.swap_to_temporary_refs(typ, vm); + Ok(()) } #[inline(always)] - pub fn payload_if_exact( + pub fn payload_if_exact( &self, vm: &VirtualMachine, ) -> Option<&T> { @@ -731,7 +982,7 @@ impl PyObject { } #[inline(always)] - pub fn downcast_ref(&self) -> Option<&Py> { + pub fn downcast_ref(&self) -> Option<&Py> { if self.payload_is::() { // SAFETY: just checked that the payload is T, and PyRef is repr(transparent) over // PyObjectRef @@ -742,7 +993,7 @@ impl PyObject { } #[inline(always)] - pub fn downcast_ref_if_exact( + pub fn downcast_ref_if_exact( &self, vm: &VirtualMachine, ) -> Option<&Py> { @@ -754,9 +1005,12 @@ 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.payload_is::()); - // SAFETY: requirements forwarded from caller + // SAFETY: requirements forwarded from caller. this is possibly a bit + // sketchy because we're widening the range of the `&` reference from + // just the `PyObjHeader` to the entire object, but under tree borrows + // it's fine according to miri, since `RefCount` isn't `Freeze`. unsafe { &*(self as *const PyObject as *const Py) } } @@ -868,7 +1122,7 @@ impl AsRef for PyObject { } } -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() @@ -899,9 +1153,27 @@ impl fmt::Debug for PyObjectRef { } #[repr(transparent)] -pub struct Py(PyInner); +pub struct Py(PyObjRepr); + +impl Py { + #[inline(always)] + fn header(&self) -> &PyObjHeader { + self.0.header() + } + + #[allow(private_bounds)] + pub fn super_(&self) -> &Py + where + T::Super: PyPayload, + // this should really be superfluous - T::Super: PyPayload implies it, + // but the current trait solver isn't smart enough + T: PyPayload>>, + { + let sup: &PyObjRepr = &self.0.sup; + // SAFETY: + unsafe { &*(sup as *const PyObjRepr as *const Py) } + } -impl Py { pub fn downgrade( &self, callback: Option, @@ -914,19 +1186,19 @@ impl Py { } } -impl ToOwned for Py { +impl ToOwned for Py { type Owned = PyRef; #[inline(always)] fn to_owned(&self) -> Self::Owned { - self.0.ref_count.inc(); + self.header().ref_count.inc(); PyRef { ptr: NonNull::from(self), } } } -impl Deref for Py { +impl Deref for Py { type Target = T; #[inline(always)] @@ -935,16 +1207,16 @@ 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) } + unsafe { &*(&self.0 as *const PyObjRepr as *const PyObject) } } } impl std::hash::Hash for Py where - T: std::hash::Hash + PyObjectPayload, + T: std::hash::Hash + PyPayload, { #[inline] fn hash(&self, state: &mut H) { @@ -954,7 +1226,7 @@ where impl PartialEq for Py where - T: PartialEq + PyObjectPayload, + T: PartialEq + PyPayload, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -962,11 +1234,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 { @@ -974,7 +1246,7 @@ where } } -impl fmt::Debug for Py { +impl fmt::Debug for Py { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } @@ -990,40 +1262,40 @@ impl fmt::Debug for Py { /// situations (such as when implementing in-place methods such as `__iadd__`) /// where a reference to the same object must be returned. #[repr(transparent)] -pub struct PyRef { +pub struct PyRef { ptr: NonNull>, } cfg_if::cfg_if! { if #[cfg(feature = "threading")] { - unsafe impl Send for PyRef {} - unsafe impl Sync for PyRef {} + unsafe impl Send for PyRef {} + unsafe impl Sync for PyRef {} } } -impl fmt::Debug for PyRef { +impl fmt::Debug for PyRef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -impl Drop for PyRef { +impl Drop for PyRef { #[inline] fn drop(&mut self) { - if self.0.ref_count.dec() { + if self.header().ref_count.dec() { unsafe { PyObject::drop_slow(self.ptr.cast::()) } } } } -impl Clone for PyRef { +impl Clone for PyRef { #[inline(always)] fn clone(&self) -> Self { (**self).to_owned() } } -impl PyRef { +impl PyRef { #[inline(always)] pub(crate) unsafe fn from_raw(raw: *const Py) -> Self { Self { @@ -1042,8 +1314,16 @@ 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)); + pub fn new_ref(payload: T, typ: crate::builtins::PyTypeRef, dict: Option) -> Self + where + T::Super: SuperDefault, + { + Self::from_repr(PyObjRepr::new(payload, typ, dict)) + } + + #[inline(always)] + fn from_repr(repr: Box>) -> Self { + let inner = Box::into_raw(repr); Self { ptr: unsafe { NonNull::new_unchecked(inner.cast::>()) }, } @@ -1058,7 +1338,7 @@ impl PyRef { impl Borrow for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn borrow(&self) -> &PyObject { @@ -1068,7 +1348,7 @@ where impl AsRef for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn as_ref(&self) -> &PyObject { @@ -1078,7 +1358,7 @@ where impl From> for PyObjectRef where - T: PyObjectPayload, + T: PyPayload, { #[inline] fn from(value: PyRef) -> Self { @@ -1089,7 +1369,7 @@ where impl Borrow> for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn borrow(&self) -> &Py { @@ -1099,7 +1379,7 @@ where impl AsRef> for PyRef where - T: PyObjectPayload, + T: PyPayload, { #[inline(always)] fn as_ref(&self) -> &Py { @@ -1109,7 +1389,7 @@ where impl Deref for PyRef where - T: PyObjectPayload, + T: PyPayload, { type Target = Py; @@ -1121,7 +1401,7 @@ where impl std::hash::Hash for PyRef where - T: std::hash::Hash + PyObjectPayload, + T: std::hash::Hash + PyPayload, { #[inline] fn hash(&self, state: &mut H) { @@ -1131,7 +1411,7 @@ where impl PartialEq for PyRef where - T: PartialEq + PyObjectPayload, + T: PartialEq + PyPayload, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -1139,15 +1419,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() @@ -1160,23 +1440,14 @@ impl PyWeakRef { /// either given values or explicitly left uninitialized macro_rules! partially_init { ( - $ty:path {$($init_field:ident: $init_value:expr),*$(,)?}, + $ty:path {$($($init_field:ident).+: $init_value:expr),*$(,)?}, Uninit { $($uninit_field:ident),*$(,)? }$(,)? ) => {{ - // check all the fields are there but *don't* actually run it - - #[allow(clippy::diverging_sub_expression)] // FIXME: better way than using `if false`? - if false { - #[allow(invalid_value, dead_code, unreachable_code)] - let _ = {$ty { - $($init_field: $init_value,)* - $($uninit_field: unreachable!(),)* - }}; - } + // FIXME: figure out a way to check that all the fields have been mentioned let mut m = ::std::mem::MaybeUninit::<$ty>::uninit(); #[allow(unused_unsafe)] unsafe { - $(::std::ptr::write(&mut (*m.as_mut_ptr()).$init_field, $init_value);)* + $(::std::ptr::write(&raw mut (*m.as_mut_ptr()).$($init_field).+, $init_value);)* } m }}; @@ -1193,11 +1464,12 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) { let (type_type, object_type) = { // We cast between these 2 types, so make sure (at compile time) that there's no change in // layout when we wrap PyInner in MaybeUninit<> - static_assertions::assert_eq_size!(MaybeUninit>, PyInner); - static_assertions::assert_eq_align!(MaybeUninit>, PyInner); + static_assertions::assert_eq_size!(MaybeUninit>, PyObjRepr); + static_assertions::assert_eq_align!(MaybeUninit>, PyObjRepr); let type_payload = PyType { base: None, + type_id: TypeId::of::(), bases: PyRwLock::default(), mro: PyRwLock::default(), subclasses: PyRwLock::default(), @@ -1207,6 +1479,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) { }; let object_payload = PyType { base: None, + type_id: TypeId::of::(), bases: PyRwLock::default(), mro: PyRwLock::default(), subclasses: PyRwLock::default(), @@ -1215,40 +1488,46 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) { heaptype_ext: None, }; let type_type_ptr = Box::into_raw(Box::new(partially_init!( - PyInner:: { - ref_count: RefCount::new(), - typeid: TypeId::of::(), - vtable: PyObjVTable::of::(), - dict: None, - weak_list: WeakRefList::new(), + PyObjRepr:: { + sup.payload: PyBaseObject, + sup.sup.ref_count: RefCount::new(), + sup.sup.vtable: PyObjVTable::of::(), + sup.sup.dict: None, + sup.sup.weak_list: WeakRefList::new(), payload: type_payload, - slots: Box::new([]), + sup.sup.slots: Box::new([]), }, Uninit { typ } ))); let object_type_ptr = Box::into_raw(Box::new(partially_init!( - PyInner:: { - ref_count: RefCount::new(), - typeid: TypeId::of::(), - vtable: PyObjVTable::of::(), - dict: None, - weak_list: WeakRefList::new(), + PyObjRepr:: { + sup.payload: PyBaseObject, + sup.sup.ref_count: RefCount::new(), + sup.sup.vtable: PyObjVTable::of::(), + sup.sup.dict: None, + sup.sup.weak_list: WeakRefList::new(), payload: object_payload, - slots: Box::new([]), + sup.sup.slots: Box::new([]), }, Uninit { typ }, ))); - let object_type_ptr = object_type_ptr as *mut PyInner; - let type_type_ptr = type_type_ptr as *mut PyInner; + let object_type_ptr = object_type_ptr as *mut PyObjRepr; + let type_type_ptr = type_type_ptr as *mut PyObjRepr; unsafe { - (*type_type_ptr).ref_count.inc(); + (*type_type_ptr).sup.sup.ref_count.inc(); let type_type = PyTypeRef::from_raw(type_type_ptr.cast()); - ptr::write(&mut (*object_type_ptr).typ, PyAtomicRef::from(type_type)); - (*type_type_ptr).ref_count.inc(); + ptr::write( + &raw mut (*object_type_ptr).sup.sup.typ, + PyAtomicRef::from(type_type), + ); + (*type_type_ptr).sup.sup.ref_count.inc(); let type_type = PyTypeRef::from_raw(type_type_ptr.cast()); - ptr::write(&mut (*type_type_ptr).typ, PyAtomicRef::from(type_type)); + ptr::write( + &raw mut (*type_type_ptr).sup.sup.typ, + PyAtomicRef::from(type_type), + ); let object_type = PyTypeRef::from_raw(object_type_ptr.cast()); @@ -1264,6 +1543,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) { let weakref_type = PyType { base: Some(object_type.clone()), + type_id: TypeId::of::(), bases: PyRwLock::new(vec![object_type.clone()]), mro: PyRwLock::new(vec![object_type.clone()]), subclasses: PyRwLock::default(), diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index b2bc6eec46..7a8c7204e7 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -1,4 +1,5 @@ use super::{ + SuperDefault, core::{Py, PyObject, PyObjectRef, PyRef}, payload::{PyObjectPayload, PyPayload}, }; @@ -564,7 +565,7 @@ impl ToPyObject for &PyObject { // explicitly implementing `ToPyObject`. impl ToPyObject for T where - T: PyPayload + Sized, + T: PyPayload + Sized, { #[inline(always)] fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { diff --git a/vm/src/object/mod.rs b/vm/src/object/mod.rs index 034523afe5..f4557b5d11 100644 --- a/vm/src/object/mod.rs +++ b/vm/src/object/mod.rs @@ -4,7 +4,8 @@ mod payload; mod traverse; mod traverse_object; -pub use self::core::*; +pub use self::core::{Py, PyObject, PyObjectBuilder, PyObjectRef, PyRef, PyWeak, PyWeakRef}; +pub(crate) use self::core::{PyObjHeader, init_type_hierarchy}; pub use self::ext::*; pub use self::payload::*; pub use traverse::{MaybeTraverse, Traverse, TraverseFn}; diff --git a/vm/src/object/payload.rs b/vm/src/object/payload.rs index 6413d6ae06..2af8e048fe 100644 --- a/vm/src/object/payload.rs +++ b/vm/src/object/payload.rs @@ -1,8 +1,7 @@ -use crate::object::{MaybeTraverse, Py, PyObjectRef, PyRef, PyResult}; +use super::{MaybeTraverse, Py, PyObjectBuilder, PyObjectRef, PyRef, PyResult, core::SuperPayload}; use crate::{ PyRefExact, - builtins::{PyBaseExceptionRef, PyType, PyTypeRef}, - types::PyTypeFlags, + builtins::{PyType, PyTypeRef}, vm::{Context, VirtualMachine}, }; @@ -19,68 +18,64 @@ cfg_if::cfg_if! { pub trait PyPayload: std::fmt::Debug + MaybeTraverse + PyThreadingConstraint + Sized + 'static { + #[allow(private_bounds)] + type Super: SuperPayload; + fn class(ctx: &Context) -> &'static Py; #[inline] - fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { + fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef + where + Self::Super: SuperPyDefault, + { self.into_ref(&vm.ctx).into() } #[inline] - fn _into_ref(self, cls: PyTypeRef, ctx: &Context) -> PyRef { - let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) { - Some(ctx.new_dict()) - } else { - None - }; - PyRef::new_ref(self, cls, dict) + fn into_exact_ref(self, ctx: &Context) -> PyRefExact + where + Self::Super: SuperPyDefault, + { + PyObjectBuilder::new(self).build_exact(ctx) } #[inline] - fn into_exact_ref(self, ctx: &Context) -> PyRefExact { - unsafe { - // Self::into_ref() always returns exact typed PyRef - PyRefExact::new_unchecked(self.into_ref(ctx)) - } + fn into_ref(self, ctx: &Context) -> PyRef + where + Self::Super: SuperPyDefault, + { + PyObjectBuilder::new(self).build(ctx) } #[inline] - fn into_ref(self, ctx: &Context) -> PyRef { - let cls = Self::class(ctx); - self._into_ref(cls.to_owned(), ctx) + fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> + where + Self::Super: SuperPyDefault, + { + PyObjectBuilder::new(self).build_with_type(cls, vm) } +} - #[inline] - fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> { - let exact_class = Self::class(&vm.ctx); - if cls.fast_issubclass(exact_class) { - Ok(self._into_ref(cls, &vm.ctx)) - } else { - #[cold] - #[inline(never)] - fn _into_ref_with_type_error( - vm: &VirtualMachine, - cls: &PyTypeRef, - exact_class: &Py, - ) -> PyBaseExceptionRef { - vm.new_type_error(format!( - "'{}' is not a subtype of '{}'", - &cls.name(), - exact_class.name() - )) - } - Err(_into_ref_with_type_error(vm, &cls, exact_class)) - } - } +pub use PyPayload as PyObjectPayload; + +pub trait PyDefault { + fn py_default(ctx: &Context) -> Self; } -pub trait PyObjectPayload: - std::any::Any + std::fmt::Debug + MaybeTraverse + PyThreadingConstraint + 'static -{ +impl PyDefault for T { + fn py_default(_ctx: &Context) -> Self { + T::default() + } } -impl PyObjectPayload for T {} +/// Implemented for `PyPayload::Super` types that implement [`PyDefault`]. +pub trait SuperPyDefault: SuperPayload { + #[doc(hidden)] + fn py_from_header(header: super::PyObjHeader, ctx: &Context) -> Self::Repr; +} -pub trait SlotOffset { - fn offset() -> usize; +/// Implemented for `PyPayload::Super` types that implement [`Default`]. +pub trait SuperDefault: SuperPayload + SuperPyDefault { + #[doc(hidden)] + fn from_header(header: super::PyObjHeader) -> Self::Repr; } diff --git a/vm/src/object/traverse_object.rs b/vm/src/object/traverse_object.rs index 2cf4fba2d3..27ae2f3940 100644 --- a/vm/src/object/traverse_object.rs +++ b/vm/src/object/traverse_object.rs @@ -1,13 +1,9 @@ use std::fmt; -use crate::{ - PyObject, - object::{ - Erased, InstanceDict, PyInner, PyObjectPayload, debug_obj, drop_dealloc_obj, try_trace_obj, - }, -}; +use crate::PyObject; -use super::{Traverse, TraverseFn}; +use super::core::{InstanceDict, debug_obj, drop_dealloc_obj, try_trace_obj}; +use super::{PyObjectPayload, Traverse, TraverseFn}; pub(in crate::object) struct PyObjVTable { pub(in crate::object) drop_dealloc: unsafe fn(*mut PyObject), @@ -36,36 +32,3 @@ unsafe impl Traverse for InstanceDict { self.d.traverse(tracer_fn) } } - -unsafe impl Traverse for PyInner { - /// Because PyObject hold a `PyInner`, so we need to trace it - fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) { - // 1. trace `dict` and `slots` field(`typ` can't trace for it's a AtomicRef while is leaked by design) - // 2. call vtable's trace function to trace payload - // self.typ.trace(tracer_fn); - self.dict.traverse(tracer_fn); - // weak_list keeps a *pointer* to a struct for maintaince weak ref, so no ownership, no trace - self.slots.traverse(tracer_fn); - - if let Some(f) = self.vtable.trace { - unsafe { - let zelf = &*(self as *const PyInner as *const PyObject); - f(zelf, tracer_fn) - } - }; - } -} - -unsafe impl Traverse for PyInner { - /// Type is known, so we can call `try_trace` directly instead of using erased type vtable - fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) { - // 1. trace `dict` and `slots` field(`typ` can't trace for it's a AtomicRef while is leaked by design) - // 2. call corresponding `try_trace` function to trace payload - // (No need to call vtable's trace function because we already know the type) - // self.typ.trace(tracer_fn); - self.dict.traverse(tracer_fn); - // weak_list keeps a *pointer* to a struct for maintaince weak ref, so no ownership, no trace - self.slots.traverse(tracer_fn); - T::try_traverse(&self.payload, tracer_fn); - } -} diff --git a/vm/src/protocol/buffer.rs b/vm/src/protocol/buffer.rs index fcd44c11d3..de2a57b847 100644 --- a/vm/src/protocol/buffer.rs +++ b/vm/src/protocol/buffer.rs @@ -402,7 +402,7 @@ pub trait BufferResizeGuard { } #[pyclass(module = false, name = "vec_buffer")] -#[derive(Debug, PyPayload)] +#[derive(Debug)] pub struct VecBuffer { data: PyMutex>, } diff --git a/vm/src/stdlib/ast/pyast.rs b/vm/src/stdlib/ast/pyast.rs index 3692b0a2c2..18e6b78e16 100644 --- a/vm/src/stdlib/ast/pyast.rs +++ b/vm/src/stdlib/ast/pyast.rs @@ -2,11 +2,13 @@ use super::*; use crate::common::ascii; -#[pyclass(module = "_ast", name = "mod", base = "NodeAst")] +#[pyclass(module = "_ast", name = "mod", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeMod; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeMod {} -#[pyclass(module = "_ast", name = "Module", base = "NodeMod")] +#[pyclass(module = "_ast", name = "Module", base = NodeMod)] +#[derive(Default, Debug)] pub(crate) struct NodeModModule; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeModModule { @@ -23,7 +25,8 @@ impl NodeModModule { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Interactive", base = "NodeMod")] +#[pyclass(module = "_ast", name = "Interactive", base = NodeMod)] +#[derive(Default, Debug)] pub(crate) struct NodeModInteractive; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeModInteractive { @@ -37,7 +40,8 @@ impl NodeModInteractive { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Expression", base = "NodeMod")] +#[pyclass(module = "_ast", name = "Expression", base = NodeMod)] +#[derive(Default, Debug)] pub(crate) struct NodeModExpression; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeModExpression { @@ -51,7 +55,8 @@ impl NodeModExpression { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "FunctionType", base = "NodeMod")] +#[pyclass(module = "_ast", name = "FunctionType", base = NodeMod)] +#[derive(Default, Debug)] pub(crate) struct NodeModFunctionType; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeModFunctionType { @@ -68,11 +73,13 @@ impl NodeModFunctionType { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "stmt", base = "NodeAst")] +#[pyclass(module = "_ast", name = "stmt", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeStmt; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmt {} -#[pyclass(module = "_ast", name = "FunctionDef", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "FunctionDef", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtFunctionDef; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtFunctionDef { @@ -103,7 +110,8 @@ impl NodeStmtFunctionDef { ); } } -#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAsyncFunctionDef; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAsyncFunctionDef { @@ -134,7 +142,8 @@ impl NodeStmtAsyncFunctionDef { ); } } -#[pyclass(module = "_ast", name = "ClassDef", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "ClassDef", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtClassDef; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtClassDef { @@ -164,7 +173,8 @@ impl NodeStmtClassDef { ); } } -#[pyclass(module = "_ast", name = "Return", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Return", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtReturn; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtReturn { @@ -187,7 +197,8 @@ impl NodeStmtReturn { ); } } -#[pyclass(module = "_ast", name = "Delete", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Delete", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtDelete; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtDelete { @@ -210,7 +221,8 @@ impl NodeStmtDelete { ); } } -#[pyclass(module = "_ast", name = "Assign", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Assign", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAssign; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAssign { @@ -237,7 +249,8 @@ impl NodeStmtAssign { ); } } -#[pyclass(module = "_ast", name = "TypeAlias", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "TypeAlias", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtTypeAlias; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtTypeAlias { @@ -264,7 +277,8 @@ impl NodeStmtTypeAlias { ); } } -#[pyclass(module = "_ast", name = "AugAssign", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "AugAssign", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAugAssign; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAugAssign { @@ -291,7 +305,8 @@ impl NodeStmtAugAssign { ); } } -#[pyclass(module = "_ast", name = "AnnAssign", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "AnnAssign", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAnnAssign; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAnnAssign { @@ -319,7 +334,8 @@ impl NodeStmtAnnAssign { ); } } -#[pyclass(module = "_ast", name = "For", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "For", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtFor; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtFor { @@ -348,7 +364,8 @@ impl NodeStmtFor { ); } } -#[pyclass(module = "_ast", name = "AsyncFor", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "AsyncFor", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAsyncFor; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAsyncFor { @@ -377,7 +394,8 @@ impl NodeStmtAsyncFor { ); } } -#[pyclass(module = "_ast", name = "While", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "While", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtWhile; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtWhile { @@ -404,7 +422,8 @@ impl NodeStmtWhile { ); } } -#[pyclass(module = "_ast", name = "If", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "If", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtIf; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtIf { @@ -431,7 +450,8 @@ impl NodeStmtIf { ); } } -#[pyclass(module = "_ast", name = "With", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "With", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtWith; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtWith { @@ -458,7 +478,8 @@ impl NodeStmtWith { ); } } -#[pyclass(module = "_ast", name = "AsyncWith", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "AsyncWith", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAsyncWith; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAsyncWith { @@ -485,7 +506,8 @@ impl NodeStmtAsyncWith { ); } } -#[pyclass(module = "_ast", name = "Match", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Match", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtMatch; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtMatch { @@ -511,7 +533,8 @@ impl NodeStmtMatch { ); } } -#[pyclass(module = "_ast", name = "Raise", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Raise", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtRaise; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtRaise { @@ -537,7 +560,8 @@ impl NodeStmtRaise { ); } } -#[pyclass(module = "_ast", name = "Try", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Try", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtTry; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtTry { @@ -565,7 +589,8 @@ impl NodeStmtTry { ); } } -#[pyclass(module = "_ast", name = "TryStar", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "TryStar", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtTryStar; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtTryStar { @@ -593,7 +618,8 @@ impl NodeStmtTryStar { ); } } -#[pyclass(module = "_ast", name = "Assert", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Assert", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtAssert; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtAssert { @@ -619,7 +645,8 @@ impl NodeStmtAssert { ); } } -#[pyclass(module = "_ast", name = "Import", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Import", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtImport; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtImport { @@ -642,7 +669,8 @@ impl NodeStmtImport { ); } } -#[pyclass(module = "_ast", name = "ImportFrom", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "ImportFrom", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtImportFrom; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtImportFrom { @@ -669,7 +697,8 @@ impl NodeStmtImportFrom { ); } } -#[pyclass(module = "_ast", name = "Global", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Global", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtGlobal; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtGlobal { @@ -692,7 +721,8 @@ impl NodeStmtGlobal { ); } } -#[pyclass(module = "_ast", name = "Nonlocal", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Nonlocal", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtNonlocal; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtNonlocal { @@ -715,7 +745,8 @@ impl NodeStmtNonlocal { ); } } -#[pyclass(module = "_ast", name = "Expr", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Expr", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtExpr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtExpr { @@ -738,7 +769,8 @@ impl NodeStmtExpr { ); } } -#[pyclass(module = "_ast", name = "Pass", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Pass", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtPass; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtPass { @@ -757,7 +789,8 @@ impl NodeStmtPass { ); } } -#[pyclass(module = "_ast", name = "Break", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Break", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtBreak; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtBreak { @@ -776,7 +809,8 @@ impl NodeStmtBreak { ); } } -#[pyclass(module = "_ast", name = "Continue", base = "NodeStmt")] +#[pyclass(module = "_ast", name = "Continue", base = NodeStmt)] +#[derive(Default, Debug)] pub(crate) struct NodeStmtContinue; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeStmtContinue { @@ -795,11 +829,13 @@ impl NodeStmtContinue { ); } } -#[pyclass(module = "_ast", name = "expr", base = "NodeAst")] +#[pyclass(module = "_ast", name = "expr", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeExpr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExpr {} -#[pyclass(module = "_ast", name = "BoolOp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "BoolOp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprBoolOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprBoolOp { @@ -825,7 +861,8 @@ impl NodeExprBoolOp { ); } } -#[pyclass(module = "_ast", name = "NamedExpr", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "NamedExpr", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprNamedExpr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprNamedExpr { @@ -851,7 +888,8 @@ impl NodeExprNamedExpr { ); } } -#[pyclass(module = "_ast", name = "BinOp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "BinOp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprBinOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprBinOp { @@ -878,7 +916,8 @@ impl NodeExprBinOp { ); } } -#[pyclass(module = "_ast", name = "UnaryOp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "UnaryOp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprUnaryOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprUnaryOp { @@ -904,7 +943,8 @@ impl NodeExprUnaryOp { ); } } -#[pyclass(module = "_ast", name = "Lambda", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Lambda", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprLambda; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprLambda { @@ -930,7 +970,8 @@ impl NodeExprLambda { ); } } -#[pyclass(module = "_ast", name = "IfExp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "IfExp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprIfExp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprIfExp { @@ -957,7 +998,8 @@ impl NodeExprIfExp { ); } } -#[pyclass(module = "_ast", name = "Dict", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Dict", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprDict; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprDict { @@ -983,7 +1025,8 @@ impl NodeExprDict { ); } } -#[pyclass(module = "_ast", name = "Set", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Set", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprSet; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprSet { @@ -1006,7 +1049,8 @@ impl NodeExprSet { ); } } -#[pyclass(module = "_ast", name = "ListComp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "ListComp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprListComp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprListComp { @@ -1032,7 +1076,8 @@ impl NodeExprListComp { ); } } -#[pyclass(module = "_ast", name = "SetComp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "SetComp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprSetComp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprSetComp { @@ -1058,7 +1103,8 @@ impl NodeExprSetComp { ); } } -#[pyclass(module = "_ast", name = "DictComp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "DictComp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprDictComp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprDictComp { @@ -1085,7 +1131,8 @@ impl NodeExprDictComp { ); } } -#[pyclass(module = "_ast", name = "GeneratorExp", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "GeneratorExp", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprGeneratorExp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprGeneratorExp { @@ -1111,7 +1158,8 @@ impl NodeExprGeneratorExp { ); } } -#[pyclass(module = "_ast", name = "Await", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Await", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprAwait; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprAwait { @@ -1134,7 +1182,8 @@ impl NodeExprAwait { ); } } -#[pyclass(module = "_ast", name = "Yield", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Yield", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprYield; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprYield { @@ -1157,7 +1206,8 @@ impl NodeExprYield { ); } } -#[pyclass(module = "_ast", name = "YieldFrom", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "YieldFrom", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprYieldFrom; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprYieldFrom { @@ -1180,7 +1230,8 @@ impl NodeExprYieldFrom { ); } } -#[pyclass(module = "_ast", name = "Compare", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Compare", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprCompare; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprCompare { @@ -1207,7 +1258,8 @@ impl NodeExprCompare { ); } } -#[pyclass(module = "_ast", name = "Call", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Call", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprCall; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprCall { @@ -1234,7 +1286,8 @@ impl NodeExprCall { ); } } -#[pyclass(module = "_ast", name = "FormattedValue", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "FormattedValue", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprFormattedValue; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprFormattedValue { @@ -1261,7 +1314,8 @@ impl NodeExprFormattedValue { ); } } -#[pyclass(module = "_ast", name = "JoinedStr", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "JoinedStr", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprJoinedStr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprJoinedStr { @@ -1284,7 +1338,8 @@ impl NodeExprJoinedStr { ); } } -#[pyclass(module = "_ast", name = "Constant", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Constant", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprConstant; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprConstant { @@ -1310,7 +1365,8 @@ impl NodeExprConstant { ); } } -#[pyclass(module = "_ast", name = "Attribute", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Attribute", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprAttribute; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprAttribute { @@ -1337,7 +1393,8 @@ impl NodeExprAttribute { ); } } -#[pyclass(module = "_ast", name = "Subscript", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Subscript", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprSubscript; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprSubscript { @@ -1364,7 +1421,8 @@ impl NodeExprSubscript { ); } } -#[pyclass(module = "_ast", name = "Starred", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Starred", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprStarred; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprStarred { @@ -1390,7 +1448,8 @@ impl NodeExprStarred { ); } } -#[pyclass(module = "_ast", name = "Name", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Name", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprName; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprName { @@ -1416,7 +1475,8 @@ impl NodeExprName { ); } } -#[pyclass(module = "_ast", name = "List", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "List", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprList; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprList { @@ -1442,7 +1502,8 @@ impl NodeExprList { ); } } -#[pyclass(module = "_ast", name = "Tuple", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Tuple", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprTuple; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprTuple { @@ -1468,7 +1529,8 @@ impl NodeExprTuple { ); } } -#[pyclass(module = "_ast", name = "Slice", base = "NodeExpr")] +#[pyclass(module = "_ast", name = "Slice", base = NodeExpr)] +#[derive(Default, Debug)] pub(crate) struct NodeExprSlice; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprSlice { @@ -1495,11 +1557,13 @@ impl NodeExprSlice { ); } } -#[pyclass(module = "_ast", name = "expr_context", base = "NodeAst")] +#[pyclass(module = "_ast", name = "expr_context", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeExprContext; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprContext {} -#[pyclass(module = "_ast", name = "Load", base = "NodeExprContext")] +#[pyclass(module = "_ast", name = "Load", base = NodeExprContext)] +#[derive(Default, Debug)] pub(crate) struct NodeExprContextLoad; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprContextLoad { @@ -1509,7 +1573,8 @@ impl NodeExprContextLoad { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Store", base = "NodeExprContext")] +#[pyclass(module = "_ast", name = "Store", base = NodeExprContext)] +#[derive(Default, Debug)] pub(crate) struct NodeExprContextStore; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprContextStore { @@ -1519,7 +1584,8 @@ impl NodeExprContextStore { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Del", base = "NodeExprContext")] +#[pyclass(module = "_ast", name = "Del", base = NodeExprContext)] +#[derive(Default, Debug)] pub(crate) struct NodeExprContextDel; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExprContextDel { @@ -1529,11 +1595,13 @@ impl NodeExprContextDel { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "boolop", base = "NodeAst")] +#[pyclass(module = "_ast", name = "boolop", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeBoolOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeBoolOp {} -#[pyclass(module = "_ast", name = "And", base = "NodeBoolOp")] +#[pyclass(module = "_ast", name = "And", base = NodeBoolOp)] +#[derive(Default, Debug)] pub(crate) struct NodeBoolOpAnd; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeBoolOpAnd { @@ -1543,7 +1611,8 @@ impl NodeBoolOpAnd { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Or", base = "NodeBoolOp")] +#[pyclass(module = "_ast", name = "Or", base = NodeBoolOp)] +#[derive(Default, Debug)] pub(crate) struct NodeBoolOpOr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeBoolOpOr { @@ -1553,11 +1622,13 @@ impl NodeBoolOpOr { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "operator", base = "NodeAst")] +#[pyclass(module = "_ast", name = "operator", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeOperator; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperator {} -#[pyclass(module = "_ast", name = "Add", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Add", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorAdd; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorAdd { @@ -1567,7 +1638,8 @@ impl NodeOperatorAdd { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Sub", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Sub", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorSub; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorSub { @@ -1577,7 +1649,8 @@ impl NodeOperatorSub { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Mult", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Mult", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorMult; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorMult { @@ -1587,7 +1660,8 @@ impl NodeOperatorMult { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "MatMult", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "MatMult", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorMatMult; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorMatMult { @@ -1597,7 +1671,8 @@ impl NodeOperatorMatMult { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Div", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Div", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorDiv; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorDiv { @@ -1607,7 +1682,8 @@ impl NodeOperatorDiv { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Mod", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Mod", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorMod; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorMod { @@ -1617,7 +1693,8 @@ impl NodeOperatorMod { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Pow", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "Pow", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorPow; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorPow { @@ -1627,7 +1704,8 @@ impl NodeOperatorPow { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "LShift", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "LShift", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorLShift; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorLShift { @@ -1637,7 +1715,8 @@ impl NodeOperatorLShift { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "RShift", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "RShift", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorRShift; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorRShift { @@ -1647,7 +1726,8 @@ impl NodeOperatorRShift { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "BitOr", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "BitOr", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorBitOr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorBitOr { @@ -1657,7 +1737,8 @@ impl NodeOperatorBitOr { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "BitXor", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "BitXor", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorBitXor; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorBitXor { @@ -1667,7 +1748,8 @@ impl NodeOperatorBitXor { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "BitAnd", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "BitAnd", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorBitAnd; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorBitAnd { @@ -1677,7 +1759,8 @@ impl NodeOperatorBitAnd { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "FloorDiv", base = "NodeOperator")] +#[pyclass(module = "_ast", name = "FloorDiv", base = NodeOperator)] +#[derive(Default, Debug)] pub(crate) struct NodeOperatorFloorDiv; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeOperatorFloorDiv { @@ -1687,11 +1770,13 @@ impl NodeOperatorFloorDiv { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "unaryop", base = "NodeAst")] +#[pyclass(module = "_ast", name = "unaryop", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeUnaryOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeUnaryOp {} -#[pyclass(module = "_ast", name = "Invert", base = "NodeUnaryOp")] +#[pyclass(module = "_ast", name = "Invert", base = NodeUnaryOp)] +#[derive(Default, Debug)] pub(crate) struct NodeUnaryOpInvert; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeUnaryOpInvert { @@ -1701,7 +1786,8 @@ impl NodeUnaryOpInvert { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Not", base = "NodeUnaryOp")] +#[pyclass(module = "_ast", name = "Not", base = NodeUnaryOp)] +#[derive(Default, Debug)] pub(crate) struct NodeUnaryOpNot; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeUnaryOpNot { @@ -1711,7 +1797,8 @@ impl NodeUnaryOpNot { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "UAdd", base = "NodeUnaryOp")] +#[pyclass(module = "_ast", name = "UAdd", base = NodeUnaryOp)] +#[derive(Default, Debug)] pub(crate) struct NodeUnaryOpUAdd; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeUnaryOpUAdd { @@ -1721,7 +1808,8 @@ impl NodeUnaryOpUAdd { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "USub", base = "NodeUnaryOp")] +#[pyclass(module = "_ast", name = "USub", base = NodeUnaryOp)] +#[derive(Default, Debug)] pub(crate) struct NodeUnaryOpUSub; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeUnaryOpUSub { @@ -1731,11 +1819,13 @@ impl NodeUnaryOpUSub { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "cmpop", base = "NodeAst")] +#[pyclass(module = "_ast", name = "cmpop", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOp; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOp {} -#[pyclass(module = "_ast", name = "Eq", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "Eq", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpEq; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpEq { @@ -1745,7 +1835,8 @@ impl NodeCmpOpEq { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "NotEq", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "NotEq", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpNotEq; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpNotEq { @@ -1755,7 +1846,8 @@ impl NodeCmpOpNotEq { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Lt", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "Lt", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpLt; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpLt { @@ -1765,7 +1857,8 @@ impl NodeCmpOpLt { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "LtE", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "LtE", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpLtE; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpLtE { @@ -1775,7 +1868,8 @@ impl NodeCmpOpLtE { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Gt", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "Gt", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpGt; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpGt { @@ -1785,7 +1879,8 @@ impl NodeCmpOpGt { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "GtE", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "GtE", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpGtE; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpGtE { @@ -1795,7 +1890,8 @@ impl NodeCmpOpGtE { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "Is", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "Is", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpIs; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpIs { @@ -1805,7 +1901,8 @@ impl NodeCmpOpIs { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "IsNot", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "IsNot", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpIsNot; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpIsNot { @@ -1815,7 +1912,8 @@ impl NodeCmpOpIsNot { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "In", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "In", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpIn; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpIn { @@ -1825,7 +1923,8 @@ impl NodeCmpOpIn { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "NotIn", base = "NodeCmpOp")] +#[pyclass(module = "_ast", name = "NotIn", base = NodeCmpOp)] +#[derive(Default, Debug)] pub(crate) struct NodeCmpOpNotIn; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeCmpOpNotIn { @@ -1835,7 +1934,8 @@ impl NodeCmpOpNotIn { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "comprehension", base = "NodeAst")] +#[pyclass(module = "_ast", name = "comprehension", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeComprehension; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeComprehension { @@ -1854,11 +1954,13 @@ impl NodeComprehension { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "excepthandler", base = "NodeAst")] +#[pyclass(module = "_ast", name = "excepthandler", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeExceptHandler; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExceptHandler {} -#[pyclass(module = "_ast", name = "ExceptHandler", base = "NodeExceptHandler")] +#[pyclass(module = "_ast", name = "ExceptHandler", base = NodeExceptHandler)] +#[derive(Default, Debug)] pub(crate) struct NodeExceptHandlerExceptHandler; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeExceptHandlerExceptHandler { @@ -1885,7 +1987,8 @@ impl NodeExceptHandlerExceptHandler { ); } } -#[pyclass(module = "_ast", name = "arguments", base = "NodeAst")] +#[pyclass(module = "_ast", name = "arguments", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeArguments; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeArguments { @@ -1907,7 +2010,8 @@ impl NodeArguments { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "arg", base = "NodeAst")] +#[pyclass(module = "_ast", name = "arg", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeArg; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeArg { @@ -1934,7 +2038,8 @@ impl NodeArg { ); } } -#[pyclass(module = "_ast", name = "keyword", base = "NodeAst")] +#[pyclass(module = "_ast", name = "keyword", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeKeyword; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeKeyword { @@ -1960,7 +2065,8 @@ impl NodeKeyword { ); } } -#[pyclass(module = "_ast", name = "alias", base = "NodeAst")] +#[pyclass(module = "_ast", name = "alias", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeAlias; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeAlias { @@ -1986,7 +2092,8 @@ impl NodeAlias { ); } } -#[pyclass(module = "_ast", name = "withitem", base = "NodeAst")] +#[pyclass(module = "_ast", name = "withitem", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeWithItem; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeWithItem { @@ -2003,7 +2110,8 @@ impl NodeWithItem { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "match_case", base = "NodeAst")] +#[pyclass(module = "_ast", name = "match_case", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeMatchCase; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeMatchCase { @@ -2021,11 +2129,13 @@ impl NodeMatchCase { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "pattern", base = "NodeAst")] +#[pyclass(module = "_ast", name = "pattern", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodePattern; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePattern {} -#[pyclass(module = "_ast", name = "MatchValue", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchValue", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchValue; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchValue { @@ -2048,7 +2158,8 @@ impl NodePatternMatchValue { ); } } -#[pyclass(module = "_ast", name = "MatchSingleton", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchSingleton", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchSingleton; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchSingleton { @@ -2071,7 +2182,8 @@ impl NodePatternMatchSingleton { ); } } -#[pyclass(module = "_ast", name = "MatchSequence", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchSequence", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchSequence; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchSequence { @@ -2094,7 +2206,8 @@ impl NodePatternMatchSequence { ); } } -#[pyclass(module = "_ast", name = "MatchMapping", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchMapping", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchMapping; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchMapping { @@ -2121,7 +2234,8 @@ impl NodePatternMatchMapping { ); } } -#[pyclass(module = "_ast", name = "MatchClass", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchClass", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchClass; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchClass { @@ -2149,7 +2263,8 @@ impl NodePatternMatchClass { ); } } -#[pyclass(module = "_ast", name = "MatchStar", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchStar", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchStar; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchStar { @@ -2172,7 +2287,8 @@ impl NodePatternMatchStar { ); } } -#[pyclass(module = "_ast", name = "MatchAs", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchAs", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchAs; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchAs { @@ -2198,7 +2314,8 @@ impl NodePatternMatchAs { ); } } -#[pyclass(module = "_ast", name = "MatchOr", base = "NodePattern")] +#[pyclass(module = "_ast", name = "MatchOr", base = NodePattern)] +#[derive(Default, Debug)] pub(crate) struct NodePatternMatchOr; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodePatternMatchOr { @@ -2221,11 +2338,13 @@ impl NodePatternMatchOr { ); } } -#[pyclass(module = "_ast", name = "type_ignore", base = "NodeAst")] +#[pyclass(module = "_ast", name = "type_ignore", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeIgnore; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeIgnore {} -#[pyclass(module = "_ast", name = "TypeIgnore", base = "NodeTypeIgnore")] +#[pyclass(module = "_ast", name = "TypeIgnore", base = NodeTypeIgnore)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeIgnoreTypeIgnore; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeIgnoreTypeIgnore { @@ -2242,11 +2361,13 @@ impl NodeTypeIgnoreTypeIgnore { class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); } } -#[pyclass(module = "_ast", name = "type_param", base = "NodeAst")] +#[pyclass(module = "_ast", name = "type_param", base = NodeAst)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeParam; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeParam {} -#[pyclass(module = "_ast", name = "TypeVar", base = "NodeTypeParam")] +#[pyclass(module = "_ast", name = "TypeVar", base = NodeTypeParam)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeParamTypeVar; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeParamTypeVar { @@ -2272,7 +2393,8 @@ impl NodeTypeParamTypeVar { ); } } -#[pyclass(module = "_ast", name = "ParamSpec", base = "NodeTypeParam")] +#[pyclass(module = "_ast", name = "ParamSpec", base = NodeTypeParam)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeParamParamSpec; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeParamParamSpec { @@ -2295,7 +2417,8 @@ impl NodeTypeParamParamSpec { ); } } -#[pyclass(module = "_ast", name = "TypeVarTuple", base = "NodeTypeParam")] +#[pyclass(module = "_ast", name = "TypeVarTuple", base = NodeTypeParam)] +#[derive(Default, Debug)] pub(crate) struct NodeTypeParamTypeVarTuple; #[pyclass(flags(HAS_DICT, BASETYPE))] impl NodeTypeParamTypeVarTuple { diff --git a/vm/src/stdlib/ast/python.rs b/vm/src/stdlib/ast/python.rs index 74c4db888a..a84444d3ad 100644 --- a/vm/src/stdlib/ast/python.rs +++ b/vm/src/stdlib/ast/python.rs @@ -3,13 +3,13 @@ use super::PY_COMPILE_FLAG_AST_ONLY; #[pymodule] pub(crate) mod _ast { use crate::{ - AsObject, Context, PyObjectRef, PyPayload, PyResult, VirtualMachine, + AsObject, Context, PyObjectRef, PyResult, VirtualMachine, builtins::{PyStrRef, PyTupleRef}, function::FuncArgs, }; #[pyattr] #[pyclass(module = "_ast", name = "AST")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(crate) struct NodeAst; #[pyclass(flags(BASETYPE, HAS_DICT))] diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index fc867db2b1..d27874b8d8 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -28,7 +28,7 @@ mod _collections { #[pyattr] #[pyclass(name = "deque", unhashable = true)] - #[derive(Debug, Default, PyPayload)] + #[derive(Debug, Default)] struct PyDeque { deque: PyRwLock>, maxlen: Option, @@ -583,7 +583,7 @@ mod _collections { #[pyattr] #[pyclass(name = "_deque_iterator")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyDequeIterator { state: usize, internal: PyMutex>, @@ -663,7 +663,7 @@ mod _collections { #[pyattr] #[pyclass(name = "_deque_reverse_iterator")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyReverseDequeIterator { state: usize, // position is counting from the tail diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index 0880c6b63b..578439b18f 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -10,8 +10,8 @@ use crossbeam_utils::atomic::AtomicCell; use rustpython_common::lock::PyRwLock; use rustpython_vm::stdlib::ctypes::base::PyCData; -#[pyclass(name = "PyCArrayType", base = "PyType", module = "_ctypes")] -#[derive(PyPayload)] +#[pyclass(name = "PyCArrayType", base = PyType, module = "_ctypes")] +#[derive()] pub struct PyCArrayType { pub(super) inner: PyCArray, } @@ -49,11 +49,11 @@ impl PyCArrayType {} #[pyclass( name = "Array", - base = "PyCData", + base = PyCData, metaclass = "PyCArrayType", module = "_ctypes" )] -#[derive(PyPayload)] +#[derive()] pub struct PyCArray { pub(super) typ: PyRwLock, pub(super) length: AtomicCell, diff --git a/vm/src/stdlib/ctypes/base.rs b/vm/src/stdlib/ctypes/base.rs index 6cc19be3df..f32463b606 100644 --- a/vm/src/stdlib/ctypes/base.rs +++ b/vm/src/stdlib/ctypes/base.rs @@ -1,4 +1,3 @@ -use super::array::{PyCArray, PyCArrayType}; use crate::builtins::PyType; use crate::builtins::{PyBytes, PyFloat, PyInt, PyNone, PyStr, PyTypeRef}; use crate::convert::ToPyObject; @@ -143,6 +142,7 @@ fn set_primitive(_type_: &str, value: &PyObjectRef, vm: &VirtualMachine) -> PyRe } } +#[derive(Default)] pub struct RawBuffer { #[allow(dead_code)] pub inner: Box<[u8]>, @@ -151,15 +151,23 @@ pub struct RawBuffer { } #[pyclass(name = "_CData", module = "_ctypes")] +#[derive(Default)] pub struct PyCData { _objects: AtomicCell>, _buffer: PyRwLock, } +impl std::fmt::Debug for PyCData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PyCData").finish_non_exhaustive() + } +} + #[pyclass] impl PyCData {} -#[pyclass(module = "_ctypes", name = "PyCSimpleType", base = "PyType")] +#[pyclass(module = "_ctypes", name = "PyCSimpleType", base = PyType)] +#[derive(Debug)] pub struct PyCSimpleType {} #[pyclass(flags(BASETYPE))] @@ -178,10 +186,9 @@ impl PyCSimpleType { #[pyclass( module = "_ctypes", name = "_SimpleCData", - base = "PyCData", + base = PyCData, metaclass = "PyCSimpleType" )] -#[derive(PyPayload)] pub struct PyCSimple { pub _type_: String, pub value: AtomicCell, @@ -247,26 +254,6 @@ impl PyCSimple { zelf.value.store(content); Ok(()) } - - #[pyclassmethod] - fn repeat(cls: PyTypeRef, n: isize, vm: &VirtualMachine) -> PyResult { - if n < 0 { - return Err(vm.new_value_error(format!("Array length must be >= 0, not {}", n))); - } - Ok(PyCArrayType { - inner: PyCArray { - typ: PyRwLock::new(cls), - length: AtomicCell::new(n as usize), - value: PyRwLock::new(vm.ctx.none()), - }, - } - .to_pyobject(vm)) - } - - #[pyclassmethod(magic)] - fn mul(cls: PyTypeRef, n: isize, vm: &VirtualMachine) -> PyResult { - PyCSimple::repeat(cls, n, vm) - } } impl PyCSimple { diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 21043da27d..4b35a95bfc 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -125,8 +125,8 @@ impl Function { } } -#[pyclass(module = "_ctypes", name = "CFuncPtr", base = "PyCData")] -#[derive(PyPayload)] +#[pyclass(module = "_ctypes", name = "CFuncPtr", base = PyCData)] +#[derive()] pub struct PyCFuncPtr { pub name: PyRwLock, pub _flags_: AtomicCell, diff --git a/vm/src/stdlib/ctypes/pointer.rs b/vm/src/stdlib/ctypes/pointer.rs index d1360f9862..c79bb1f4fb 100644 --- a/vm/src/stdlib/ctypes/pointer.rs +++ b/vm/src/stdlib/ctypes/pointer.rs @@ -1,4 +1,5 @@ #[pyclass(name = "Pointer", module = "_ctypes")] +#[derive(Debug)] pub struct PyCPointer {} #[pyclass(flags(BASETYPE, IMMUTABLETYPE))] diff --git a/vm/src/stdlib/ctypes/structure.rs b/vm/src/stdlib/ctypes/structure.rs index 10c1fa3df8..4c700e3a08 100644 --- a/vm/src/stdlib/ctypes/structure.rs +++ b/vm/src/stdlib/ctypes/structure.rs @@ -2,14 +2,14 @@ use super::base::PyCData; use crate::builtins::{PyList, PyStr, PyTuple, PyTypeRef}; use crate::function::FuncArgs; use crate::types::GetAttr; -use crate::{AsObject, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine}; +use crate::{AsObject, Py, PyObjectRef, PyResult, VirtualMachine}; use rustpython_common::lock::PyRwLock; use rustpython_vm::types::Constructor; use std::collections::HashMap; use std::fmt::Debug; -#[pyclass(module = "_ctypes", name = "Structure", base = "PyCData")] -#[derive(PyPayload, Debug)] +#[pyclass(module = "_ctypes", name = "Structure", base = PyCData)] +#[derive(Debug)] pub struct PyCStructure { #[allow(dead_code)] field_data: PyRwLock>, diff --git a/vm/src/stdlib/ctypes/union.rs b/vm/src/stdlib/ctypes/union.rs index 2d76dbc9ca..37728677f1 100644 --- a/vm/src/stdlib/ctypes/union.rs +++ b/vm/src/stdlib/ctypes/union.rs @@ -1,7 +1,8 @@ use super::base::PyCData; // TODO: metaclass = "UnionType" -#[pyclass(module = "_ctypes", name = "Union", base = "PyCData")] +#[pyclass(module = "_ctypes", name = "Union", base = PyCData)] +#[derive(Debug)] pub struct PyCUnion {} #[pyclass(flags(BASETYPE, IMMUTABLETYPE))] diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 3e1979e3d0..0e50eecca7 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -392,7 +392,7 @@ mod _io { #[pyattr] #[pyclass(name = "_IOBase")] - #[derive(Debug, PyPayload)] + #[derive(Debug, Default)] pub struct _IOBase; #[pyclass(with(IterNext, Iterable, Destructor), flags(BASETYPE, HAS_DICT))] @@ -600,7 +600,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "_RawIOBase", base = "_IOBase")] + #[pyclass(name = "_RawIOBase", base = _IOBase)] + #[derive(Debug, Default)] pub(super) struct _RawIOBase; #[pyclass(flags(BASETYPE, HAS_DICT))] @@ -658,7 +659,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "_BufferedIOBase", base = "_IOBase")] + #[pyclass(name = "_BufferedIOBase", base = _IOBase)] + #[derive(Default, Debug)] struct _BufferedIOBase; #[pyclass(flags(BASETYPE))] @@ -716,8 +718,8 @@ mod _io { // TextIO Base has no public constructor #[pyattr] - #[pyclass(name = "_TextIOBase", base = "_IOBase")] - #[derive(Debug, PyPayload)] + #[pyclass(name = "_TextIOBase", base = _IOBase)] + #[derive(Debug, Default)] struct _TextIOBase; #[pyclass(flags(BASETYPE))] @@ -1690,8 +1692,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "BufferedReader", base = "_BufferedIOBase")] - #[derive(Debug, Default, PyPayload)] + #[pyclass(name = "BufferedReader", base = _BufferedIOBase)] + #[derive(Debug, Default)] struct BufferedReader { data: PyThreadMutex, } @@ -1740,8 +1742,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "BufferedWriter", base = "_BufferedIOBase")] - #[derive(Debug, Default, PyPayload)] + #[pyclass(name = "BufferedWriter", base = _BufferedIOBase)] + #[derive(Debug, Default)] struct BufferedWriter { data: PyThreadMutex, } @@ -1769,8 +1771,8 @@ mod _io { impl DefaultConstructor for BufferedWriter {} #[pyattr] - #[pyclass(name = "BufferedRandom", base = "_BufferedIOBase")] - #[derive(Debug, Default, PyPayload)] + #[pyclass(name = "BufferedRandom", base = _BufferedIOBase)] + #[derive(Debug, Default)] struct BufferedRandom { data: PyThreadMutex, } @@ -1805,8 +1807,8 @@ mod _io { impl DefaultConstructor for BufferedRandom {} #[pyattr] - #[pyclass(name = "BufferedRWPair", base = "_BufferedIOBase")] - #[derive(Debug, Default, PyPayload)] + #[pyclass(name = "BufferedRWPair", base = _BufferedIOBase)] + #[derive(Debug, Default)] struct BufferedRWPair { read: BufferedReader, write: BufferedWriter, @@ -2205,8 +2207,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "TextIOWrapper", base = "_TextIOBase")] - #[derive(Debug, Default, PyPayload)] + #[pyclass(name = "TextIOWrapper", base = _TextIOBase)] + #[derive(Debug, Default)] struct TextIOWrapper { data: PyThreadMutex>, } @@ -3157,7 +3159,7 @@ mod _io { #[pyattr] #[pyclass(name)] - #[derive(Debug, PyPayload, Default)] + #[derive(Debug, Default)] struct IncrementalNewlineDecoder { // TODO: Traverse data: PyThreadMutex>, @@ -3382,8 +3384,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "StringIO", base = "_TextIOBase")] - #[derive(Debug, PyPayload)] + #[pyclass(name = "StringIO", base = _TextIOBase)] + #[derive(Debug)] struct StringIO { buffer: PyRwLock, closed: AtomicCell, @@ -3522,8 +3524,8 @@ mod _io { } #[pyattr] - #[pyclass(name = "BytesIO", base = "_BufferedIOBase")] - #[derive(Debug, PyPayload)] + #[pyclass(name = "BytesIO", base = _BufferedIOBase)] + #[derive(Debug)] struct BytesIO { buffer: PyRwLock, closed: AtomicCell, @@ -4150,8 +4152,8 @@ mod fileio { } #[pyattr] - #[pyclass(module = "io", name, base = "_RawIOBase")] - #[derive(Debug, PyPayload)] + #[pyclass(module = "io", name, base = _RawIOBase)] + #[derive(Debug)] pub(super) struct FileIO { fd: AtomicCell, closefd: AtomicCell, diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index addfc991ff..bfcf88478e 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -30,7 +30,7 @@ mod decl { #[pyattr] #[pyclass(name = "chain")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsChain { source: PyRwLock>, active: PyRwLock>, @@ -167,7 +167,7 @@ mod decl { #[pyattr] #[pyclass(name = "compress")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsCompress { data: PyIter, selectors: PyIter, @@ -227,7 +227,7 @@ mod decl { #[pyattr] #[pyclass(name = "count")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsCount { cur: PyRwLock, step: PyObjectRef, @@ -302,7 +302,7 @@ mod decl { #[pyattr] #[pyclass(name = "cycle")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsCycle { iter: PyIter, saved: PyRwLock>, @@ -354,7 +354,7 @@ mod decl { #[pyattr] #[pyclass(name = "repeat")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsRepeat { object: PyObjectRef, times: Option>, @@ -440,7 +440,7 @@ mod decl { #[pyattr] #[pyclass(name = "starmap")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsStarmap { function: PyObjectRef, iterable: PyIter, @@ -497,7 +497,7 @@ mod decl { #[pyattr] #[pyclass(name = "takewhile")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsTakewhile { predicate: PyObjectRef, iterable: PyIter, @@ -580,7 +580,7 @@ mod decl { #[pyattr] #[pyclass(name = "dropwhile")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsDropwhile { predicate: ArgCallable, iterable: PyIter, @@ -690,7 +690,7 @@ mod decl { #[pyattr] #[pyclass(name = "groupby")] - #[derive(PyPayload)] + #[derive()] struct PyItertoolsGroupBy { iterable: PyIter, key_func: Option, @@ -810,7 +810,7 @@ mod decl { #[pyattr] #[pyclass(name = "_grouper")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsGrouper { groupby: PyRef, } @@ -855,7 +855,7 @@ mod decl { #[pyattr] #[pyclass(name = "islice")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsIslice { iterable: PyIter, cur: AtomicCell, @@ -1012,7 +1012,7 @@ mod decl { #[pyattr] #[pyclass(name = "filterfalse")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsFilterFalse { predicate: PyObjectRef, iterable: PyIter, @@ -1084,7 +1084,7 @@ mod decl { #[pyattr] #[pyclass(name = "accumulate")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsAccumulate { iterable: PyIter, bin_op: Option, @@ -1231,7 +1231,7 @@ mod decl { #[pyattr] #[pyclass(name = "tee")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsTee { tee_data: PyRc, index: AtomicCell, @@ -1309,7 +1309,7 @@ mod decl { #[pyattr] #[pyclass(name = "product")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsProduct { pools: Vec>, idxs: PyRwLock>, @@ -1460,7 +1460,7 @@ mod decl { #[pyattr] #[pyclass(name = "combinations")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsCombinations { pool: Vec, indices: PyRwLock>, @@ -1601,7 +1601,7 @@ mod decl { #[pyattr] #[pyclass(name = "combinations_with_replacement")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsCombinationsWithReplacement { pool: Vec, indices: PyRwLock>, @@ -1689,7 +1689,7 @@ mod decl { #[pyattr] #[pyclass(name = "permutations")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsPermutations { pool: Vec, // Collected input iterable indices: PyRwLock>, // One index per element in pool @@ -1855,7 +1855,7 @@ mod decl { #[pyattr] #[pyclass(name = "zip_longest")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsZipLongest { iterators: Vec, fillvalue: PyRwLock, @@ -1913,7 +1913,7 @@ mod decl { #[pyattr] #[pyclass(name = "pairwise")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsPairwise { iterator: PyIter, old: PyRwLock>, @@ -1957,7 +1957,7 @@ mod decl { #[pyattr] #[pyclass(name = "batched")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItertoolsBatched { exhausted: AtomicCell, iterable: PyIter, diff --git a/vm/src/stdlib/operator.rs b/vm/src/stdlib/operator.rs index fbb8147e9f..82ee015f7a 100644 --- a/vm/src/stdlib/operator.rs +++ b/vm/src/stdlib/operator.rs @@ -351,7 +351,7 @@ mod _operator { /// (r.name.first, r.name.last). #[pyattr] #[pyclass(name = "attrgetter")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyAttrGetter { attrs: Vec, } @@ -450,7 +450,7 @@ mod _operator { /// After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) #[pyattr] #[pyclass(name = "itemgetter")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyItemGetter { items: Vec, } @@ -520,7 +520,7 @@ mod _operator { /// r.name('date', foo=1). #[pyattr] #[pyclass(name = "methodcaller")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyMethodCaller { name: PyStrRef, args: FuncArgs, diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 08a5051fe7..7ca490623d 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -432,7 +432,7 @@ pub(super) mod _os { #[pyattr] #[pyclass(name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct DirEntry { file_name: std::ffi::OsString, pathval: PathBuf, @@ -623,7 +623,7 @@ pub(super) mod _os { #[pyattr] #[pyclass(name = "ScandirIter")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct ScandirIterator { entries: PyRwLock>, mode: OutputMode, diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index d75629745c..1be3d6e795 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -660,7 +660,7 @@ pub mod module { #[pyattr] #[pyclass(name = "sched_param")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct SchedParam { sched_priority: PyObjectRef, } diff --git a/vm/src/stdlib/sre.rs b/vm/src/stdlib/sre.rs index fdb48c7524..dce1b43db6 100644 --- a/vm/src/stdlib/sre.rs +++ b/vm/src/stdlib/sre.rs @@ -110,7 +110,7 @@ mod _sre { #[pyattr] #[pyclass(name = "SRE_Template")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Template { literal: PyObjectRef, items: Vec<(usize, PyObjectRef)>, @@ -187,7 +187,7 @@ mod _sre { #[pyattr] #[pyclass(name = "Pattern")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(crate) struct Pattern { pub pattern: PyObjectRef, pub flags: SreFlag, @@ -587,7 +587,7 @@ mod _sre { #[pyattr] #[pyclass(name = "Match")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub(crate) struct Match { string: PyObjectRef, pattern: PyRef, @@ -843,7 +843,7 @@ mod _sre { #[pyattr] #[pyclass(name = "SRE_Scanner")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct SreScanner { pattern: PyRef, string: PyObjectRef, diff --git a/vm/src/stdlib/symtable.rs b/vm/src/stdlib/symtable.rs index 7a575cb089..63a711c034 100644 --- a/vm/src/stdlib/symtable.rs +++ b/vm/src/stdlib/symtable.rs @@ -35,7 +35,7 @@ mod symtable { #[pyattr] #[pyclass(name = "SymbolTable")] - #[derive(PyPayload)] + #[derive()] struct PySymbolTable { symtable: SymbolTable, } @@ -149,7 +149,7 @@ mod symtable { #[pyattr] #[pyclass(name = "Symbol")] - #[derive(PyPayload)] + #[derive()] struct PySymbol { symbol: Symbol, namespaces: Vec, diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index b3e345b20a..042c9592a8 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -109,7 +109,7 @@ pub(crate) mod _thread { #[pyattr(name = "LockType")] #[pyclass(module = "thread", name = "lock")] - #[derive(PyPayload)] + #[derive()] struct Lock { mu: RawMutex, } @@ -186,7 +186,7 @@ pub(crate) mod _thread { pub type RawRMutex = RawReentrantMutex; #[pyattr] #[pyclass(module = "thread", name = "RLock")] - #[derive(PyPayload)] + #[derive()] struct RLock { mu: RawRMutex, } @@ -380,7 +380,7 @@ pub(crate) mod _thread { #[pyattr] #[pyclass(module = "thread", name = "_local")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Local { data: ThreadLocal, } diff --git a/vm/src/stdlib/typing.rs b/vm/src/stdlib/typing.rs index c266e811ca..5016254170 100644 --- a/vm/src/stdlib/typing.rs +++ b/vm/src/stdlib/typing.rs @@ -3,7 +3,7 @@ pub(crate) use _typing::make_module; #[pymodule] pub(crate) mod _typing { use crate::{ - PyObjectRef, PyPayload, PyResult, VirtualMachine, + PyObjectRef, PyResult, VirtualMachine, builtins::{PyGenericAlias, PyTupleRef, PyTypeRef, pystr::AsPyStr}, function::IntoFuncArgs, }; @@ -25,7 +25,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name = "TypeVar")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct TypeVar { name: PyObjectRef, // TODO PyStrRef? @@ -73,7 +73,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name = "ParamSpec")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct ParamSpec { name: PyObjectRef, @@ -88,7 +88,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name = "TypeVarTuple")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct TypeVarTuple { name: PyObjectRef, @@ -102,7 +102,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name = "ParamSpecArgs")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct ParamSpecArgs {} #[pyclass(flags(BASETYPE))] @@ -110,7 +110,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name = "ParamSpecKwargs")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct ParamSpecKwargs {} #[pyclass(flags(BASETYPE))] @@ -118,7 +118,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct TypeAliasType { name: PyObjectRef, // TODO PyStrRef? @@ -144,7 +144,7 @@ pub(crate) mod _typing { #[pyattr] #[pyclass(name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] #[allow(dead_code)] pub(crate) struct Generic {} diff --git a/vm/src/stdlib/winreg.rs b/vm/src/stdlib/winreg.rs index 8d1ca89ddd..c7bd18ffff 100644 --- a/vm/src/stdlib/winreg.rs +++ b/vm/src/stdlib/winreg.rs @@ -30,7 +30,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { mod winreg { use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::{ - PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, builtins::PyStrRef, + PyObjectRef, PyRef, PyResult, TryFromObject, VirtualMachine, builtins::PyStrRef, convert::ToPyException, }; use ::winreg::{RegKey, RegValue, enums::RegType}; @@ -59,7 +59,7 @@ mod winreg { #[pyattr] #[pyclass(module = "winreg", name = "HKEYType")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct PyHkey { key: PyRwLock, } diff --git a/vm/src/types/slot.rs b/vm/src/types/slot.rs index e2121973ec..b455996b45 100644 --- a/vm/src/types/slot.rs +++ b/vm/src/types/slot.rs @@ -8,6 +8,7 @@ use crate::{ Either, FromArgs, FuncArgs, OptionalArg, PyComparisonValue, PyMethodDef, PySetterValue, }, identifier, + object::{PyDefault, SuperPyDefault}, protocol::{ PyBuffer, PyIterReturn, PyMapping, PyMappingMethods, PyNumber, PyNumberMethods, PyNumberSlots, PySequence, PySequenceMethods, @@ -782,12 +783,12 @@ pub trait Constructor: PyPayload { fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult; } -pub trait DefaultConstructor: PyPayload + Default { +pub trait DefaultConstructor: PyPayload + PyDefault { fn construct_and_init(args: Self::Args, vm: &VirtualMachine) -> PyResult> where Self: Initializer, { - let this = Self::default().into_ref(&vm.ctx); + let this = Self::py_default(&vm.ctx).into_ref(&vm.ctx); Self::init(this.clone(), args, vm)?; Ok(this) } @@ -809,7 +810,9 @@ where type Args = FuncArgs; fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult { - Self::default().into_ref_with_type(vm, cls).map(Into::into) + Self::py_default(&vm.ctx) + .into_ref_with_type(vm, cls) + .map(Into::into) } fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/vm/context.rs b/vm/src/vm/context.rs index a61484e6bc..15e4ae487e 100644 --- a/vm/src/vm/context.rs +++ b/vm/src/vm/context.rs @@ -21,7 +21,7 @@ use crate::{ PyMethodFlags, }, intern::{InternableString, MaybeInternedString, StringPool}, - object::{Py, PyObjectPayload, PyObjectRef, PyPayload, PyRef}, + object::{Py, PyObjectRef, PyPayload, PyRef, SuperDefault}, types::{PyTypeFlags, PyTypeSlots, TypeZoo}, }; use malachite_bigint::BigInt; @@ -267,7 +267,7 @@ impl Context { let exceptions = exceptions::ExceptionZoo::init(); #[inline] - fn create_object( + fn create_object>( payload: T, cls: &'static Py, ) -> PyRef { @@ -364,7 +364,7 @@ impl Context { pub fn new_pyref(&self, value: T) -> PyRef

where T: Into

, - P: PyPayload, + P: PyPayload, { value.into().into_ref(self) } diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index 7baaae7770..1b3fec1e03 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -260,7 +260,7 @@ impl VirtualMachine { } fn import_utf8_encodings(&mut self) -> PyResult<()> { - import::import_frozen(self, "codecs")?; + thread::enter_vm(self, || import::import_frozen(self, "codecs"))?; // FIXME: See corresponding part of `core_frozen_inits` // let encoding_module_name = if cfg!(feature = "freeze-stdlib") { // "encodings.utf_8" diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index f8d1b2ebc3..7e4352fdd6 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -161,7 +161,7 @@ mod _browser { #[pyattr] #[pyclass(module = "browser", name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Document { doc: web_sys::Document, } @@ -193,7 +193,7 @@ mod _browser { #[pyattr] #[pyclass(module = "browser", name)] - #[derive(Debug, PyPayload)] + #[derive(Debug)] struct Element { elem: web_sys::Element, } diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index f159c467d0..d558dedd6f 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -56,7 +56,7 @@ mod _js { #[pyattr] #[pyclass(module = "_js", name = "JSValue")] - #[derive(Debug, PyPayload)] + #[derive(Debug)] pub struct PyJsValue { pub(crate) value: JsValue, } @@ -289,7 +289,7 @@ mod _js { #[pyattr] #[pyclass(module = "_js", name = "JSClosure")] - #[derive(PyPayload)] + #[derive()] struct JsClosure { closure: cell::RefCell>, destroyed: cell::Cell, @@ -384,7 +384,7 @@ mod _js { #[pyattr] #[pyclass(module = "_js", name = "Promise")] - #[derive(Debug, Clone, PyPayload)] + #[derive(Debug, Clone)] pub struct PyPromise { value: PromiseKind, } @@ -556,7 +556,7 @@ mod _js { } #[pyclass(no_attr, module = "_js", name = "AwaitPromise")] - #[derive(PyPayload)] + #[derive()] struct AwaitPromise { obj: cell::Cell>, }