@@ -931,6 +931,48 @@ impl ExecutingFrame<'_> {
931931 dict. merge_object ( source, vm) ?;
932932 Ok ( None )
933933 }
934+ Instruction :: DictMerge { index } => {
935+ let source = self . pop_value ( ) ;
936+ let idx = index. get ( arg) ;
937+
938+ // Get the dict to merge into (same logic as DICT_UPDATE)
939+ let dict_ref = if idx <= 1 {
940+ self . top_value ( )
941+ } else {
942+ self . nth_value ( idx - 1 )
943+ } ;
944+
945+ let dict: & Py < PyDict > = unsafe { dict_ref. downcast_unchecked_ref ( ) } ;
946+
947+ // Check if source is a mapping
948+ if vm
949+ . get_method ( source. clone ( ) , vm. ctx . intern_str ( "keys" ) )
950+ . is_none ( )
951+ {
952+ return Err ( vm. new_type_error ( format ! (
953+ "'{}' object is not a mapping" ,
954+ source. class( ) . name( )
955+ ) ) ) ;
956+ }
957+
958+ // Check for duplicate keys
959+ let keys_iter = vm. call_method ( & source, "keys" , ( ) ) ?;
960+ for key in keys_iter. try_to_value :: < Vec < PyObjectRef > > ( vm) ? {
961+ if key. downcast_ref :: < PyStr > ( ) . is_none ( ) {
962+ return Err ( vm. new_type_error ( "keywords must be strings" . to_owned ( ) ) ) ;
963+ }
964+ if dict. contains_key ( & * key, vm) {
965+ let key_repr = key. repr ( vm) ?;
966+ return Err ( vm. new_type_error ( format ! (
967+ "got multiple values for keyword argument {}" ,
968+ key_repr. as_str( )
969+ ) ) ) ;
970+ }
971+ let value = vm. call_method ( & source, "__getitem__" , ( key. clone ( ) , ) ) ?;
972+ dict. set_item ( & * key, value, vm) ?;
973+ }
974+ Ok ( None )
975+ }
934976 Instruction :: EndAsyncFor => {
935977 // END_ASYNC_FOR pops (awaitable, exc) from stack
936978 // Stack: [awaitable, exc] -> []
@@ -2379,15 +2421,13 @@ impl ExecutingFrame<'_> {
23792421 Ok ( None )
23802422 }
23812423 Ok ( PyIterReturn :: StopIteration ( _) ) => {
2382- // Pop iterator from stack:
2383- self . pop_value ( ) ;
2384-
2385- // End of for loop
2424+ // CPython 3.14: Do NOT pop iterator here
2425+ // POP_ITER instruction will handle cleanup after the loop
23862426 self . jump ( target) ;
23872427 Ok ( None )
23882428 }
23892429 Err ( next_error) => {
2390- // Pop iterator from stack:
2430+ // On error, pop iterator and propagate
23912431 self . pop_value ( ) ;
23922432 Err ( next_error)
23932433 }
0 commit comments