COMMUNITY

Having trouble with an abstract with type parameters over an extern class

I think this may be a bug, but I wanted to post here first to see if I was maybe doing something wrong. I am trying to define an abstract over an extern class, both with type parameters. What I’m really trying to do is use the abstract to declare higher order operations over an extern class, so I only need to implement a core set of functionality in my targets. Here’s some code that shows the issue:

extern class Object_<T> {
    public function method<TN>(cb:T->TN):Object_<TN>;
}

abstract Broken<T>(Object_<T>) {

    inline private function new(thiz:Object_<T>) {
        this = thiz;
    }

    public function method<TN>(cb:T->TN):Broken<TN> {
        return new Broken<TN>(this.method(cb));
    }
}
class TestCase {

    public function broken(obj:Broken<String>):Broken<Int> {
        return obj.method(s -> 1);
    }
}

When compiled to C# (using Haxe 4.0.5 and hxcs 4.0.0-alpha, and the command line "haxe -cs dist File.hx), the code generated for TestCase fails to compile. Specifically, it generates this code:

 public virtual global::src.Object_<int> broken(global::src.Object_<string> obj) {
            #line 30 "/mnt/c/Users/jesse/Development/bommer-common/bugs/src/GenericAbstract.hx"
            return ((global::src.Object_<int>) (global::src._GenericAbstract.Broken_Impl_.method<object, string>(((global::src.Object_<string>) (obj) ), ((global::haxe.lang.Function) (( (( global::src.TestCase_broken_30__Fun.__hx_current != null )) ? (global::src.TestCase_broken_30__Fun.__hx_current) : (global::src.TestCase_broken_30__Fun.__hx_current = ((global::src.TestCase_broken_30__Fun) (new global::src.TestCase_broken_30__Fun()) )) )) ))) );
        }

And fails because of that typecast to Object_. The code for method is:

  public static global::src.Object_<TN> method<TN, T>(global::src.Object_<T> this1, global::haxe.lang.Function cb) {
            #line 16 "/mnt/c/Users/jesse/Development/bommer-common/bugs/src/GenericAbstract.hx"
            global::src.Object_<TN> this2 = this1.method<TN>(((global::haxe.lang.Function) (cb) ));
            #line 16 "/mnt/c/Users/jesse/Development/bommer-common/bugs/src/GenericAbstract.hx"
            return ((global::src.Object_<TN>) (this2) );
        }

…because the TestCase code above specifies object as TN, method returns an Object_<object> instead of an Object_<int>.

I have noticed that if I @:forward(method) and remove it from Broken, it generates compilable code in TestCase. But that would defeat my reason for using an abstract (as stated above).
Am I doing something silly here? Or is this a bug in the Haxe/C# compiler?

Try adding @:nativeGen meta to your abstract. If that won’t help, then submit an issue.

You can also try compilation flags like -D erase-generics and -D fast-cast if they suite your needs. You can find them in haxe --help-defines