@@ -4612,12 +4612,27 @@ impl ExecutingFrame<'_> {
46124612 }
46134613 }
46144614 Instruction :: ForIterGen => {
4615- // ForIterGen is not faithfully implementable without inline
4616- // generator frame resumption (as CPython does). Fall through
4617- // to the generic path so the debugger sees StopIteration.
46184615 let target = bytecode:: Label ( self . lasti ( ) + 1 + u32:: from ( arg) ) ;
4619- self . execute_for_iter ( vm, target) ?;
4620- Ok ( None )
4616+ let iter = self . top_value ( ) ;
4617+ if let Some ( generator) = iter. downcast_ref_if_exact :: < PyGenerator > ( vm) {
4618+ match generator. as_coro ( ) . send ( iter, vm. ctx . none ( ) , vm) {
4619+ Ok ( PyIterReturn :: Return ( value) ) => {
4620+ self . push_value ( value) ;
4621+ }
4622+ Ok ( PyIterReturn :: StopIteration ( value) ) => {
4623+ if vm. use_tracing . get ( ) && !vm. is_none ( & self . object . trace . lock ( ) ) {
4624+ let stop_exc = vm. new_stop_iteration ( value) ;
4625+ self . fire_exception_trace ( & stop_exc, vm) ?;
4626+ }
4627+ self . for_iter_jump_on_exhausted ( target) ;
4628+ }
4629+ Err ( e) => return Err ( e) ,
4630+ }
4631+ Ok ( None )
4632+ } else {
4633+ self . execute_for_iter ( vm, target) ?;
4634+ Ok ( None )
4635+ }
46214636 }
46224637 Instruction :: LoadGlobalModule => {
46234638 let oparg = u32:: from ( arg) ;
@@ -7299,6 +7314,8 @@ impl ExecutingFrame<'_> {
72997314 Some ( Instruction :: ForIterList )
73007315 } else if iter. downcast_ref_if_exact :: < PyTupleIterator > ( vm) . is_some ( ) {
73017316 Some ( Instruction :: ForIterTuple )
7317+ } else if iter. downcast_ref_if_exact :: < PyGenerator > ( vm) . is_some ( ) {
7318+ Some ( Instruction :: ForIterGen )
73027319 } else {
73037320 None
73047321 } ;
0 commit comments