@@ -196,8 +196,8 @@ def prepare_func_def(
196196 mapper : Mapper ,
197197 options : CompilerOptions ,
198198) -> FuncDecl :
199- #create_generator_class_if_needed(module_name, class_name, fdef, mapper)
200- #assert False
199+ # create_generator_class_if_needed(module_name, class_name, fdef, mapper)
200+ # assert False
201201
202202 kind = (
203203 FUNC_CLASSMETHOD
@@ -210,38 +210,37 @@ def prepare_func_def(
210210 return decl
211211
212212
213- def create_generator_class_if_needed (
213+ def create_generator_class_for_func (
214214 module_name : str , class_name : str | None , fdef : FuncDef , mapper : Mapper , name_suffix : str = ""
215- ) -> None :
216- """If function is a generator/async function, declare a generator class.
215+ ) -> ClassIR :
216+ """For a generator/async function, declare a generator class.
217217
218218 Each generator and async function gets a dedicated class that implements the
219219 generator protocol with generated methods.
220220 """
221- if fdef .is_coroutine or fdef .is_generator :
222- name = "_" .join (x for x in [fdef .name , class_name ] if x ) + "_gen" + name_suffix
223- cir = ClassIR (name , module_name , is_generated = True , is_final_class = True )
224- cir .reuse_freed_instance = True
225- mapper .fdef_to_generator [fdef ] = cir
221+ assert fdef .is_coroutine or fdef .is_generator
222+ name = "_" .join (x for x in [fdef .name , class_name ] if x ) + "_gen" + name_suffix
223+ cir = ClassIR (name , module_name , is_generated = True , is_final_class = True )
224+ cir .reuse_freed_instance = True
225+ mapper .fdef_to_generator [fdef ] = cir
226226
227- helper_sig = FuncSignature (
228- (
229- RuntimeArg (SELF_NAME , object_rprimitive ),
230- RuntimeArg ("type" , object_rprimitive ),
231- RuntimeArg ("value" , object_rprimitive ),
232- RuntimeArg ("traceback" , object_rprimitive ),
233- RuntimeArg ("arg" , object_rprimitive ),
234- # If non-NULL, used to store return value instead of raising StopIteration(retv)
235- RuntimeArg ("stop_iter_ptr" , object_pointer_rprimitive ),
236- ),
237- object_rprimitive ,
238- )
227+ helper_sig = FuncSignature (
228+ (
229+ RuntimeArg (SELF_NAME , object_rprimitive ),
230+ RuntimeArg ("type" , object_rprimitive ),
231+ RuntimeArg ("value" , object_rprimitive ),
232+ RuntimeArg ("traceback" , object_rprimitive ),
233+ RuntimeArg ("arg" , object_rprimitive ),
234+ # If non-NULL, used to store return value instead of raising StopIteration(retv)
235+ RuntimeArg ("stop_iter_ptr" , object_pointer_rprimitive ),
236+ ),
237+ object_rprimitive ,
238+ )
239239
240- # The implementation of most generator functionality is behind this magic method.
241- helper_fn_decl = FuncDecl (
242- GENERATOR_HELPER_NAME , name , module_name , helper_sig , internal = True
243- )
244- cir .method_decls [helper_fn_decl .name ] = helper_fn_decl
240+ # The implementation of most generator functionality is behind this magic method.
241+ helper_fn_decl = FuncDecl (GENERATOR_HELPER_NAME , name , module_name , helper_sig , internal = True )
242+ cir .method_decls [helper_fn_decl .name ] = helper_fn_decl
243+ return cir
245244
246245
247246def prepare_method_def (
@@ -816,5 +815,13 @@ def registered_impl_from_possible_register_call(
816815
817816def gen_generator_types (mapper : Mapper , modules : list [MypyFile ]) -> None :
818817 for fdef , ir in mapper .func_to_decl .items ():
819- if isinstance (fdef , FuncDef ):
820- create_generator_class_if_needed (ir .module_name , ir .class_name , fdef , mapper )
818+ if isinstance (fdef , FuncDef ) and (fdef .is_coroutine or fdef .is_generator ):
819+ gen_ir = create_generator_class_for_func (ir .module_name , ir .class_name , fdef , mapper )
820+ # TODO: We could probably support decorators sometimes (static and class method?)
821+ if not fdef .is_decorated :
822+ # Give a more precise type for generators, so that we can optimize
823+ # code that uses them. They return a generator object, which has a
824+ # specific class. Without this, the type would have to be 'object'.
825+ ir .sig .ret_type = RInstance (gen_ir )
826+ if ir .bound_sig :
827+ ir .bound_sig .ret_type = RInstance (gen_ir )
0 commit comments