@@ -443,117 +443,140 @@ impl<'a> PyNumber<'a> {
443443
444444 // PyNumber_Check
445445 pub fn check ( obj : & PyObject ) -> bool {
446- let methods = & obj. class ( ) . slots . as_number ;
447- methods. int . load ( ) . is_some ( )
448- || methods. index . load ( ) . is_some ( )
449- || methods. float . load ( ) . is_some ( )
450- || obj. downcastable :: < PyComplex > ( )
446+ let cls = & obj. class ( ) ;
447+ // TODO: when we finally have a proper slot inheritance, mro_find_map can be removed
448+ // methods.int.load().is_some()
449+ // || methods.index.load().is_some()
450+ // || methods.float.load().is_some()
451+ // || obj.downcastable::<PyComplex>()
452+ let has_number = cls
453+ . mro_find_map ( |x| {
454+ let methods = & x. slots . as_number ;
455+ if methods. int . load ( ) . is_some ( )
456+ || methods. index . load ( ) . is_some ( )
457+ || methods. float . load ( ) . is_some ( )
458+ {
459+ Some ( ( ) )
460+ } else {
461+ None
462+ }
463+ } )
464+ . is_some ( ) ;
465+ has_number || obj. downcastable :: < PyComplex > ( )
451466 }
452467}
453468
454469impl PyNumber < ' _ > {
455470 // PyIndex_Check
456471 pub fn is_index ( self ) -> bool {
457- self . class ( ) . slots . as_number . index . load ( ) . is_some ( )
472+ self . class ( )
473+ . mro_find_map ( |x| x. slots . as_number . index . load ( ) )
474+ . is_some ( )
458475 }
459476
460477 #[ inline]
461478 pub fn int ( self , vm : & VirtualMachine ) -> Option < PyResult < PyIntRef > > {
462- self . class ( ) . slots . as_number . int . load ( ) . map ( |f| {
463- let ret = f ( self , vm) ?;
464-
465- if let Some ( ret) = ret. downcast_ref_if_exact :: < PyInt > ( vm) {
466- return Ok ( ret. to_owned ( ) ) ;
467- }
468-
469- let ret_class = ret. class ( ) . to_owned ( ) ;
470- if let Some ( ret) = ret. downcast_ref :: < PyInt > ( ) {
471- warnings:: warn (
472- vm. ctx . exceptions . deprecation_warning ,
473- format ! (
474- "__int__ returned non-int (type {ret_class}). \
479+ self . class ( )
480+ . mro_find_map ( |x| x. slots . as_number . int . load ( ) )
481+ . map ( |f| {
482+ let ret = f ( self , vm) ?;
483+
484+ if let Some ( ret) = ret. downcast_ref_if_exact :: < PyInt > ( vm) {
485+ return Ok ( ret. to_owned ( ) ) ;
486+ }
487+
488+ let ret_class = ret. class ( ) . to_owned ( ) ;
489+ if let Some ( ret) = ret. downcast_ref :: < PyInt > ( ) {
490+ warnings:: warn (
491+ vm. ctx . exceptions . deprecation_warning ,
492+ format ! (
493+ "__int__ returned non-int (type {ret_class}). \
475494 The ability to return an instance of a strict subclass of int \
476495 is deprecated, and may be removed in a future version of Python."
477- ) ,
478- 1 ,
479- vm,
480- ) ?;
481-
482- Ok ( ret. to_owned ( ) )
483- } else {
484- Err ( vm. new_type_error ( format ! (
485- "{}.__int__ returned non-int(type {})" ,
486- self . class( ) ,
487- ret_class
488- ) ) )
489- }
490- } )
496+ ) ,
497+ 1 ,
498+ vm,
499+ ) ?;
500+
501+ Ok ( ret. to_owned ( ) )
502+ } else {
503+ Err ( vm. new_type_error ( format ! (
504+ "{}.__int__ returned non-int(type {})" ,
505+ self . class( ) ,
506+ ret_class
507+ ) ) )
508+ }
509+ } )
491510 }
492511
493512 #[ inline]
494513 pub fn index ( self , vm : & VirtualMachine ) -> Option < PyResult < PyIntRef > > {
495- self . class ( ) . slots . as_number . index . load ( ) . map ( |f| {
496- let ret = f ( self , vm) ?;
497-
498- if let Some ( ret) = ret. downcast_ref_if_exact :: < PyInt > ( vm) {
499- return Ok ( ret. to_owned ( ) ) ;
500- }
501-
502- let ret_class = ret. class ( ) . to_owned ( ) ;
503- if let Some ( ret) = ret. downcast_ref :: < PyInt > ( ) {
504- warnings:: warn (
505- vm. ctx . exceptions . deprecation_warning ,
506- format ! (
507- "__index__ returned non-int (type {ret_class}). \
514+ self . class ( )
515+ . mro_find_map ( |x| x. slots . as_number . index . load ( ) )
516+ . map ( |f| {
517+ let ret = f ( self , vm) ?;
518+
519+ if let Some ( ret) = ret. downcast_ref_if_exact :: < PyInt > ( vm) {
520+ return Ok ( ret. to_owned ( ) ) ;
521+ }
522+
523+ let ret_class = ret. class ( ) . to_owned ( ) ;
524+ if let Some ( ret) = ret. downcast_ref :: < PyInt > ( ) {
525+ warnings:: warn (
526+ vm. ctx . exceptions . deprecation_warning ,
527+ format ! (
528+ "__index__ returned non-int (type {ret_class}). \
508529 The ability to return an instance of a strict subclass of int \
509530 is deprecated, and may be removed in a future version of Python."
510- ) ,
511- 1 ,
512- vm,
513- ) ?;
514-
515- Ok ( ret. to_owned ( ) )
516- } else {
517- Err ( vm. new_type_error ( format ! (
518- "{}.__index__ returned non-int(type {})" ,
519- self . class( ) ,
520- ret_class
521- ) ) )
522- }
523- } )
531+ ) ,
532+ 1 ,
533+ vm,
534+ ) ?;
535+
536+ Ok ( ret. to_owned ( ) )
537+ } else {
538+ Err ( vm. new_type_error ( format ! (
539+ "{}.__index__ returned non-int(type {})" ,
540+ self . class( ) ,
541+ ret_class
542+ ) ) )
543+ }
544+ } )
524545 }
525546
526547 #[ inline]
527548 pub fn float ( self , vm : & VirtualMachine ) -> Option < PyResult < PyRef < PyFloat > > > {
528- self . class ( ) . slots . as_number . float . load ( ) . map ( |f| {
529- let ret = f ( self , vm) ?;
530-
531- if let Some ( ret) = ret. downcast_ref_if_exact :: < PyFloat > ( vm) {
532- return Ok ( ret. to_owned ( ) ) ;
533- }
534-
535- let ret_class = ret. class ( ) . to_owned ( ) ;
536- if let Some ( ret) = ret. downcast_ref :: < PyFloat > ( ) {
537- warnings:: warn (
538- vm. ctx . exceptions . deprecation_warning ,
539- format ! (
540- "__float__ returned non-float (type {ret_class}). \
549+ self . class ( )
550+ . mro_find_map ( |x| x. slots . as_number . float . load ( ) )
551+ . map ( |f| {
552+ let ret = f ( self , vm) ?;
553+
554+ if let Some ( ret) = ret. downcast_ref_if_exact :: < PyFloat > ( vm) {
555+ return Ok ( ret. to_owned ( ) ) ;
556+ }
557+
558+ let ret_class = ret. class ( ) . to_owned ( ) ;
559+ if let Some ( ret) = ret. downcast_ref :: < PyFloat > ( ) {
560+ warnings:: warn (
561+ vm. ctx . exceptions . deprecation_warning ,
562+ format ! (
563+ "__float__ returned non-float (type {ret_class}). \
541564 The ability to return an instance of a strict subclass of float \
542565 is deprecated, and may be removed in a future version of Python."
543- ) ,
544- 1 ,
545- vm,
546- ) ?;
547-
548- Ok ( ret. to_owned ( ) )
549- } else {
550- Err ( vm. new_type_error ( format ! (
551- "{}.__float__ returned non-float(type {})" ,
552- self . class( ) ,
553- ret_class
554- ) ) )
555- }
556- } )
566+ ) ,
567+ 1 ,
568+ vm,
569+ ) ?;
570+
571+ Ok ( ret. to_owned ( ) )
572+ } else {
573+ Err ( vm. new_type_error ( format ! (
574+ "{}.__float__ returned non-float(type {})" ,
575+ self . class( ) ,
576+ ret_class
577+ ) ) )
578+ }
579+ } )
557580 }
558581}
559582
0 commit comments