@@ -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,18 +71,21 @@ impl PyFunction {
7971 }
8072 } ) ;
8173
74+ // CPython 3.13 style: Use minimal attributes, others will be set via SET_FUNCTION_ATTRIBUTE
75+ let qualname = vm. ctx . new_str ( code. qualname . as_str ( ) ) ;
76+
8277 let func = Self {
83- code,
78+ code : code . clone ( ) ,
8479 globals,
8580 builtins,
86- closure,
87- defaults_and_kwdefaults : PyMutex :: new ( ( defaults , kw_only_defaults ) ) ,
81+ closure : None , // will be set by SET_FUNCTION_ATTRIBUTE
82+ defaults_and_kwdefaults : PyMutex :: new ( ( None , None ) ) , // will be set by SET_FUNCTION_ATTRIBUTE
8883 name,
8984 qualname : PyMutex :: new ( qualname) ,
90- type_params : PyMutex :: new ( type_params ) ,
91- annotations : PyMutex :: new ( annotations ) ,
85+ type_params : PyMutex :: new ( vm . ctx . empty_tuple . clone ( ) ) , // will be set by SET_FUNCTION_ATTRIBUTE
86+ annotations : PyMutex :: new ( vm . ctx . new_dict ( ) ) , // will be set by SET_FUNCTION_ATTRIBUTE
9287 module : PyMutex :: new ( module) ,
93- doc : PyMutex :: new ( doc ) ,
88+ doc : PyMutex :: new ( vm . ctx . none ( ) ) , // will be set by SET_FUNCTION_ATTRIBUTE
9489 #[ cfg( feature = "jit" ) ]
9590 jitted_code : OnceCell :: new ( ) ,
9691 } ;
@@ -326,31 +321,40 @@ impl PyFunction {
326321 vm : & VirtualMachine ,
327322 ) -> PyResult < ( ) > {
328323 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- } ) ?;
324+ if attr == bytecode:: MakeFunctionFlags :: DEFAULTS {
325+ let defaults = match attr_value. downcast :: < PyTuple > ( ) {
326+ Ok ( tuple) => tuple,
327+ Err ( obj) => {
328+ return Err ( vm. new_type_error ( format ! (
329+ "__defaults__ must be a tuple, not {}" ,
330+ obj. class( ) . name( )
331+ ) ) ) ;
332+ }
333+ } ;
336334 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- } ) ?;
335+ } else if attr == bytecode:: MakeFunctionFlags :: KW_ONLY_DEFAULTS {
336+ let kwdefaults = match attr_value. downcast :: < PyDict > ( ) {
337+ Ok ( dict) => dict,
338+ Err ( obj) => {
339+ return Err ( vm. new_type_error ( format ! (
340+ "__kwdefaults__ must be a dict, not {}" ,
341+ obj. class( ) . name( )
342+ ) ) ) ;
343+ }
344+ } ;
344345 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- } ) ?;
346+ } else if attr == bytecode:: MakeFunctionFlags :: ANNOTATIONS {
347+ let annotations = match attr_value. downcast :: < PyDict > ( ) {
348+ Ok ( dict) => dict,
349+ Err ( obj) => {
350+ return Err ( vm. new_type_error ( format ! (
351+ "__annotations__ must be a dict, not {}" ,
352+ obj. class( ) . name( )
353+ ) ) ) ;
354+ }
355+ } ;
352356 * self . annotations . lock ( ) = annotations;
353- } else if attr. contains ( bytecode:: MakeFunctionFlags :: CLOSURE ) {
357+ } else if attr == bytecode:: MakeFunctionFlags :: CLOSURE {
354358 // For closure, we need special handling
355359 // The closure tuple contains cell objects
356360 let closure_tuple = attr_value
@@ -365,14 +369,16 @@ impl PyFunction {
365369 . into_pyref ( ) ;
366370
367371 self . closure = Some ( closure_tuple. try_into_typed :: < PyCell > ( vm) ?) ;
368- } else if attr. contains ( bytecode:: MakeFunctionFlags :: TYPE_PARAMS ) {
372+ } else if attr == bytecode:: MakeFunctionFlags :: TYPE_PARAMS {
369373 let type_params = attr_value. clone ( ) . downcast :: < PyTuple > ( ) . map_err ( |_| {
370374 vm. new_type_error ( format ! (
371375 "__type_params__ must be a tuple, not {}" ,
372376 attr_value. class( ) . name( )
373377 ) )
374378 } ) ?;
375379 * self . type_params . lock ( ) = type_params;
380+ } else {
381+ unreachable ! ( "This is a compiler bug" ) ;
376382 }
377383 Ok ( ( ) )
378384 }
@@ -682,34 +688,25 @@ impl Constructor for PyFunction {
682688 None
683689 } ;
684690
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- ) ?;
691+ // CPython 3.13 style: Create minimal function, set attributes separately
692+ let mut func = Self :: new ( args. code . clone ( ) , args. globals . clone ( ) , vm) ?;
693+
694+ // Set function name if provided
695+ if let Some ( name) = args. name . into_option ( ) {
696+ * func. name . lock ( ) = name. clone ( ) ;
697+ // Also update qualname to match the name
698+ * func. qualname . lock ( ) = name;
699+ }
700+ // Now set additional attributes directly
701+ if let Some ( closure_tuple) = closure {
702+ func. closure = Some ( closure_tuple) ;
703+ }
704+ if let Some ( defaults) = args. defaults . into_option ( ) {
705+ func. defaults_and_kwdefaults . lock ( ) . 0 = Some ( defaults) ;
706+ }
707+ if let Some ( kwdefaults) = args. kwdefaults . into_option ( ) {
708+ func. defaults_and_kwdefaults . lock ( ) . 1 = Some ( kwdefaults) ;
709+ }
713710
714711 func. into_ref_with_type ( vm, cls) . map ( Into :: into)
715712 }
0 commit comments