HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.17k stars 654 forks source link

`@:generic` leaks type parameters #4599

Open waneck opened 9 years ago

waneck commented 9 years ago

The following code:

class Main {
  static function main() {
    Test2.somethingElse(10);
  }
}

class Test {
  @:generic public static function something<T>(t:T) {
    return t;
  }
}

@:forward
abstract Test2(Test) {
  @:extern inline public static function somethingElse<T>(t:T) {
    return Test.something(t);
  }
}

Will generate the following -D dump for Test.something:

    static public something_somethingElse_T(method) : t : somethingElse.T -> somethingElse.T

     = function(t:somethingElse.T) = {
        var tmp = t;
        return tmp;
    }

That somethingElse.T comes from the abstract type

waneck commented 9 years ago

Also unfortunately there's no way to call a @:generic function from another function - be it @:generic or inline. And since @:forward doesn't work for static fields, there's no way to correctly deal with wrapping a type on an abstract if it has static fields/functions

Simn commented 9 years ago

Isn't this just another instance of #3033?

waneck commented 9 years ago

It's not. This one has to do with @:generic types being generated with leaked type parameters - it has nothing to do with TMono types

Simn commented 8 years ago

It's probably the same as #3663. We expand @:generic while typing the inline function, so this is technically consistent.

Simn commented 8 years ago

It's not quite the same: #3663 is about inlining while generically expanding whereas this issue is about generically expanding while inlining.

Simn commented 1 year ago

One solution for this might be to allow partial generic expansion. Basically, if we substitute a generic type parameter with a non-generic one, we absorb that type parameter into the new function and make the function @:generic again.

This would require reapplying calls to generic functions, but I think this is exactly the same situation as overload calls for which we already do that anyway.