@@ -1083,6 +1083,49 @@ func bar(v *foo.Foo6) {
10831083` )
10841084}
10851085
1086+ // Test that pre-range statements are emitted to outer scope
1087+ // Regression test for: goplus/xgo#2629
1088+ func TestForRangePreStmts (t * testing.T ) {
1089+ pkg := newMainPackage ()
1090+ // Create a function that takes an interface{} parameter
1091+ v := pkg .NewParam (token .NoPos , "data" , types .NewInterfaceType (nil , nil ).Complete ())
1092+
1093+ pkg .NewFunc (nil , "bar" , types .NewTuple (v ), nil , false ).BodyStart (pkg ).
1094+ // Start for-range and push the block scope
1095+ ForRange ("k" , "v" ).
1096+ // This simulates the scenario where type assertion statements are emitted
1097+ // during range expression compilation. We'll manually emit a statement
1098+ // to the current block (which is the for-range block scope) before
1099+ // calling RangeAssignThen.
1100+ DefineVarStart (token .NoPos , "_autoGo_1" , "_" ).
1101+ Val (ctxRef (pkg , "data" )).TypeAssert (types .NewMap (
1102+ types .Typ [types .String ],
1103+ types .NewInterfaceType (nil , nil ).Complete (),
1104+ ), 2 ).
1105+ EndInit (1 ).
1106+ // Now call RangeAssignThen which should extract the DefineVar statement
1107+ // and save it as a pre-statement
1108+ VarVal ("_autoGo_1" ).
1109+ RangeAssignThen (token .NoPos ).
1110+ Val (pkg .Import ("fmt" ).Ref ("Println" )).Val (ctxRef (pkg , "k" )).Val (ctxRef (pkg , "v" )).Call (2 ).EndStmt ().
1111+ End ().
1112+ End ()
1113+
1114+ // The expected output should have the type assertion BEFORE the for-range loop,
1115+ // not inside it
1116+ domTest (t , pkg , `package main
1117+
1118+ import "fmt"
1119+
1120+ func bar(data interface{}) {
1121+ _autoGo_1, _ := data.(map[string]interface{})
1122+ for k, v := range _autoGo_1 {
1123+ fmt.Println(k, v)
1124+ }
1125+ }
1126+ ` )
1127+ }
1128+
10861129// ----------------------------------------------------------------------------
10871130
10881131func TestStaticMethod (t * testing.T ) {
0 commit comments