Skip to content

Commit 88f591d

Browse files
committed
migrate to Initializer
1 parent 364756e commit 88f591d

File tree

6 files changed

+418
-335
lines changed

6 files changed

+418
-335
lines changed

crates/derive-impl/src/pyclass.rs

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -714,21 +714,16 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
714714
};
715715

716716
// Check if with(Constructor) is specified. If Constructor trait is used, don't generate slot_new
717-
let mut has_slot_new = false;
718-
719717
let mut extra_attrs = Vec::new();
718+
let mut with_items = vec![];
720719
for nested in &attr {
721720
if let NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) = nested {
722721
// If we already found the constructor trait, no need to keep looking for it
723-
if !has_slot_new && path.is_ident("with") {
724-
// Check if Constructor is in the list
722+
if path.is_ident("with") {
725723
for meta in nested {
726-
if let NestedMeta::Meta(Meta::Path(p)) = meta
727-
&& p.is_ident("Constructor")
728-
{
729-
has_slot_new = true;
730-
}
724+
with_items.push(meta.get_ident().expect("with() has non-ident item").clone());
731725
}
726+
continue;
732727
}
733728
extra_attrs.push(NestedMeta::Meta(Meta::List(MetaList {
734729
path: path.clone(),
@@ -738,43 +733,45 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
738733
}
739734
}
740735

741-
let mut has_slot_init = false;
736+
let with_contains = |with_items: &[Ident], s: &str| {
737+
// Check if Constructor is in the list
738+
for ident in with_items {
739+
if ident.to_string().as_str() == s {
740+
return true;
741+
}
742+
}
743+
false
744+
};
745+
742746
let syn::ItemImpl {
743747
generics,
744748
self_ty,
745749
items,
746750
..
747751
} = &imp;
748-
for item in items {
749-
// FIXME: better detection or correct wrapper implementation
750-
let Some(ident) = item.get_ident() else {
751-
continue;
752-
};
753-
let item_name = ident.to_string();
754-
match item_name.as_str() {
755-
"slot_new" => {
756-
has_slot_new = true;
757-
}
758-
"slot_init" => {
759-
has_slot_init = true;
760-
}
761-
_ => continue,
762-
}
763-
}
764752

765-
// TODO: slot_new, slot_init must be Constructor or Initializer later
766-
767-
let slot_new = if has_slot_new {
753+
let slot_new = if with_contains(&with_items, "Constructor") {
768754
quote!()
769755
} else {
756+
with_items.push(Ident::new("Constructor", Span::call_site()));
770757
quote! {
771-
#[pyslot]
772-
pub fn slot_new(
773-
cls: ::rustpython_vm::builtins::PyTypeRef,
774-
args: ::rustpython_vm::function::FuncArgs,
775-
vm: &::rustpython_vm::VirtualMachine,
776-
) -> ::rustpython_vm::PyResult {
777-
<Self as ::rustpython_vm::class::PyClassDef>::Base::slot_new(cls, args, vm)
758+
impl ::rustpython_vm::types::Constructor for #self_ty {
759+
type Args = ::rustpython_vm::function::FuncArgs;
760+
761+
fn slot_new(
762+
cls: ::rustpython_vm::builtins::PyTypeRef,
763+
args: ::rustpython_vm::function::FuncArgs,
764+
vm: &::rustpython_vm::VirtualMachine,
765+
) -> ::rustpython_vm::PyResult {
766+
<Self as ::rustpython_vm::class::PyClassDef>::Base::slot_new(cls, args, vm)
767+
}
768+
fn py_new(
769+
_cls: &::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
770+
_args: Self::Args,
771+
_vm: &VirtualMachine
772+
) -> PyResult<Self> {
773+
unreachable!("slot_new is defined")
774+
}
778775
}
779776
}
780777
};
@@ -783,19 +780,29 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
783780
// from `BaseException` in `SimpleExtendsException` macro.
784781
// See: `(initproc)BaseException_init`
785782
// spell-checker:ignore initproc
786-
let slot_init = if has_slot_init {
783+
let slot_init = if with_contains(&with_items, "Initializer") {
787784
quote!()
788785
} else {
789-
// FIXME: this is a generic logic for types not only for exceptions
786+
with_items.push(Ident::new("Initializer", Span::call_site()));
790787
quote! {
791-
#[pyslot]
792-
#[pymethod(name="__init__")]
793-
pub fn slot_init(
794-
zelf: ::rustpython_vm::PyObjectRef,
795-
args: ::rustpython_vm::function::FuncArgs,
796-
vm: &::rustpython_vm::VirtualMachine,
797-
) -> ::rustpython_vm::PyResult<()> {
798-
<Self as ::rustpython_vm::class::PyClassDef>::Base::slot_init(zelf, args, vm)
788+
impl ::rustpython_vm::types::Initializer for #self_ty {
789+
type Args = ::rustpython_vm::function::FuncArgs;
790+
791+
fn slot_init(
792+
zelf: ::rustpython_vm::PyObjectRef,
793+
args: ::rustpython_vm::function::FuncArgs,
794+
vm: &::rustpython_vm::VirtualMachine,
795+
) -> PyResult<()> {
796+
<Self as ::rustpython_vm::class::PyClassDef>::Base::slot_init(zelf, args, vm)
797+
}
798+
799+
fn init(
800+
_zelf: ::rustpython_vm::PyRef<Self>,
801+
_args: Self::Args,
802+
_vm: &VirtualMachine
803+
) -> PyResult<()> {
804+
unreachable!("slot_init is defined")
805+
}
799806
}
800807
}
801808
};
@@ -807,13 +814,13 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
807814
};
808815

809816
Ok(quote! {
810-
#[pyclass(flags(BASETYPE, HAS_DICT) #extra_attrs_tokens)]
817+
#[pyclass(flags(BASETYPE, HAS_DICT), with(#(#with_items),*) #extra_attrs_tokens)]
811818
impl #generics #self_ty {
812819
#(#items)*
813-
814-
#slot_new
815-
#slot_init
816820
}
821+
822+
#slot_new
823+
#slot_init
817824
})
818825
}
819826

crates/stdlib/src/ssl/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(crate) mod ssl_error {
77
use crate::vm::{
88
PyPayload, PyRef, PyResult, VirtualMachine,
99
builtins::{PyBaseExceptionRef, PyOSError, PyStrRef},
10-
types::Constructor,
10+
types::{Constructor, Initializer},
1111
};
1212

1313
// Error type constants - exposed as pyattr and available for internal use

crates/vm/src/builtins/object.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use super::{PyDictRef, PyList, PyStr, PyStrRef, PyType, PyTypeRef};
22
use crate::common::hash::PyHash;
33
use crate::types::PyTypeFlags;
44
use crate::{
5-
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
5+
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
66
class::PyClassImpl,
77
convert::ToPyResult,
88
function::{Either, FuncArgs, PyArithmeticValue, PyComparisonValue, PySetterValue},
9-
types::{Constructor, PyComparisonOp},
9+
types::{Constructor, Initializer, PyComparisonOp},
1010
};
1111
use itertools::Itertools;
1212

@@ -115,6 +115,18 @@ impl Constructor for PyBaseObject {
115115
}
116116
}
117117

118+
impl Initializer for PyBaseObject {
119+
type Args = FuncArgs;
120+
121+
fn slot_init(_zelf: PyObjectRef, _args: FuncArgs, _vm: &VirtualMachine) -> PyResult<()> {
122+
Ok(())
123+
}
124+
125+
fn init(_zelf: PyRef<Self>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<()> {
126+
unreachable!("slot_init is defined")
127+
}
128+
}
129+
118130
// TODO: implement _PyType_GetSlotNames properly
119131
fn type_slot_names(typ: &Py<PyType>, vm: &VirtualMachine) -> PyResult<Option<super::PyListRef>> {
120132
// let attributes = typ.attributes.read();
@@ -235,7 +247,7 @@ fn object_getstate_default(obj: &PyObject, required: bool, vm: &VirtualMachine)
235247
// getstate.call((), vm)
236248
// }
237249

238-
#[pyclass(with(Constructor), flags(BASETYPE))]
250+
#[pyclass(with(Constructor, Initializer), flags(BASETYPE))]
239251
impl PyBaseObject {
240252
#[pymethod(raw)]
241253
fn __getstate__(vm: &VirtualMachine, args: FuncArgs) -> PyResult {
@@ -444,19 +456,17 @@ impl PyBaseObject {
444456
obj.str(vm)
445457
}
446458

447-
#[pyslot]
448-
#[pymethod]
449-
fn __init__(_zelf: PyObjectRef, _args: FuncArgs, _vm: &VirtualMachine) -> PyResult<()> {
450-
Ok(())
451-
}
452-
453459
#[pygetset]
454460
fn __class__(obj: PyObjectRef) -> PyTypeRef {
455461
obj.class().to_owned()
456462
}
457463

458-
#[pygetset(name = "__class__", setter)]
459-
fn set_class(instance: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
464+
#[pygetset(setter)]
465+
fn set___class__(
466+
instance: PyObjectRef,
467+
value: PyObjectRef,
468+
vm: &VirtualMachine,
469+
) -> PyResult<()> {
460470
match value.downcast::<PyType>() {
461471
Ok(cls) => {
462472
let both_module = instance.class().fast_issubclass(vm.ctx.types.module_type)

0 commit comments

Comments
 (0)