Tuple Assignment with Struct Pointer Yields Incorrect Output in translated haxe
Source Go Code:
package main
type S struct{ p int }
var test S
func main() {
temp := &test
temp, temp.p = new(S), 2
println(temp.p, test.p)
}
Go Output:
0 2
Translated Haxe Code:
package _internal;
function main():Void {
var _temp = (stdgo.Go.setRef(_internal.Runner__test._test) : stdgo.Ref<_internal.Runner_s.S>);
{
final __tmp__0 = (stdgo.Go.setRef(({} : _internal.Runner_s.S)) : stdgo.Ref<_internal.Runner_s.S>);
final __tmp__1 = (2 : stdgo.GoInt);
_temp = @:binopAssign __tmp__0;
(@:checkr _temp ?? throw "null pointer dereference")._p = @:binopAssign __tmp__1;
};
stdgo.Go.println((@:checkr _temp ?? throw "null pointer dereference")._p, _internal.Runner__test._test._p);
}
Haxe Output:
2 0
Analysis:
The discrepancy in the output between the Go and translated Haxe code is due to a difference in the evaluation order of tuple assignments involving struct pointers. In the original Go code, the line temp, temp.p = new(S), 2 is evaluated left-to-right, ensuring that temp.p = 2 is executed before temp is reassigned to new(S). This leads to the expected output 0 2, where test.p is correctly updated through the original pointer.
In the translated Haxe code, the equivalent assignment is broken down into temporary variables (__tmp__0 and __tmp__1), and the order of assignment is reversed. Specifically, _temp is first assigned __tmp__0 (a new struct), and then the field assignment is applied to this new instance rather than the original test struct. This results in the incorrect output 2 0, as the field _p of the test struct is never updated.
The issue indicates that go2hx does not correctly replicate the left-to-right evaluation semantics of Go's tuple assignments, leading to a runtime divergence. The correct behavior should maintain the original reference during field assignment before updating the pointer, as in the Go code.
...and yet a further superb bug @Yeaseen the emulation of multiple assignment has been problematic before, the project can use this error to fix the correct sequence of events. Thank you again for spending time finding this problem.
This is trickery then I first realized, this gives output 2 0 for both Haxe and Go:
package main
type S struct{ p int }
var test S
func main() {
temp := &test
//temp, temp.p = new(S), 2
temp = new(S)
temp.p = 2
println(temp.p, test.p)
}
it's almost as if we need to make temporary variables for both the right side and the left side. Hopefully I am missing something.