44use crate :: {
55 AsObject , Py , PyObject , PyObjectRef , PyRef , PyResult , TryFromObject , VirtualMachine ,
66 builtins:: {
7- PyBaseObject , PyBytes , PyDict , PyDictRef , PyGenericAlias , PyInt , PyList , PyStr , PyTuple ,
8- PyTupleRef , PyType , PyTypeRef , PyUtf8Str , pystr:: AsPyStr ,
7+ PyBytes , PyDict , PyDictRef , PyGenericAlias , PyInt , PyList , PyStr , PyTuple , PyTupleRef ,
8+ PyType , PyTypeRef , PyUtf8Str , pystr:: AsPyStr ,
99 } ,
1010 common:: { hash:: PyHash , str:: to_ascii} ,
1111 convert:: { ToPyObject , ToPyResult } ,
@@ -580,18 +580,13 @@ impl PyObject {
580580 if let Ok ( cls) = cls. try_to_ref :: < PyType > ( vm) {
581581 // PyType_Check(cls) - cls is a type object
582582 let mut retval = self . class ( ) . is_subtype ( cls) ;
583- if !retval {
584- // __class__ is a data descriptor on object that always returns
585- // obj.class() under standard __getattribute__. Only do the
586- // expensive attribute lookup when getattro is overridden.
587- if !self . has_standard_getattro ( )
588- && let Some ( i_cls) =
589- vm. get_attribute_opt ( self . to_owned ( ) , identifier ! ( vm, __class__) ) ?
590- && let Ok ( i_cls_type) = PyTypeRef :: try_from_object ( vm, i_cls)
591- && !i_cls_type. is ( self . class ( ) )
592- {
593- retval = i_cls_type. is_subtype ( cls) ;
594- }
583+ if !retval
584+ && let Some ( i_cls) =
585+ vm. get_attribute_opt ( self . to_owned ( ) , identifier ! ( vm, __class__) ) ?
586+ && let Ok ( i_cls_type) = PyTypeRef :: try_from_object ( vm, i_cls)
587+ && !i_cls_type. is ( self . class ( ) )
588+ {
589+ retval = i_cls_type. is_subtype ( cls) ;
595590 }
596591 Ok ( retval)
597592 } else {
@@ -603,15 +598,13 @@ impl PyObject {
603598 )
604599 } ) ?;
605600
606- let i_cls: PyObjectRef = if self . has_standard_getattro ( ) {
607- self . class ( ) . to_owned ( ) . into ( )
601+ if let Some ( i_cls) =
602+ vm. get_attribute_opt ( self . to_owned ( ) , identifier ! ( vm, __class__) ) ?
603+ {
604+ i_cls. abstract_issubclass ( cls, vm)
608605 } else {
609- match vm. get_attribute_opt ( self . to_owned ( ) , identifier ! ( vm, __class__) ) ? {
610- Some ( cls) => cls,
611- None => return Ok ( false ) ,
612- }
613- } ;
614- i_cls. abstract_issubclass ( cls, vm)
606+ Ok ( false )
607+ }
615608 }
616609 }
617610
@@ -789,15 +782,6 @@ impl PyObject {
789782 Err ( vm. new_type_error ( format ! ( "'{}' does not support item deletion" , self . class( ) ) ) )
790783 }
791784
792- /// Returns true if the object uses the standard `__getattribute__`
793- /// (i.e. `object.__getattribute__`), meaning attribute access follows
794- /// the normal descriptor protocol without custom interception.
795- #[ inline]
796- fn has_standard_getattro ( & self ) -> bool {
797- let getattro = self . class ( ) . slots . getattro . load ( ) . unwrap ( ) ;
798- getattro as usize == PyBaseObject :: getattro as * const ( ) as usize
799- }
800-
801785 /// Equivalent to CPython's _PyObject_LookupSpecial
802786 /// Looks up a special method in the type's MRO without checking instance dict.
803787 /// Returns None if not found (masking AttributeError like CPython).
0 commit comments