在宏中统一泛型类型

Unify generic types in macro

我想使用宏来检查函数是否返回特定的泛型类型,比如 Array,所以如果函数返回 Array<Dynamic>Array<String> 也没问题甚至是通用的 Array<T>.

所以我尝试 Context.unify 它与 Array<Dynamic>。对于 Array<String>Array<Dynamic> 没问题,但当类型参数为 "generic" 时它会失败,因为 ComplexType Array<T> 不会转换为具有 Type not found: T 的类型(请参见下面的代码)。是否有任何可能的方法来实现我正在尝试做的事情?

package;

#if macro
import haxe.macro.Context;
using haxe.macro.ComplexTypeTools;
#end

#if !macro @:build(Macros.build()) #end
class Main 
{
    public function test<T>():Array<T>
    {
        return [];
    }
}

class Macros
{
    public static function build()
    {
        #if macro
        var fields = Context.getBuildFields();
        for(field in fields)
        {
            switch(field.kind)
            {
                case FFun(f):
                    // try to unify Array<String> with Array<Dynamic>
                    trace(Context.unify((macro:Array<String>).toType(), (macro:Array<Dynamic>).toType())); 
                    // true

                    // try to unify Array<T> with Array<Dynamic>
                    trace(Context.unify(f.ret.toType(), (macro:Array<Dynamic>).toType())); 
                    // Type not found: T
                default:
            }
        }
        return null;
        #end
    }
}

更新

因此,检查 TPath 并不是最好的主意。 基于先前关于 Dynamic 可分配给任何类型的假设,我们可以用 Dynamic 替换不可转换的类型参数(例如 Array<T> = Array<Dynamic>)并尝试统一它。

static function toTypeExt(c:ComplexType):Null<haxe.macro.Type>
{
    try {
        return c.toType();          
    } catch (error:Error)
    {                   
        switch (c)                          
        {
            case TPath(p):                  
                //deep copy of the TPath with all type parameters as Dynamic
                var paramsCopy = [for (i in 0...p.params.length) TPType(macro:Dynamic)];
                var pCopy:TypePath = {
                    name: p.name,
                    pack: p.pack,
                    sub: p.sub,
                    params: paramsCopy
                }
                var cCopy = TPath(pCopy);

                //convert after
                return cCopy.toType();
            default:                    
        }
    }

    return null;
}

在构建宏中使用 toTypeExt() 而不是 toType。

trace(Context.unify(toTypeExt(f.ret), (macro:Array<Dynamic>).toType()));

在我看来更像是一种解决方法,但是 ComplexTypeTools.toType 有一个奇怪的地方 - 它会在 class 类型参数下成功,而在方法类型参数上失败。

旧答案

统一将不起作用,因为无法将具有类型参数的 ComplexType 转换为 Type(在该上下文中)。但是由于您正在与 Array 统一,因此可以安全地假设任何 Array 都将与它统一(因为任何类型都可以分配给 Dynamic http://haxe.org/manual/types-dynamic.html)。


可能不是 pritiest 解决方案,但简单的 TPath 检查是解决方法:

    case FFun(f):                   
        switch (f.ret) {
                case TPath({ name: "Array", pack: [], params: _ }):
                    trace("Yay!");
                default:                            
        }