@@ -12,7 +12,7 @@ use crate::{
1212 builtins:: { PyFloat , PyInt , PyStr } ,
1313 class:: PyClassImpl ,
1414 convert:: ToPyObject ,
15- function:: { ArgSize , FuncArgs , OptionalArg , PyComparisonValue } ,
15+ function:: { ArgSize , Either , FuncArgs , OptionalArg , PyComparisonValue } ,
1616 iter:: PyExactSizeIterator ,
1717 protocol:: { PyIterReturn , PyMappingMethods , PySequenceMethods } ,
1818 recursion:: ReprGuard ,
@@ -21,7 +21,7 @@ use crate::{
2121 sorting:: timsort,
2222 types:: {
2323 AsMapping , AsSequence , Comparable , Constructor , Initializer , IterNext , Iterable ,
24- PyComparisonOp , Representable , SelfIter ,
24+ PyComparisonOp , Representable , RichCompareFunc , SelfIter ,
2525 } ,
2626 vm:: VirtualMachine ,
2727} ;
@@ -639,6 +639,7 @@ enum PreSort {
639639 Str ,
640640 Int ,
641641 Float ,
642+ Object ( RichCompareFunc ) ,
642643 Generic ,
643644}
644645
@@ -659,6 +660,8 @@ fn pre_sort_check<'a>(
659660 PreSort :: Int
660661 } else if class. is ( vm. ctx . types . float_type ) {
661662 PreSort :: Float
663+ } else if let Some ( f) = class. slots . richcompare . load ( ) {
664+ PreSort :: Object ( f)
662665 } else {
663666 PreSort :: Generic
664667 }
@@ -676,6 +679,31 @@ fn float_lt(a: &PyObjectRef, b: &PyObjectRef) -> bool {
676679 a. downcast_ref :: < PyFloat > ( ) . unwrap ( ) . to_f64 ( ) < b. downcast_ref :: < PyFloat > ( ) . unwrap ( ) . to_f64 ( )
677680}
678681
682+ fn object_lt (
683+ cmp : RichCompareFunc ,
684+ a : & PyObjectRef ,
685+ b : & PyObjectRef ,
686+ vm : & VirtualMachine ,
687+ ) -> PyResult < bool > {
688+ #[ allow( unpredictable_function_pointer_comparisons) ]
689+ if a. class ( ) . slots . richcompare . load ( ) != Some ( cmp) {
690+ return a. rich_compare_bool ( b, PyComparisonOp :: Lt , vm) ;
691+ }
692+ match cmp ( a, b, PyComparisonOp :: Lt , vm) ? {
693+ Either :: B ( PyComparisonValue :: Implemented ( v) ) => Ok ( v) ,
694+ Either :: B ( PyComparisonValue :: NotImplemented ) => {
695+ a. rich_compare_bool ( b, PyComparisonOp :: Lt , vm)
696+ }
697+ Either :: A ( obj) => {
698+ if obj. is ( & vm. ctx . not_implemented ) {
699+ a. rich_compare_bool ( b, PyComparisonOp :: Lt , vm)
700+ } else {
701+ obj. try_to_bool ( vm)
702+ }
703+ }
704+ }
705+ }
706+
679707fn timsort_specialized < T , K > (
680708 vm : & VirtualMachine ,
681709 items : & mut [ T ] ,
@@ -711,6 +739,14 @@ where
711739 } ;
712740 Ok ( float_lt ( a, b) )
713741 } ) ,
742+ PreSort :: Object ( cmp) => timsort ( items, & mut |a, b| {
743+ let ( a, b) = if reverse {
744+ ( key ( b) , key ( a) )
745+ } else {
746+ ( key ( a) , key ( b) )
747+ } ;
748+ object_lt ( cmp, a, b, vm)
749+ } ) ,
714750 PreSort :: Generic => timsort ( items, & mut |a, b| {
715751 let ( a, b) = if reverse {
716752 ( key ( b) , key ( a) )
0 commit comments