@@ -6,7 +6,8 @@ use crate::{
66 common:: hash:: PyHash ,
77 function:: { FuncArgs , PyMethodDef , PyMethodFlags , PySetterValue } ,
88 types:: {
9- Callable , Comparable , GetDescriptor , Hashable , InitFunc , PyComparisonOp , Representable ,
9+ Callable , Comparable , GetDescriptor , HashFunc , Hashable , InitFunc , PyComparisonOp ,
10+ Representable ,
1011 } ,
1112} ;
1213use rustpython_common:: lock:: PyRwLock ;
@@ -391,14 +392,52 @@ pub fn init(ctx: &Context) {
391392
392393// PySlotWrapper - wrapper_descriptor
393394
395+ /// Type-erased slot function - mirrors CPython's void* d_wrapped
396+ /// Each variant knows how to call the wrapped function with proper types
397+ #[ derive( Clone , Copy ) ]
398+ pub enum SlotFunc {
399+ Init ( InitFunc ) ,
400+ Hash ( HashFunc ) ,
401+ }
402+
403+ impl std:: fmt:: Debug for SlotFunc {
404+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
405+ match self {
406+ SlotFunc :: Init ( _) => write ! ( f, "SlotFunc::Init(...)" ) ,
407+ SlotFunc :: Hash ( _) => write ! ( f, "SlotFunc::Hash(...)" ) ,
408+ }
409+ }
410+ }
411+
412+ impl SlotFunc {
413+ /// Call the wrapped slot function with proper type handling
414+ pub fn call ( & self , obj : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
415+ match self {
416+ SlotFunc :: Init ( func) => {
417+ func ( obj, args, vm) ?;
418+ Ok ( vm. ctx . none ( ) )
419+ }
420+ SlotFunc :: Hash ( func) => {
421+ if !args. args . is_empty ( ) || !args. kwargs . is_empty ( ) {
422+ return Err (
423+ vm. new_type_error ( "__hash__() takes no arguments (1 given)" . to_owned ( ) )
424+ ) ;
425+ }
426+ let hash = func ( & obj, vm) ?;
427+ Ok ( vm. ctx . new_int ( hash) . into ( ) )
428+ }
429+ }
430+ }
431+ }
432+
394433/// wrapper_descriptor: wraps a slot function as a Python method
395434// = PyWrapperDescrObject
396435#[ pyclass( name = "wrapper_descriptor" , module = false ) ]
397436#[ derive( Debug ) ]
398437pub struct PySlotWrapper {
399438 pub typ : & ' static Py < PyType > ,
400439 pub name : & ' static PyStrInterned ,
401- pub wrapped : InitFunc ,
440+ pub wrapped : SlotFunc ,
402441 pub doc : Option < & ' static str > ,
403442}
404443
@@ -430,7 +469,7 @@ impl Callable for PySlotWrapper {
430469 type Args = FuncArgs ;
431470
432471 fn call ( zelf : & Py < Self > , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
433- // list.__init__(l, [1,2,3]) form
472+ // list.__init__(l, [1,2,3]) form - first arg is self
434473 let ( obj, rest) : ( PyObjectRef , FuncArgs ) = args. bind ( vm) ?;
435474
436475 if !obj. fast_isinstance ( zelf. typ ) {
@@ -442,8 +481,7 @@ impl Callable for PySlotWrapper {
442481 ) ) ) ;
443482 }
444483
445- ( zelf. wrapped ) ( obj, rest, vm) ?;
446- Ok ( vm. ctx . none ( ) )
484+ zelf. wrapped . call ( obj, rest, vm)
447485 }
448486}
449487
@@ -506,8 +544,7 @@ impl Callable for PyMethodWrapper {
506544 type Args = FuncArgs ;
507545
508546 fn call ( zelf : & Py < Self > , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
509- ( zelf. wrapper . wrapped ) ( zelf. obj . clone ( ) , args, vm) ?;
510- Ok ( vm. ctx . none ( ) )
547+ zelf. wrapper . wrapped . call ( zelf. obj . clone ( ) , args, vm)
511548 }
512549}
513550
0 commit comments