@@ -8,12 +8,19 @@ use crate::{
88 VirtualMachine ,
99} ;
1010use crossbeam_utils:: atomic:: AtomicCell ;
11- use once_cell:: sync:: OnceCell ;
1211
1312type UnaryFunc < R = PyObjectRef > = AtomicCell < Option < fn ( & PyNumber , & VirtualMachine ) -> PyResult < R > > > ;
1413type BinaryFunc < R = PyObjectRef > =
1514 AtomicCell < Option < fn ( & PyNumber , & PyObject , & VirtualMachine ) -> PyResult < R > > > ;
1615
16+
17+ impl PyObject {
18+ #[ inline]
19+ pub fn to_number ( & self ) -> PyNumber < ' _ > {
20+ PyNumber :: from ( self )
21+ }
22+ }
23+
1724#[ derive( Default ) ]
1825pub struct PyNumberMethods {
1926 /* Number implementations must check *both*
@@ -107,39 +114,36 @@ impl PyNumberMethods {
107114
108115pub struct PyNumber < ' a > {
109116 pub obj : & ' a PyObject ,
110- // some fast path do not need methods, so we do lazy initialize
111- methods : OnceCell < PointerSlot < PyNumberMethods > > ,
117+ methods : & ' a PyNumberMethods ,
112118}
113119
114120impl < ' a > From < & ' a PyObject > for PyNumber < ' a > {
115121 fn from ( obj : & ' a PyObject ) -> Self {
122+ static GLOBAL_NOT_IMPLEMENTED : PyNumberMethods = PyNumberMethods :: NOT_IMPLEMENTED ;
116123 Self {
117124 obj,
118- methods : OnceCell :: new ( ) ,
125+ methods : Self :: find_methods ( obj ) . map_or ( & GLOBAL_NOT_IMPLEMENTED , |m| unsafe { m . borrow_static ( ) } ) ,
119126 }
120127 }
121128}
122129
123130impl PyNumber < ' _ > {
124- pub fn methods ( & self ) -> & PyNumberMethods {
125- static GLOBAL_NOT_IMPLEMENTED : PyNumberMethods = PyNumberMethods :: NOT_IMPLEMENTED ;
126-
127- self . methods
128- . get_or_init ( || {
129- Self :: find_methods ( self . obj )
130- . unwrap_or_else ( || PointerSlot :: from ( & GLOBAL_NOT_IMPLEMENTED ) )
131- } )
132- . as_ref ( )
133- }
134-
135131 fn find_methods ( obj : & PyObject ) -> Option < PointerSlot < PyNumberMethods > > {
136132 obj. class ( ) . mro_find_map ( |x| x. slots . as_number . load ( ) )
137133 }
138134
135+ pub fn methods ( & self ) -> & PyNumberMethods {
136+ self . methods
137+ }
138+
139139 // PyNumber_Check
140140 pub fn check ( obj : & PyObject ) -> bool {
141- let num = PyNumber :: from ( obj) ;
142- let methods = num. methods ( ) ;
141+ let methods = if let Some ( m) = Self :: find_methods ( obj) {
142+ m
143+ } else {
144+ return false ;
145+ } ;
146+ let methods = methods. as_ref ( ) ;
143147 methods. int . load ( ) . is_some ( )
144148 || methods. index . load ( ) . is_some ( )
145149 || methods. float . load ( ) . is_some ( )
@@ -197,7 +201,7 @@ impl PyNumber<'_> {
197201 // vm,
198202 // )?;
199203 let ret = f. invoke ( ( ) , vm) ?;
200- PyNumber :: from ( ret. as_ref ( ) ) . index ( vm) . map_err ( |_| {
204+ ret. to_number ( ) . index ( vm) . map_err ( |_| {
201205 vm. new_type_error ( format ! (
202206 "__trunc__ returned non-Integral (type {})" ,
203207 ret. class( )
0 commit comments