@@ -242,6 +242,8 @@ static int codegen_pattern_subpattern(compiler *,
242242                                      pattern_ty , pattern_context  * );
243243static  int  codegen_make_closure (compiler  * c , location  loc ,
244244                                PyCodeObject  * co , Py_ssize_t  flags );
245+ static  int  codegen_make_annotate_function (compiler  * c , location  loc ,
246+                                           PyCodeObject  * co );
245247
246248
247249/* Add an opcode with an integer argument */ 
@@ -696,7 +698,8 @@ codegen_setup_annotations_scope(compiler *c, location loc,
696698
697699static  int 
698700codegen_leave_annotations_scope (compiler  * c , location  loc ,
699-                                 Py_ssize_t  annotations_len )
701+                                 Py_ssize_t  annotations_len ,
702+                                 bool  is_function )
700703{
701704    ADDOP_I (c , loc , BUILD_MAP , annotations_len );
702705    ADDOP_IN_SCOPE (c , loc , RETURN_VALUE );
@@ -732,7 +735,8 @@ codegen_leave_annotations_scope(compiler *c, location loc,
732735    if  (co  ==  NULL ) {
733736        return  ERROR ;
734737    }
735-     int  ret  =  codegen_make_closure (c , loc , co , 0 );
738+     int  ret  =  is_function  ? codegen_make_annotate_function (c , loc , co )
739+                           : codegen_make_closure (c , loc , co , 0 );
736740    Py_DECREF (co );
737741    RETURN_IF_ERROR (ret );
738742    return  SUCCESS ;
@@ -780,7 +784,8 @@ codegen_process_deferred_annotations(compiler *c, location loc)
780784    }
781785    Py_DECREF (deferred_anno );
782786
783-     RETURN_IF_ERROR (codegen_leave_annotations_scope (c , loc , annotations_len ));
787+     RETURN_IF_ERROR (codegen_leave_annotations_scope (c , loc , annotations_len ,
788+                     /* is_function */ false));
784789    RETURN_IF_ERROR (codegen_nameop (c , loc , & _Py_ID (__annotate__ ), Store ));
785790
786791    return  SUCCESS ;
@@ -852,6 +857,32 @@ _PyCodegen_EnterAnonymousScope(compiler* c, mod_ty mod)
852857    return  SUCCESS ;
853858}
854859
860+ static  int 
861+ codegen_make_annotate_function (compiler  * c , location  loc ,
862+                                PyCodeObject  * co )
863+ {
864+     // For annotate functions, we don't bother creating the function object 
865+     // unless the __annotate__ attribute is accessed. 
866+     // We may store the prepared data as follows: 
867+     // - Just a code object 
868+     // - A tuple containing the code object, followed by a number of cell objects. 
869+     ADDOP_LOAD_CONST (c , loc , (PyObject * )co );
870+     if  (co -> co_nfreevars ) {
871+         int  i  =  PyUnstable_Code_GetFirstFree (co );
872+         for  (; i  <  co -> co_nlocalsplus ; ++ i ) {
873+             /* Bypass com_addop_varname because it will generate 
874+                LOAD_DEREF but LOAD_CLOSURE is needed. 
875+             */ 
876+             PyObject  * name  =  PyTuple_GET_ITEM (co -> co_localsplusnames , i );
877+             int  arg  =  _PyCompile_LookupArg (c , co , name );
878+             RETURN_IF_ERROR (arg );
879+             ADDOP_I (c , loc , LOAD_CLOSURE , arg );
880+         }
881+         ADDOP_I (c , loc , BUILD_TUPLE , co -> co_nfreevars  +  1 );
882+     }
883+     return  SUCCESS ;
884+ }
885+ 
855886static  int 
856887codegen_make_closure (compiler  * c , location  loc ,
857888                     PyCodeObject  * co , Py_ssize_t  flags )
@@ -1065,7 +1096,7 @@ codegen_annotations(compiler *c, location loc,
10651096            c , codegen_annotations_in_scope (c , loc , args , returns , & annotations_len )
10661097        );
10671098        RETURN_IF_ERROR (
1068-             codegen_leave_annotations_scope (c , loc , annotations_len )
1099+             codegen_leave_annotations_scope (c , loc , annotations_len ,  /* is_function */ true )
10691100        );
10701101        return  MAKE_FUNCTION_ANNOTATE ;
10711102    }
0 commit comments