@@ -139,7 +139,7 @@ impl Default for PyTypeFlags {
139139
140140pub ( crate ) type GenericMethod = fn ( & PyObject , FuncArgs , & VirtualMachine ) -> PyResult ;
141141pub ( crate ) type AsMappingFunc = fn ( & PyObject , & VirtualMachine ) -> & ' static PyMappingMethods ;
142- pub ( crate ) type AsNumberFunc = fn ( & PyObject , & VirtualMachine ) -> Cow < ' static , PyNumberMethods > ;
142+ pub ( crate ) type AsNumberFunc = fn ( & PyObject , & VirtualMachine ) -> & ' static PyNumberMethods ;
143143pub ( crate ) type HashFunc = fn ( & PyObject , & VirtualMachine ) -> PyResult < PyHash > ;
144144// CallFunc = GenericMethod
145145pub ( crate ) type GetattroFunc = fn ( & PyObject , PyStrRef , & VirtualMachine ) -> PyResult ;
@@ -340,43 +340,65 @@ fn as_sequence_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PySeque
340340 static_as_sequence_generic ( has_length, has_ass_item)
341341}
342342
343- fn as_number_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> Cow < ' static , PyNumberMethods > {
344- Cow :: Owned ( PyNumberMethods {
345- int : then_some_closure ! (
346- zelf. class( ) . has_attr( identifier!( vm, __int__) ) ,
347- |num, vm| {
348- let ret =
349- vm. call_special_method( num. obj. to_owned( ) , identifier!( vm, __int__) , ( ) ) ?;
350- ret. downcast:: <PyInt >( ) . map_err( |obj| {
351- vm. new_type_error( format!( "__int__ returned non-int (type {})" , obj. class( ) ) )
352- } )
353- }
354- ) ,
355- float : then_some_closure ! (
356- zelf. class( ) . has_attr( identifier!( vm, __float__) ) ,
357- |num, vm| {
358- let ret =
359- vm. call_special_method( num. obj. to_owned( ) , identifier!( vm, __float__) , ( ) ) ?;
360- ret. downcast:: <PyFloat >( ) . map_err( |obj| {
361- vm. new_type_error( format!(
362- "__float__ returned non-float (type {})" ,
363- obj. class( )
364- ) )
365- } )
366- }
367- ) ,
368- index : then_some_closure ! (
369- zelf. class( ) . has_attr( identifier!( vm, __index__) ) ,
370- |num, vm| {
371- let ret =
372- vm. call_special_method( num. obj. to_owned( ) , identifier!( vm, __index__) , ( ) ) ?;
373- ret. downcast:: <PyInt >( ) . map_err( |obj| {
374- vm. new_type_error( format!( "__index__ returned non-int (type {})" , obj. class( ) ) )
375- } )
376- }
377- ) ,
378- ..PyNumberMethods :: NOT_IMPLEMENTED
379- } )
343+ pub ( crate ) fn static_as_number_generic (
344+ has_int : bool ,
345+ has_float : bool ,
346+ has_index : bool ,
347+ ) -> & ' static PyNumberMethods {
348+ static METHODS : & [ PyNumberMethods ] = & [
349+ new_generic ( false , false , false ) ,
350+ new_generic ( true , false , false ) ,
351+ new_generic ( false , true , false ) ,
352+ new_generic ( true , true , false ) ,
353+ new_generic ( false , false , true ) ,
354+ new_generic ( true , false , true ) ,
355+ new_generic ( false , true , true ) ,
356+ new_generic ( true , true , true ) ,
357+ ] ;
358+
359+ fn int ( num : & PyNumber , vm : & VirtualMachine ) -> PyResult < PyRef < PyInt > > {
360+ let ret = vm. call_special_method ( num. obj . to_owned ( ) , identifier ! ( vm, __int__) , ( ) ) ?;
361+ ret. downcast :: < PyInt > ( ) . map_err ( |obj| {
362+ vm. new_type_error ( format ! ( "__int__ returned non-int (type {})" , obj. class( ) ) )
363+ } )
364+ }
365+ fn float ( num : & PyNumber , vm : & VirtualMachine ) -> PyResult < PyRef < PyFloat > > {
366+ let ret = vm. call_special_method ( num. obj . to_owned ( ) , identifier ! ( vm, __float__) , ( ) ) ?;
367+ ret. downcast :: < PyFloat > ( ) . map_err ( |obj| {
368+ vm. new_type_error ( format ! (
369+ "__float__ returned non-float (type {})" ,
370+ obj. class( )
371+ ) )
372+ } )
373+ }
374+ fn index ( num : & PyNumber , vm : & VirtualMachine ) -> PyResult < PyRef < PyInt > > {
375+ let ret = vm. call_special_method ( num. obj . to_owned ( ) , identifier ! ( vm, __index__) , ( ) ) ?;
376+ ret. downcast :: < PyInt > ( ) . map_err ( |obj| {
377+ vm. new_type_error ( format ! ( "__index__ returned non-int (type {})" , obj. class( ) ) )
378+ } )
379+ }
380+
381+ const fn new_generic ( has_int : bool , has_float : bool , has_index : bool ) -> PyNumberMethods {
382+ PyNumberMethods {
383+ int : if has_int { Some ( int) } else { None } ,
384+ float : if has_float { Some ( float) } else { None } ,
385+ index : if has_index { Some ( index) } else { None } ,
386+ ..PyNumberMethods :: NOT_IMPLEMENTED
387+ }
388+ }
389+
390+ let key = bool_int ( has_int) | ( bool_int ( has_float) << 1 ) | ( bool_int ( has_index) << 2 ) ;
391+
392+ & METHODS [ key]
393+ }
394+
395+ fn as_number_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> & ' static PyNumberMethods {
396+ let ( has_int, has_float, has_index) = (
397+ zelf. class ( ) . has_attr ( identifier ! ( vm, __int__) ) ,
398+ zelf. class ( ) . has_attr ( identifier ! ( vm, __float__) ) ,
399+ zelf. class ( ) . has_attr ( identifier ! ( vm, __index__) ) ,
400+ ) ;
401+ static_as_number_generic ( has_int, has_float, has_index)
380402}
381403
382404fn hash_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> PyResult < PyHash > {
@@ -1041,8 +1063,8 @@ pub trait AsNumber: PyPayload {
10411063
10421064 #[ inline]
10431065 #[ pyslot]
1044- fn as_number ( _zelf : & PyObject , _vm : & VirtualMachine ) -> Cow < ' static , PyNumberMethods > {
1045- Cow :: Borrowed ( & Self :: AS_NUMBER )
1066+ fn as_number ( _zelf : & PyObject , _vm : & VirtualMachine ) -> & ' static PyNumberMethods {
1067+ & Self :: AS_NUMBER
10461068 }
10471069
10481070 fn number_downcast < ' a > ( number : & ' a PyNumber ) -> & ' a Py < Self > {
0 commit comments