@@ -473,7 +473,7 @@ pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result<Tok
473473 ident,
474474 & class_name,
475475 module_name. as_deref ( ) ,
476- base,
476+ base. clone ( ) ,
477477 metaclass,
478478 unhashable,
479479 attrs,
@@ -528,19 +528,45 @@ pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result<Tok
528528 }
529529 } ;
530530
531- let impl_payload = if let Some ( ctx_type_name) = class_meta. ctx_name ( ) ? {
532- let ctx_type_ident = Ident :: new ( & ctx_type_name, ident. span ( ) ) ; // FIXME span
531+ // Generate PyPayload impl based on whether base exists
532+ let impl_payload = if let Some ( base_type) = & base {
533+ let class_fn = if let Some ( ctx_type_name) = class_meta. ctx_name ( ) ? {
534+ let ctx_type_ident = Ident :: new ( & ctx_type_name, ident. span ( ) ) ;
535+ quote ! { ctx. types. #ctx_type_ident }
536+ } else {
537+ quote ! { <Self as :: rustpython_vm:: class:: StaticType >:: static_type( ) }
538+ } ;
533539
534- // We need this to make extend mechanism work:
535540 quote ! {
536541 impl :: rustpython_vm:: PyPayload for #ident {
542+ #[ inline]
543+ fn payload_type_id( ) -> :: std:: any:: TypeId {
544+ <#base_type as :: rustpython_vm:: PyPayload >:: payload_type_id( )
545+ }
546+
547+ #[ inline]
548+ fn validate_downcastable_from( obj: & :: rustpython_vm:: PyObject ) -> bool {
549+ <Self as :: rustpython_vm:: class:: PyClassDef >:: BASICSIZE <= obj. class( ) . slots. basicsize && obj. class( ) . fast_issubclass( <Self as :: rustpython_vm:: class:: StaticType >:: static_type( ) )
550+ }
551+
537552 fn class( ctx: & :: rustpython_vm:: vm:: Context ) -> & ' static :: rustpython_vm:: Py <:: rustpython_vm:: builtins:: PyType > {
538- ctx . types . #ctx_type_ident
553+ #class_fn
539554 }
540555 }
541556 }
542557 } else {
543- quote ! { }
558+ if let Some ( ctx_type_name) = class_meta. ctx_name ( ) ? {
559+ let ctx_type_ident = Ident :: new ( & ctx_type_name, ident. span ( ) ) ;
560+ quote ! {
561+ impl :: rustpython_vm:: PyPayload for #ident {
562+ fn class( ctx: & :: rustpython_vm:: vm:: Context ) -> & ' static :: rustpython_vm:: Py <:: rustpython_vm:: builtins:: PyType > {
563+ ctx. types. #ctx_type_ident
564+ }
565+ }
566+ }
567+ } else {
568+ quote ! { }
569+ }
544570 } ;
545571
546572 let empty_impl = if let Some ( attrs) = class_meta. impl_attrs ( ) ? {
@@ -579,26 +605,6 @@ pub(crate) fn impl_pyexception(attr: PunctuatedNestedMeta, item: Item) -> Result
579605 let class_name = class_meta. class_name ( ) ?;
580606
581607 let base_class_name = class_meta. base ( ) ?;
582- let impl_payload = if let Some ( ctx_type_name) = class_meta. ctx_name ( ) ? {
583- let ctx_type_ident = Ident :: new ( & ctx_type_name, ident. span ( ) ) ; // FIXME span
584-
585- // We need this to make extend mechanism work:
586- quote ! {
587- impl :: rustpython_vm:: PyPayload for #ident {
588- fn class( ctx: & :: rustpython_vm:: vm:: Context ) -> & ' static :: rustpython_vm:: Py <:: rustpython_vm:: builtins:: PyType > {
589- ctx. exceptions. #ctx_type_ident
590- }
591- }
592- }
593- } else {
594- quote ! {
595- impl :: rustpython_vm:: PyPayload for #ident {
596- fn class( _ctx: & :: rustpython_vm:: vm:: Context ) -> & ' static :: rustpython_vm:: Py <:: rustpython_vm:: builtins:: PyType > {
597- <Self as :: rustpython_vm:: class:: StaticType >:: static_type( )
598- }
599- }
600- }
601- } ;
602608 let impl_pyclass = if class_meta. has_impl ( ) ? {
603609 quote ! {
604610 #[ pyexception]
@@ -611,7 +617,6 @@ pub(crate) fn impl_pyexception(attr: PunctuatedNestedMeta, item: Item) -> Result
611617 let ret = quote ! {
612618 #[ pyclass( module = false , name = #class_name, base = #base_class_name) ]
613619 #item
614- #impl_payload
615620 #impl_pyclass
616621 } ;
617622 Ok ( ret)
0 commit comments