@@ -774,7 +774,9 @@ public static object Index(object? o) {
774774 throw TypeError ( "'{0}' object cannot be interpreted as an integer" , PythonTypeOps . GetName ( o ) ) ;
775775 }
776776
777- internal static bool TryToIndex ( object ? o , [ NotNullWhen ( true ) ] out object ? index ) {
777+ internal static bool TryToIndex ( object ? o , [ NotNullWhen ( true ) ] out object ? index ) {
778+ var context = DefaultContext . Default ;
779+
778780 switch ( o ) {
779781 case int i :
780782 index = Int32Ops . __index__ ( i ) ;
@@ -807,26 +809,42 @@ internal static bool TryToIndex(object? o, [NotNullWhen(true)]out object? index)
807809 break ;
808810 }
809811
810- if ( PythonTypeOps . TryInvokeUnaryOperator ( DefaultContext . Default , o , "__index__" , out index ) ) {
811- if ( ! ( index is int ) && ! ( index is BigInteger ) )
812- throw TypeError ( "__index__ returned non-int (type {0})" , PythonTypeOps . GetName ( index ) ) ;
813- return true ;
812+ if ( PythonTypeOps . TryInvokeUnaryOperator ( context , o , "__index__" , out index ) ) {
813+ if ( index is int || index is BigInteger )
814+ return true ;
815+ if ( index is Extensible < int > || index is Extensible < BigInteger > ) {
816+ Warn ( context , PythonExceptions . DeprecationWarning , $ "__index__ returned non-int (type { PythonTypeOps . GetName ( index ) } ). The ability to return an instance of a strict subclass of int is deprecated, and may be removed in a future version of Python.") ;
817+ return true ;
818+ }
819+ throw TypeError ( "__index__ returned non-int (type {0})" , PythonTypeOps . GetName ( index ) ) ;
814820 }
815821
816822 index = default ;
817823 return false ;
818824 }
819825
820- private static bool ObjectToInt ( object o , out int res , out BigInteger longRes ) {
821- if ( o is BigInteger bi ) {
822- if ( ! bi . AsInt32 ( out res ) ) {
823- longRes = bi ;
824- return false ;
825- }
826- } else if ( o is int i ) {
827- res = i ;
828- } else {
829- res = Converter . ConvertToInt32 ( o ) ;
826+ private static bool IndexObjectToInt ( object o , out int res , out BigInteger longRes ) {
827+ switch ( o ) {
828+ case int i :
829+ res = i ;
830+ break ;
831+ case Extensible < int > ei : // deprecated
832+ res = ei ;
833+ break ;
834+ case BigInteger bi :
835+ if ( ! bi . AsInt32 ( out res ) ) {
836+ longRes = bi ;
837+ return false ;
838+ }
839+ break ;
840+ case Extensible < BigInteger > ebi : // deprecated
841+ if ( ! ebi . Value . AsInt32 ( out res ) ) {
842+ longRes = ebi ;
843+ return false ;
844+ }
845+ break ;
846+ default :
847+ throw new InvalidOperationException ( ) ;
830848 }
831849
832850 longRes = default ;
@@ -848,7 +866,9 @@ internal static bool Length(object? o, out int res, out BigInteger bigRes) {
848866
849867 object len = PythonContext . InvokeUnaryOperator ( DefaultContext . Default , UnaryOperators . Length , o , $ "object of type '{ GetPythonTypeName ( o ) } ' has no len()") ;
850868
851- if ( ObjectToInt ( len , out res , out bigRes ) ) {
869+ var indexObj = Index ( len ) ;
870+
871+ if ( IndexObjectToInt ( indexObj , out res , out bigRes ) ) {
852872 if ( res < 0 ) throw ValueError ( "__len__() should return >= 0" ) ;
853873 return true ;
854874 } else {
0 commit comments