Class type incompatible with generics

Hi all.

Just a small thing I encountered where I feel like it ought to be possible and I could be missing something. I had the following code:

static function main() {
dothing(MyGeneric<Float>);
}

static function dothing<T>(type : Class<T>) : Void {
trace(type);
}

I thought it might be possible to solve this by marking MyGeneric<T> using @:generic, but it still failed with the compiler complaining about dothing(MyGeneric<Float>) being an invalid expression.

Can this be done at all? Any help would be much appreciated :smile:

You need to insert Type.resolveClass in place of MyGeneric (without type param) because you get Class at runtime like this

macro function resolveClass(e:haxe.macro.Expr) {
var name = haxe.macro.ExprTools.toString(e);
var ret = macro Type.resolveClass($v{name});
trace(haxe.macro.ExprTools.toString(ret));
return ret;
}

class Main {
static function main() {
dothing(resolveClass(MyGeneric));
}
}

There’s no benefit to using macros here, when all the macro does generate the code dothing(Type.resolveClass("MyGeneric")), and you could just as easily type that yourself. But it’s even easier to type dothing(MyGeneric), which has the exact same result.

Neither option allows type parameters, but I think you could get around that with a typedef:

typedef MyGenericFloat = MyGeneric<Float>;

//...

dothing(MyGenericFloat);

This should, in theory, get you the information about the generated MyGeneric_Float type. Haven’t tested, though.

The reason for using macro here is to point out that user can’t get complete type information using runtime functions like Type.typeof or even Class because runtime types have some common root. User should switch to macros, preferably onAfterTyping or similar.

Hi Player, many thanks for the response.

Yeah, this is essentially what I ended up doing. Instead of abstracts, I simply extended a chosen interface with another and recreated the syntax that the generic metadata generates like so:

interface SomeInterface<T> { }
interface SomeInterface_Int extends SomeInterface<Int> { }

It’s a bit impractical but it gets the job done. Perhaps one day it would be nice, if a class/interface/etc is marked generic, to be able to retrieve its type using Type.getClass(MyClass<Int>)

Re: Ilir-Liburn; I did give macros a go as suggested but I went with the above work around due to simplicity.