HaxeFoundation / haxe

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

Can't use mixed arrays with macros #11681

Closed Sword352 closed 5 days ago

Sword352 commented 1 month ago

For some reason it's impossible to pass a mixed array when doing a macro call with the @:build metadata.

Example:

class Macro {
  #if macro
    public static function build(array:Array<Dynamic>):Array<haxe.macro.Expr.Field> {
      return haxe.macro.Context.getBuildFields();
    }
  #end
}
@:build(Macro.build(["hi", "hello", 0]))
class Test {
  static function main() {
    trace("Haxe is great!");
  }
}

Output:

[ERROR] Test.hx:1: characters 37-38

 1 | @:build(Macro.build(["hi", "hello", 0]))
   |                                     ^
   | Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>

[ERROR] Test.hx:1: characters 37-38

 1 | @:build(Macro.build(["hi", "hello", 0]))
   |                                     ^
   | Int should be String
   | For function argument 'array'

What I also find weird is the fact that the value's type seems to be resolved. I rather have an anonymous structure on my end, with a dynamic value field. When hovering the anon structure in my IDE, value is displayed with a type of Int when it's value is equal to 0, for example. On plain context it would be displayed with the Dynamic type no matter what.

filt3rek commented 1 month ago

Hej,

A workaround could be something like that : https://try.haxe.org/#28E4147C

@:build(Macro.build("hi", "hello", 0))
class Test {
  static function main() {
    trace("Haxe is great!");
  }
}
import haxe.macro.Expr;
using haxe.macro.ExprTools;
class Macro {
  #if macro
    public static function build(...args:Expr):Array<Field> {
      var a = args.toArray().map( e->e.getValue() );
      trace( a );
      return haxe.macro.Context.getBuildFields();
    }
  #end
}
Sword352 commented 5 days ago

Turns out this is normal behaviour