[jvm] Bad type on operand stack when spreading an array for Rest<T> generic arg
function main():Void {
t(...[10]);
}
function t<T>(x:haxe.Rest<T>) {}
openjdk 21.0.2 Haxe nightly 5.0.0-alpha.1+0620b1b
I don't think an open Rest<T> can work on this target. Rest arguments are based on native arrays, which are invariant. There is no type in the run-time that would accept both int[] and java.lang.Object[], so declaring one in Haxe is always going to cause problems.
You can produce a similar error with Vector directly:
import haxe.ds.Vector;
function main():Void {
var a = Vector.fromArrayCopy([10]);
t(a); // Exception in thread "main" java.lang.ClassCastException: class [I cannot be cast to class [Ljava.lang.Object; ([I and [Ljava.lang.Object; are in module java.base of loader 'bootstrap')
}
function t<T>(x:Vector<T>) {
trace(x);
}
The problem with catching this during typing is that the compiler doesn't have a mechanism to disallow something like a generic Vector<T>, and I'm not sure how that would best be expressed either.
This can be worked around by making t inline, because then we can work with the concrete type at the call-site.
Ran into this again today, thanks for the tip about inlining.
Any suggestion for how to overcome the generic arg not allowing variance in this example?
function main():Void {
new Test<Int>(0,0,...[]);
}
class Test<T> {
public function new(length:Int, capacity:Int, args:haxe.Rest<T>) {
}
}
If I set Test to inline it makes it no longer possible to define Test without Rest args:
new Test<Int>(0,0);
Hitting the compiler error, is this also intentional?:
(length : Int, capacity : Int, args : haxe.Rest<Int>) -> Void should be (Int, Int) -> Void