@@ -26,6 +26,14 @@ pub struct PyFloat {
2626 value : f64 ,
2727}
2828
29+ impl < ' a > BorrowValue < ' a > for PyFloat {
30+ type Borrowed = & ' a f64 ;
31+
32+ fn borrow_value ( & ' a self ) -> Self :: Borrowed {
33+ & self . value
34+ }
35+ }
36+
2937impl PyFloat {
3038 pub fn to_f64 ( self ) -> f64 {
3139 self . value
@@ -55,11 +63,32 @@ impl From<f64> for PyFloat {
5563 }
5664}
5765
58- pub fn try_float ( obj : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < Option < f64 > > {
66+ pub ( crate ) fn try_float ( obj : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < Option < f64 > > {
67+ if let Some ( float) = obj. payload_if_exact :: < PyFloat > ( vm) {
68+ return Ok ( Some ( float. borrow_value ( ) . clone ( ) ) ) ;
69+ }
70+ if let Some ( method) = vm. get_method ( obj. clone ( ) , "__float__" ) {
71+ let result = vm. invoke ( & method?, ( ) ) ?;
72+ // TODO: returning strict subclasses of float in __float__ is deprecated
73+ return match result. payload :: < PyFloat > ( ) {
74+ Some ( float_obj) => Ok ( Some ( float_obj. borrow_value ( ) . clone ( ) ) ) ,
75+ None => Err ( vm. new_type_error ( format ! (
76+ "__float__ returned non-float (type '{}')" ,
77+ result. class( ) . name
78+ ) ) ) ,
79+ } ;
80+ }
81+ if let Some ( r) = vm. to_index_opt ( obj. clone ( ) ) . transpose ( ) ? {
82+ return Ok ( Some ( int:: to_float ( r. borrow_value ( ) , vm) ?) ) ;
83+ }
84+ Ok ( None )
85+ }
86+
87+ pub ( crate ) fn to_op_float ( obj : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < Option < f64 > > {
5988 let v = if let Some ( float) = obj. payload_if_subclass :: < PyFloat > ( vm) {
6089 Some ( float. value )
6190 } else if let Some ( int) = obj. payload_if_subclass :: < PyInt > ( vm) {
62- Some ( int:: try_float ( int. borrow_value ( ) , vm) ?)
91+ Some ( int:: to_float ( int. borrow_value ( ) , vm) ?)
6392 } else {
6493 None
6594 } ;
@@ -143,7 +172,7 @@ impl PyFloat {
143172 ) -> PyResult < PyRef < Self > > {
144173 let float_val = match arg {
145174 OptionalArg :: Present ( val) => {
146- if let Some ( f) = to_float ( vm , & val) ? {
175+ if let Some ( f) = try_float ( & val, vm ) ? {
147176 f
148177 } else if let Some ( s) = val. payload_if_subclass :: < PyStr > ( vm) {
149178 float_ops:: parse_str ( s. borrow_value ( ) . trim ( ) ) . ok_or_else ( || {
@@ -193,7 +222,7 @@ impl PyFloat {
193222 where
194223 F : Fn ( f64 , f64 ) -> PyResult < f64 > ,
195224 {
196- try_float ( & other, vm) ?. map_or_else (
225+ to_op_float ( & other, vm) ?. map_or_else (
197226 || Ok ( NotImplemented ) ,
198227 |other| Ok ( Implemented ( op ( self . value , other) ?) ) ,
199228 )
@@ -204,7 +233,7 @@ impl PyFloat {
204233 where
205234 F : Fn ( f64 , f64 ) -> PyResult ,
206235 {
207- try_float ( & other, vm) ?. map_or_else (
236+ to_op_float ( & other, vm) ?. map_or_else (
208237 || Ok ( vm. ctx . not_implemented ( ) ) ,
209238 |other| op ( self . value , other) ,
210239 )
@@ -511,22 +540,6 @@ impl Hashable for PyFloat {
511540 }
512541}
513542
514- fn to_float ( vm : & VirtualMachine , obj : & PyObjectRef ) -> PyResult < Option < f64 > > {
515- let value = if let Some ( float) = obj. payload_if_subclass :: < PyFloat > ( vm) {
516- float. value
517- } else if let Some ( int) = obj. payload_if_subclass :: < PyInt > ( vm) {
518- int:: try_float ( int. borrow_value ( ) , vm) ?
519- } else {
520- let method = match vm. get_method ( obj. clone ( ) , "__float__" ) {
521- Some ( x) => x?,
522- None => return Ok ( None ) ,
523- } ;
524- let result = vm. invoke ( & method, ( ) ) ?;
525- PyFloatRef :: try_from_object ( vm, result) ?. to_f64 ( )
526- } ;
527- Ok ( Some ( value) )
528- }
529-
530543pub type PyFloatRef = PyRef < PyFloat > ;
531544
532545// Retrieve inner float value:
@@ -556,7 +569,7 @@ impl IntoPyFloat {
556569
557570impl TryFromObject for IntoPyFloat {
558571 fn try_from_object ( vm : & VirtualMachine , obj : PyObjectRef ) -> PyResult < Self > {
559- let value = to_float ( vm , & obj) ?. ok_or_else ( || {
572+ let value = try_float ( & obj, vm ) ?. ok_or_else ( || {
560573 vm. new_type_error ( format ! ( "must be real number, not {}" , obj. class( ) . name) )
561574 } ) ?;
562575 Ok ( IntoPyFloat { value } )
0 commit comments