calling a macro function next to an unrelated genericBuild class

49 views
Skip to first unread message

Munir Hussin

unread,
Apr 20, 2016, 2:09:44 PM4/20/16
to Haxe
Hello. I'm refactoring my codes and changing stuff from hardcoded Foo1<T0>, Foo2<T0,T1> ... into Foo<Rest> using genericBuild to automatically create those FooN classes as needed.

However, I ran into a strange error, and I'm unsure if it's due to a mistake in my macro builder or if its a bug.

Here's a simplified version of the code to show the error:

Foo.hx:

package;

import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;

using haxe.macro.TypeTools;
using haxe.macro.ComplexTypeTools;

@:genericBuild(FooMacro.build())
class Foo<Rest>
{
    public function new() trace("foo!");
}

class FooMacro
{
    public static var cache = new Map<Int, Bool>();
    
    public static macro function build():ComplexType
    {
        return switch(Context.getLocalType())
        {
            case TInst(_.get() => { name: "Foo" }, params):
                buildClass(params);
                
            case t:
                throw 'Incompatible type: $t';
        }
    }
    
    public static function buildClass(params:Array<Type>):ComplexType
    {
        var pos = Context.currentPos();
        var n = params.length;
        var className = 'Foo$n';
        
        if (!cache.exists(n))
        {
            var fields = Context.getBuildFields();
            
            Context.defineType(
            {
                pack: [],
                name: className,
                pos: pos,
                params: [for (i in 0...n) { name: 'T$i' }],
                kind: TDClass(),
                fields: fields
            });
            
            cache[n] = true;
        }
        
        return TPath({pack: [], name: className, params: [for (t in params) TPType(t.toComplexType())]});
    }
}


Main.hx

class Main
{
    
    public static function main()
    {
        var a = new Foo<Int, Int>();  // comment this, uncomment below: works
        bar();                        // comment this, uncomment above: works
                                      // both lines uncomment: error
    }
    
    // Calling this macro function results in an error
    // at the line with `new Foo<Int, Int>()`
    //    Unknown<0> cannot be constructed
    // The bar macro function has nothing to do with Foo
    public static macro function bar()
    {
        return macro null;
    }
}


Anyone knows how can I fix this? Thanks in advance.


Ben Merckx

unread,
Apr 20, 2016, 6:19:36 PM4/20/16
to Haxe
Mixing genericBuild classes and macros in the same context can mess things up. I believe the next haxe release has a proper compile time error for this. The easiest way to fix this is to move the bar method to a seperate class. If you wish to keep it there you'll have to mark every usage of Foo (the import statement as well) in #if !macro ... #end

Munir Hussin

unread,
Apr 20, 2016, 7:31:25 PM4/20/16
to Haxe
Both your suggestions worked. I didn't need to mark out the import statement of Foo, it somehow works too. Thanks! Much appreciated.
Reply all
Reply to author
Forward
0 new messages