@@ -54,18 +54,10 @@ unsafe impl Traverse for PyFunction {
5454}
5555
5656impl PyFunction {
57- #[ allow( clippy:: too_many_arguments) ]
5857 #[ inline]
5958 pub ( crate ) fn new (
6059 code : PyRef < PyCode > ,
6160 globals : PyDictRef ,
62- closure : Option < PyRef < PyTuple < PyCellRef > > > ,
63- defaults : Option < PyTupleRef > ,
64- kw_only_defaults : Option < PyDictRef > ,
65- qualname : PyStrRef ,
66- type_params : PyTupleRef ,
67- annotations : PyDictRef ,
68- doc : PyObjectRef ,
6961 vm : & VirtualMachine ,
7062 ) -> PyResult < Self > {
7163 let name = PyMutex :: new ( code. obj_name . to_owned ( ) ) ;
@@ -79,27 +71,22 @@ impl PyFunction {
7971 }
8072 } ) ;
8173
74+ let qualname = vm. ctx . new_str ( code. qualname . as_str ( ) ) ;
8275 let func = Self {
83- code,
76+ code : code . clone ( ) ,
8477 globals,
8578 builtins,
86- closure,
87- defaults_and_kwdefaults : PyMutex :: new ( ( defaults , kw_only_defaults ) ) ,
79+ closure : None ,
80+ defaults_and_kwdefaults : PyMutex :: new ( ( None , None ) ) ,
8881 name,
8982 qualname : PyMutex :: new ( qualname) ,
90- type_params : PyMutex :: new ( type_params ) ,
91- annotations : PyMutex :: new ( annotations ) ,
83+ type_params : PyMutex :: new ( vm . ctx . empty_tuple . clone ( ) ) ,
84+ annotations : PyMutex :: new ( vm . ctx . new_dict ( ) ) ,
9285 module : PyMutex :: new ( module) ,
93- doc : PyMutex :: new ( doc ) ,
86+ doc : PyMutex :: new ( vm . ctx . none ( ) ) ,
9487 #[ cfg( feature = "jit" ) ]
9588 jitted_code : OnceCell :: new ( ) ,
9689 } ;
97-
98- // let name = qualname.as_str().split('.').next_back().unwrap();
99- // func.set_attr(identifier!(vm, __name__), vm.new_pyobj(name), vm)?;
100- // func.set_attr(identifier!(vm, __qualname__), qualname, vm)?;
101- // func.set_attr(identifier!(vm, __doc__), doc, vm)?;
102-
10390 Ok ( func)
10491 }
10592
@@ -318,39 +305,47 @@ impl PyFunction {
318305 }
319306
320307 /// Set function attribute based on MakeFunctionFlags
321- /// This is used by SET_FUNCTION_ATTRIBUTE instruction in CPython 3.13 style
322308 pub ( crate ) fn set_function_attribute (
323309 & mut self ,
324310 attr : bytecode:: MakeFunctionFlags ,
325311 attr_value : PyObjectRef ,
326312 vm : & VirtualMachine ,
327313 ) -> PyResult < ( ) > {
328314 use crate :: builtins:: PyDict ;
329- if attr. contains ( bytecode:: MakeFunctionFlags :: DEFAULTS ) {
330- let defaults = attr_value. clone ( ) . downcast :: < PyTuple > ( ) . map_err ( |_| {
331- vm. new_type_error ( format ! (
332- "__defaults__ must be a tuple, not {}" ,
333- attr_value. class( ) . name( )
334- ) )
335- } ) ?;
315+ if attr == bytecode:: MakeFunctionFlags :: DEFAULTS {
316+ let defaults = match attr_value. downcast :: < PyTuple > ( ) {
317+ Ok ( tuple) => tuple,
318+ Err ( obj) => {
319+ return Err ( vm. new_type_error ( format ! (
320+ "__defaults__ must be a tuple, not {}" ,
321+ obj. class( ) . name( )
322+ ) ) ) ;
323+ }
324+ } ;
336325 self . defaults_and_kwdefaults . lock ( ) . 0 = Some ( defaults) ;
337- } else if attr. contains ( bytecode:: MakeFunctionFlags :: KW_ONLY_DEFAULTS ) {
338- let kwdefaults = attr_value. clone ( ) . downcast :: < PyDict > ( ) . map_err ( |_| {
339- vm. new_type_error ( format ! (
340- "__kwdefaults__ must be a dict, not {}" ,
341- attr_value. class( ) . name( )
342- ) )
343- } ) ?;
326+ } else if attr == bytecode:: MakeFunctionFlags :: KW_ONLY_DEFAULTS {
327+ let kwdefaults = match attr_value. downcast :: < PyDict > ( ) {
328+ Ok ( dict) => dict,
329+ Err ( obj) => {
330+ return Err ( vm. new_type_error ( format ! (
331+ "__kwdefaults__ must be a dict, not {}" ,
332+ obj. class( ) . name( )
333+ ) ) ) ;
334+ }
335+ } ;
344336 self . defaults_and_kwdefaults . lock ( ) . 1 = Some ( kwdefaults) ;
345- } else if attr. contains ( bytecode:: MakeFunctionFlags :: ANNOTATIONS ) {
346- let annotations = attr_value. clone ( ) . downcast :: < PyDict > ( ) . map_err ( |_| {
347- vm. new_type_error ( format ! (
348- "__annotations__ must be a dict, not {}" ,
349- attr_value. class( ) . name( )
350- ) )
351- } ) ?;
337+ } else if attr == bytecode:: MakeFunctionFlags :: ANNOTATIONS {
338+ let annotations = match attr_value. downcast :: < PyDict > ( ) {
339+ Ok ( dict) => dict,
340+ Err ( obj) => {
341+ return Err ( vm. new_type_error ( format ! (
342+ "__annotations__ must be a dict, not {}" ,
343+ obj. class( ) . name( )
344+ ) ) ) ;
345+ }
346+ } ;
352347 * self . annotations . lock ( ) = annotations;
353- } else if attr. contains ( bytecode:: MakeFunctionFlags :: CLOSURE ) {
348+ } else if attr == bytecode:: MakeFunctionFlags :: CLOSURE {
354349 // For closure, we need special handling
355350 // The closure tuple contains cell objects
356351 let closure_tuple = attr_value
@@ -365,14 +360,16 @@ impl PyFunction {
365360 . into_pyref ( ) ;
366361
367362 self . closure = Some ( closure_tuple. try_into_typed :: < PyCell > ( vm) ?) ;
368- } else if attr. contains ( bytecode:: MakeFunctionFlags :: TYPE_PARAMS ) {
363+ } else if attr == bytecode:: MakeFunctionFlags :: TYPE_PARAMS {
369364 let type_params = attr_value. clone ( ) . downcast :: < PyTuple > ( ) . map_err ( |_| {
370365 vm. new_type_error ( format ! (
371366 "__type_params__ must be a tuple, not {}" ,
372367 attr_value. class( ) . name( )
373368 ) )
374369 } ) ?;
375370 * self . type_params . lock ( ) = type_params;
371+ } else {
372+ unreachable ! ( "This is a compiler bug" ) ;
376373 }
377374 Ok ( ( ) )
378375 }
@@ -682,34 +679,23 @@ impl Constructor for PyFunction {
682679 None
683680 } ;
684681
685- // Get function name - use provided name or default to code object name
686- let name = args
687- . name
688- . into_option ( )
689- . unwrap_or_else ( || PyStr :: from ( args. code . obj_name . as_str ( ) ) . into_ref ( & vm. ctx ) ) ;
690-
691- // Get qualname - for now just use the name
692- let qualname = name. clone ( ) ;
693-
694- // Create empty type_params and annotations
695- let type_params = vm. ctx . new_tuple ( vec ! [ ] ) ;
696- let annotations = vm. ctx . new_dict ( ) ;
697-
698- // Get doc from code object - for now just use None
699- let doc = vm. ctx . none ( ) ;
700-
701- let func = Self :: new (
702- args. code ,
703- args. globals ,
704- closure,
705- args. defaults . into_option ( ) ,
706- args. kwdefaults . into_option ( ) ,
707- qualname,
708- type_params,
709- annotations,
710- doc,
711- vm,
712- ) ?;
682+ let mut func = Self :: new ( args. code . clone ( ) , args. globals . clone ( ) , vm) ?;
683+ // Set function name if provided
684+ if let Some ( name) = args. name . into_option ( ) {
685+ * func. name . lock ( ) = name. clone ( ) ;
686+ // Also update qualname to match the name
687+ * func. qualname . lock ( ) = name;
688+ }
689+ // Now set additional attributes directly
690+ if let Some ( closure_tuple) = closure {
691+ func. closure = Some ( closure_tuple) ;
692+ }
693+ if let Some ( defaults) = args. defaults . into_option ( ) {
694+ func. defaults_and_kwdefaults . lock ( ) . 0 = Some ( defaults) ;
695+ }
696+ if let Some ( kwdefaults) = args. kwdefaults . into_option ( ) {
697+ func. defaults_and_kwdefaults . lock ( ) . 1 = Some ( kwdefaults) ;
698+ }
713699
714700 func. into_ref_with_type ( vm, cls) . map ( Into :: into)
715701 }
0 commit comments