@@ -462,26 +462,26 @@ impl PyObject {
462462 }
463463
464464 fn recursive_issubclass ( & self , cls : & PyObject , vm : & VirtualMachine ) -> PyResult < bool > {
465- if let ( Ok ( obj) , Ok ( cls) ) = ( self . try_to_ref :: < PyType > ( vm) , cls. try_to_ref :: < PyType > ( vm) ) {
466- Ok ( obj. fast_issubclass ( cls) )
467- } else {
468- // Check if derived is a class
469- self . check_class ( vm, || {
470- format ! ( "issubclass() arg 1 must be a class, not {}" , self . class( ) )
471- } ) ?;
472-
473- // Check if cls is a class, tuple, or union
474- if !cls. class ( ) . is ( vm. ctx . types . union_type ) {
475- cls. check_class ( vm, || {
476- format ! (
477- "issubclass() arg 2 must be a class, a tuple of classes, or a union, not {}" ,
478- cls. class( )
479- )
480- } ) ?;
481- }
465+ // Fast path for both being types (matches CPython's PyType_Check)
466+ if let Some ( cls) = PyType :: check ( cls)
467+ && let Some ( derived) = PyType :: check ( self )
468+ {
469+ // PyType_IsSubtype equivalent
470+ return Ok ( derived. is_subtype ( cls) ) ;
471+ }
472+ // Check if derived is a class
473+ self . check_class ( vm, || {
474+ format ! ( "issubclass() arg 1 must be a class, not {}" , self . class( ) )
475+ } ) ?;
482476
483- self . abstract_issubclass ( cls, vm)
477+ // Check if cls is a class, tuple, or union (matches CPython's order and message)
478+ if !cls. class ( ) . is ( vm. ctx . types . union_type ) {
479+ cls. check_class ( vm, || {
480+ "issubclass() arg 2 must be a class, a tuple of classes, or a union" . to_string ( )
481+ } ) ?;
484482 }
483+
484+ self . abstract_issubclass ( cls, vm)
485485 }
486486
487487 /// Real issubclass check without going through __subclasscheck__
0 commit comments