Browse Source

[macro] handle rest args for macros
by replacing `Rest<Expr>` with `Array<Expr>` in signatures (fixes #10012)

Aleksandr Kuzmenko 4 years ago
parent
commit
fb67f3cac0
2 changed files with 31 additions and 0 deletions
  1. 12 0
      src/typing/macroContext.ml
  2. 19 0
      tests/unit/src/unit/issues/Issue10012.hx

+ 12 - 0
src/typing/macroContext.ml

@@ -600,6 +600,18 @@ type macro_arg_type =
 
 let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	let mctx, (margs,mret,mclass,mfield), call_macro = load_macro ctx (mode = MDisplay) cpath f p in
+	let margs =
+		(*
+			Replace "rest:haxe.Rest<Expr>" in macro signatures with "rest:Array<Expr>".
+			This allows to avoid handling special cases for rest args in macros during typing.
+		*)
+		match List.rev margs with
+		| (n,o,t) :: margs_rev ->
+			(match follow t with
+			| TAbstract ({ a_path = ["haxe"],"Rest" }, [t1]) -> List.rev ((n,o,mctx.t.tarray t1) :: margs_rev)
+			| _ -> margs)
+		| _ -> margs
+	in
 	let mpos = mfield.cf_pos in
 	let ctexpr = mk_type_path (["haxe";"macro"],"Expr") in
 	let expr = Typeload.load_instance mctx (ctexpr,p) false in

+ 19 - 0
tests/unit/src/unit/issues/Issue10012.hx

@@ -0,0 +1,19 @@
+package unit.issues;
+
+#if !macro
+class Issue10012 extends unit.Test {
+	function test() {
+		var s = format("foo", 1, true, a);
+		aeq(['"foo"', '1', 'true', 'a'], s);
+	}
+
+	macro static function format(...exprs:haxe.macro.Expr):haxe.macro.Expr;
+}
+#else
+class Issue10012 extends unit.Test {
+	macro static function format(...exprs:haxe.macro.Expr):haxe.macro.Expr {
+		var strings = exprs.toArray().map(e -> macro $v{haxe.macro.ExprTools.toString(e)});
+		return macro $a{strings};
+	}
+}
+#end