2
0
Эх сурвалжийг харах

[inliner] find common type for rest args against monomorphs

see #10124
Simon Krajewski 4 жил өмнө
parent
commit
a6d72649b3

+ 16 - 9
src/optimization/inline.ml

@@ -483,8 +483,7 @@ class inline_state ctx ethis params cf f p = object(self)
 			set_inlined_vars args1 args2;
 			set_inlined_vars args1 args2;
 			Some vthis
 			Some vthis
 
 
-	method finalize config e tl tret p =
-		let has_params,map_type = match config with Some config -> config | None -> inline_default_config cf ethis.etype in
+	method finalize e tl tret has_params map_type p =
 		if self#had_side_effect then List.iter (fun (l,e) ->
 		if self#had_side_effect then List.iter (fun (l,e) ->
 			if self#might_be_affected e && not (ExtType.has_value_semantics e.etype) then l.i_force_temp <- true;
 			if self#might_be_affected e && not (ExtType.has_value_semantics e.etype) then l.i_force_temp <- true;
 		) _inlined_vars;
 		) _inlined_vars;
@@ -650,7 +649,8 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 		| None -> raise Exit
 		| None -> raise Exit
 		| Some e -> Some e)
 		| Some e -> Some e)
 	with Exit ->
 	with Exit ->
-	let params = inline_rest_params ctx f params p in
+	let has_params,map_type = match config with Some config -> config | None -> inline_default_config cf ethis.etype in
+	let params = inline_rest_params ctx f params map_type p in
 	let state = new inline_state ctx ethis params cf f p in
 	let state = new inline_state ctx ethis params cf f p in
 	let vthis_opt = state#initialize in
 	let vthis_opt = state#initialize in
 	let opt f = function
 	let opt f = function
@@ -849,7 +849,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 		| _ -> []
 		| _ -> []
 	in
 	in
 	let tl = arg_types params f.tf_args in
 	let tl = arg_types params f.tf_args in
-	let e = state#finalize config e tl tret p in
+	let e = state#finalize e tl tret has_params map_type p in
 	if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin
 	if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin
 		let se t = s_expr_pretty true t true (s_type (print_context())) in
 		let se t = s_expr_pretty true t true (s_type (print_context())) in
 		print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s"
 		print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s"
@@ -884,7 +884,7 @@ and type_inline_ctor ctx c cf tf ethis el po =
 	in
 	in
 	type_inline ctx cf tf ethis el ctx.t.tvoid None po true
 	type_inline ctx cf tf ethis el ctx.t.tvoid None po true
 
 
-and inline_rest_params ctx f params p =
+and inline_rest_params ctx f params map_type p =
 	if not ctx.com.config.pf_supports_rest_args then
 	if not ctx.com.config.pf_supports_rest_args then
 		params
 		params
 	else
 	else
@@ -897,16 +897,23 @@ and inline_rest_params ctx f params p =
 				| [{ eexpr = TUnop(Spread,Prefix,e) }] -> [e]
 				| [{ eexpr = TUnop(Spread,Prefix,e) }] -> [e]
 				(* In other cases: `haxe.Rest.of([param1, param2, ...])` *)
 				(* In other cases: `haxe.Rest.of([param1, param2, ...])` *)
 				| _ ->
 				| _ ->
-					match follow v.v_type with
-					| TAbstract ({ a_path = ["haxe"],"Rest"; a_impl = Some c } as a, [t]) as rest_t ->
+					match follow (map_type v.v_type) with
+					| TAbstract ({ a_path = ["haxe"],"Rest"; a_impl = Some c } as a, [t]) ->
 						let cf =
 						let cf =
 							try PMap.find "of" c.cl_statics
 							try PMap.find "of" c.cl_statics
 							with Not_found -> die ~p:c.cl_name_pos "Can't find haxe.Rest.of function" __LOC__
 							with Not_found -> die ~p:c.cl_name_pos "Can't find haxe.Rest.of function" __LOC__
 						and p = punion_el (List.map (fun e -> (),e.epos) params) in
 						and p = punion_el (List.map (fun e -> (),e.epos) params) in
 						(* [param1, param2, ...] *)
 						(* [param1, param2, ...] *)
-						let array = mk (TArrayDecl params) (ctx.t.tarray t) p in
+						(* If we don't know the type (e.g. the rest argument is a field type parameter) then we need
+						   to find a common type via unify_min. *)
+						let t_params = match follow t with
+							| TMono _ -> unify_min ctx params
+							| _ -> t
+						in
+						let array = mk (TArrayDecl params) (ctx.t.tarray t_params) p in
 						(* haxe.Rest.of(array) *)
 						(* haxe.Rest.of(array) *)
-						[make_static_call ctx c cf (apply_params a.a_params [t]) [array] rest_t p]
+						let e = make_static_call ctx c cf (apply_params a.a_params [t]) [array] (TAbstract(a,[t_params])) p in
+						[e]
 					| _ ->
 					| _ ->
 						die ~p:v.v_pos "Unexpected rest arguments type" __LOC__
 						die ~p:v.v_pos "Unexpected rest arguments type" __LOC__
 				)
 				)

+ 31 - 0
tests/unit/src/unit/issues/Issue10124.hx

@@ -0,0 +1,31 @@
+package unit.issues;
+
+import utest.Assert;
+
+using unit.issues.Issue10124.Util;
+
+private class Util {
+	public static inline function add<T>(arr:Array<T>,...values:T) {
+		for (v in values)
+			arr.push(v);
+	}
+
+	public static inline function addFloat<T>(arr:Array<Any>,...values:Float) {
+		for (v in values)
+			arr.push(v);
+	}
+}
+
+class Issue10124 extends Test {
+	function test1() {
+		var arr = [1, 3, 4];
+		arr.add(5, 6, 7);
+		Assert.same([1, 3, 4, 5, 6, 7], arr);
+	}
+
+	function test2() {
+		var arr = [1, 3, 4];
+		arr.addFloat(5, 6, 7);
+		Assert.same([1, 3, 4, 5, 6, 7], arr);
+	}
+}