@@ -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
0 commit comments