@@ -8,6 +8,7 @@ use crate::{
88 function:: {
99 Callee , FuncArgs , ItemDoc , PyMethodDef , PyMethodFlags , PySetterValue , PySsize , plain_doc,
1010 } ,
11+ object:: { Traverse , TraverseFn } ,
1112 protocol:: { PyNumberBinaryFunc , PyNumberTernaryFunc , PyNumberUnaryFunc } ,
1213 types:: {
1314 Callable , Comparable , DelFunc , DescrGetFunc , DescrSetFunc , GenericMethod , GetDescriptor ,
@@ -34,17 +35,37 @@ pub struct PyDescriptorOwned {
3435 pub qualname : PyRwLock < Option < String > > ,
3536}
3637
37- #[ pyclass( name = "method_descriptor" , module = false ) ]
38+ impl PyDescriptor {
39+ fn bind (
40+ & self ,
41+ method : & ' static PyMethodDef ,
42+ owner : Option < PyObjectRef > ,
43+ obj : PyObjectRef ,
44+ ctx : & Context ,
45+ ) -> PyRef < PyNativeMethod > {
46+ let mut bound = method. to_bound_method ( obj, self . typ ) ;
47+ bound. func . _method_def_owner = owner;
48+ bound. into_ref ( ctx)
49+ }
50+ }
51+
52+ #[ pyclass( name = "method_descriptor" , module = false , traverse = "manual" ) ]
3853pub struct PyMethodDescriptor {
3954 #[ pymember( name = "__objclass__" , path = "typ" ) ]
4055 #[ pymember( name = "__name__" , path = "name" ) ]
4156 pub common : PyDescriptor ,
42- pub method : & ' static PyMethodDef ,
57+ pub ( crate ) method : & ' static PyMethodDef ,
4358 // vectorcall: vector_call_func,
4459 /// Prevent HeapMethodDef from being freed while this descriptor references it
4560 pub ( crate ) _method_def_owner : Option < PyObjectRef > ,
4661}
4762
63+ unsafe impl Traverse for PyMethodDescriptor {
64+ fn traverse ( & self , tracer_fn : & mut TraverseFn < ' _ > ) {
65+ self . _method_def_owner . traverse ( tracer_fn) ;
66+ }
67+ }
68+
4869impl PyMethodDescriptor {
4970 pub fn new ( method : & ' static PyMethodDef , typ : & ' static Py < PyType > , ctx : & Context ) -> Self {
5071 Self {
@@ -125,7 +146,8 @@ impl Callable for PyMethodDescriptor {
125146
126147impl PyMethodDescriptor {
127148 pub fn bind ( & self , obj : PyObjectRef , ctx : & Context ) -> PyRef < PyNativeMethod > {
128- self . method . build_bound_method ( ctx, obj, self . common . typ )
149+ self . common
150+ . bind ( self . method , self . _method_def_owner . clone ( ) , obj, ctx)
129151 }
130152}
131153
@@ -173,15 +195,21 @@ impl Representable for PyMethodDescriptor {
173195}
174196
175197// METH_CLASS descriptors. Same layout as method_descriptor; a distinct type.
176- #[ pyclass( name = "classmethod_descriptor" , module = false ) ]
198+ #[ pyclass( name = "classmethod_descriptor" , module = false , traverse = "manual" ) ]
177199pub struct PyClassMethodDescriptor {
178200 #[ pymember( name = "__objclass__" , path = "typ" ) ]
179201 #[ pymember( name = "__name__" , path = "name" ) ]
180202 pub common : PyDescriptor ,
181- pub method : & ' static PyMethodDef ,
203+ pub ( crate ) method : & ' static PyMethodDef ,
182204 pub ( crate ) _method_def_owner : Option < PyObjectRef > ,
183205}
184206
207+ unsafe impl Traverse for PyClassMethodDescriptor {
208+ fn traverse ( & self , tracer_fn : & mut TraverseFn < ' _ > ) {
209+ self . _method_def_owner . traverse ( tracer_fn) ;
210+ }
211+ }
212+
185213impl PyClassMethodDescriptor {
186214 pub fn new ( method : & ' static PyMethodDef , typ : & ' static Py < PyType > , ctx : & Context ) -> Self {
187215 Self {
@@ -196,7 +224,8 @@ impl PyClassMethodDescriptor {
196224 }
197225
198226 pub fn bind ( & self , obj : PyObjectRef , ctx : & Context ) -> PyRef < PyNativeMethod > {
199- self . method . build_bound_method ( ctx, obj, self . common . typ )
227+ self . common
228+ . bind ( self . method , self . _method_def_owner . clone ( ) , obj, ctx)
200229 }
201230}
202231
0 commit comments