Inconsistent behavior with abstract array inline functions
After trying to figure out why HaxeFlixel's MatrixVector.set function did not behave correctly when targeting Hashlink, I found out inlined functions caused the compiler to not create unique references for variables used from the abstract. I've created a code sample where this is viewable: https://try.haxe.org/#3852320A. Instead of the sample performing this[0] = y; this[1] = x; it would behave as this[0] = this[1]; this[1] = this[0];. The traced value should return as [0, 10] but instead returns as [0, 0], you can see this work correctly when switching the target to Javascript or Eval.
I originally wrote this off as an odd issue with Hashlink and was planning to write an issue on their repo until I messed around with the test more and found out that this behavior is also reproducible on non-hashlink targets when the inline function's default parameter values are omitted, leading me to believe that this might stem from Haxe instead.
Sample with omitted default parameter values: https://try.haxe.org/#b7e8Eb21. No targets return [0, 10].
The compiler can be forced to create an unique reference when the variable is used inside of the inlined function, for example adding a trace in the function like trace(x, y); would fix it.
Here's a slightly more minimal sample to reproduce the issue:
function main() {
var arr = [10,0];
trace('Before flipping: ' + arr);
// Flips values at 0 and 1
set(arr, arr[1], arr[0]);
trace('After flipping: ' + arr);
}
inline function set(arr:Array<Int>, x:Int, y:Int) {
arr[0] = x;
arr[1] = y;
}
https://try.haxe.org/#8fF5e36F
If the assignments are made to object fields instead of an array, then haxe is capable of generating a temporary variable correctly:
let y = obj.x;
obj.x = obj.y;
obj.y = y;
Object version source code
function main() {
var obj = {x:10, y:0};
trace('Before flipping: ' + obj);
// Flips values at 0 and 1
set(obj, obj.y, obj.x);
trace('After flipping: ' + obj);
}
inline function set(obj:{x:Int, y:Int}, x:Int, y:Int) {
obj.x = x;
obj.y = y;
}