hashlink icon indicating copy to clipboard operation
hashlink copied to clipboard

Null exception when casting with inheritance of depth 2+

Open cardgdev opened this issue 1 year ago • 1 comments

Casting a subclass of a subclass to their base class will cause a strange "null" exception at line 0 of a random external/standard library.

abstract class A {
	public abstract function work():Void;
}

abstract class B extends A {

	public abstract function work(): Void;
}

class C extends B {
	public function new() {}

	public function work():Void {
		trace("doing");
	}
}

class Main {

    static function main(){
        var c = new C();
        var a: A = cast c;
        a.work();
    }
}

Result:

Called from A.work(C:\HaxeToolkit\haxe\std/hl/_std/Date.hx:0) Called from $Main.main(Main.hx:24) Called from .init(?:1)

As you can see it strangely fails at "Date.hx:0". Casting to Dynamic instead can be used as a workaround.

The above code snippet works in other targets.

cardgdev avatar May 22 '23 09:05 cardgdev

This comes from haxe compiler (genhl) that does not detect that the abstract "work" method is overriden in subclasses, and thus creates a static call to A.work() instead of dynamic call for the specific instance.

Here's ASM dump:

		.21    @0 new 0
		.21    @1 call 1, C.new(0)
		.23    @2 call 1, A.work(0)
		.24    @3 ret 1

The temporary solution is to either define the work() method in A (not abstract method) or maybe to override it in a class D extends C, but I don't think that will be enough.

ncannasse avatar May 22 '23 13:05 ncannasse