Sfoglia il codice sorgente

[jvm] rework Rest implementation

closes #10761
closes #10906
Simon Krajewski 2 anni fa
parent
commit
97cc13b7dd

+ 17 - 31
src/generators/genjvm.ml

@@ -168,12 +168,6 @@ let rec jsignature_of_type gctx stack t =
 				| [t] -> TArray(jsignature_of_type t,None)
 				| _ -> die "" __LOC__
 				end
-			| ["haxe"],"Rest" ->
-				begin match tl with
-				| [t] -> TArray(get_boxed_type (jsignature_of_type t),None)
-				| _ -> die "" __LOC__
-				end
-			(* | ["haxe"],"Rest" -> TArray(object_sig,None) *)
 			| [],"Dynamic" ->
 				object_sig
 			| [],("Class" | "Enum") ->
@@ -215,8 +209,6 @@ let rec jsignature_of_type gctx stack t =
 		jsig
 	) tl) (return_of_type gctx stack tr)
 	| TAnon an -> object_sig
-	| TType({ t_path = ["haxe"],"Rest$NativeRest" },[t]) ->
-		TArray(get_boxed_type (jsignature_of_type t),None)
 	| TType(td,tl) ->
 		begin match gctx.typedef_interfaces#get_interface_class td.t_path with
 		| Some c -> TObject(c.cl_path,[])
@@ -269,13 +261,13 @@ module AnnotationHandler = struct
 			| EField(e1,s,_) ->
 				let path = parse_path e1 in
 				AEnum(object_path_sig path,s)
-			| ECall(e1, el) -> 
+			| ECall(e1, el) ->
 				let path = parse_path e1 in
 				let _,name = ExtString.String.replace (snd path) "." "$" in
 				let path = (fst path, name) in
-				let values = List.map parse_value_pair el in 
-				AAnnotation(TObject(path, []),values)	
-				
+				let values = List.map parse_value_pair el in
+				AAnnotation(TObject(path, []),values)
+
 			| _ -> Error.typing_error "Expected value expression" (pos e)
 		and parse_value_pair e = match fst e with
 			| EBinop(OpAssign,(EConst(Ident s),_),e1) ->
@@ -1471,7 +1463,7 @@ class texpr_to_jvm
 					| TUnop (Spread,_,e) ->
 						self#texpr (rvalue_sig jsig) e
 					| _ ->
-						self#new_native_array (get_boxed_type (jsignature_of_type gctx t1)) (e :: el)
+						self#new_native_array (jsignature_of_type gctx t1) (e :: el)
 					);
 					List.rev (jsig :: acc)
 				| _ ->
@@ -1488,7 +1480,7 @@ class texpr_to_jvm
 				(match Type.follow t with
 				| TAbstract({a_path = ["haxe"],"Rest"},[t1]) ->
 					let jsig = jsignature_of_type gctx t in
-					self#new_native_array (get_boxed_type (jsignature_of_type gctx t1)) [];
+					self#new_native_array (jsignature_of_type gctx t1) [];
 					List.rev (jsig :: acc)
 				| _ -> List.rev acc)
 			| _,[] -> List.rev acc
@@ -1589,16 +1581,6 @@ class texpr_to_jvm
 			| _ ->
 				Error.typing_error (Printf.sprintf "Bad __array__ type: %s" (s_type (print_context()) tr)) e1.epos;
 			end
-		| TField(_,FStatic({cl_path = (["haxe"],"Rest$Rest_Impl_")},{cf_name = "createNative"})) ->
-			begin match tr, el with
-			| TType({ t_path = ["haxe"],"Rest$NativeRest" },[t]), [e2] ->
-				self#texpr (if need_val ret then rvalue_any else RVoid) e2;
-				let jsig = get_boxed_type (self#vtype t) in
-				ignore(NativeArray.create jm#get_code jc#get_pool jsig);
-				Some (array_sig jsig)
-			| _ ->
-				Error.typing_error (Printf.sprintf "Bad __array__ type: %s" (s_type (print_context()) tr)) e1.epos;
-			end
 		| TField(_,FStatic({cl_path = (["haxe"],"EnumTools")}, {cf_name = "values"})) ->
 			begin match el with
 			| [e1] ->
@@ -1748,7 +1730,16 @@ class texpr_to_jvm
 			end
 		| _ ->
 			self#texpr rvalue_any e1;
-			invoke e1.etype;
+			let t = match e1.eexpr with
+				| TLocal ({v_extra = Some {v_params = l}} as v) when l <> [] ->
+					(* If we call a local variable with type parameters, we want to use the general (unapplied)
+					   type, which is the variable type itself. This is necessary for some special situations
+					   like the Rest<T> case in issue #10906. *)
+					v.v_type
+				| _ ->
+					e1.etype
+			in
+			invoke t;
 		in
 		match need_val ret,tro with
 		| false,Some _ -> code#pop
@@ -2051,12 +2042,7 @@ class texpr_to_jvm
 			| TInst({cl_path = (["java"],"NativeArray")},[t]) ->
 				self#texpr rvalue_any e1;
 				let vt = self#vtype e1.etype in
-				let vte =
-					let vte = self#vtype t in
-					match e1.etype with
-					| TType ({ t_path = ["haxe"],"Rest$NativeRest" },_) -> get_boxed_type vte
-					| _ -> vte
-				in
+				let vte = self#vtype t in
 				self#texpr rvalue_any e2;
 				self#read_native_array vt vte
 			| t ->

+ 0 - 6
std/java/_std/haxe/Rest.hx

@@ -17,11 +17,6 @@ abstract Rest<T>(NativeRest<T>) {
 	inline function get_length():Int
 		return this.length;
 
-	#if jvm
-	@:from static public function of<T>(array:Array<T>):Rest<T> {
-		return new Rest(@:privateAccess array.__a);
-	}
-	#else
 	@:from extern inline static public function of<T>(array:Array<T>):Rest<T> {
 		var result = createNative(array.length);
 		var src:NativeArray<Object> = cast @:privateAccess array.__a;
@@ -29,7 +24,6 @@ abstract Rest<T>(NativeRest<T>) {
 			result[i] = cast src[i];
 		return new Rest(result);
 	}
-	#end
 
 	@:noDoc
 	@:generic

+ 61 - 0
std/jvm/_std/haxe/Rest.hx

@@ -0,0 +1,61 @@
+package haxe;
+
+import haxe.ds.Vector;
+import haxe.iterators.RestIterator;
+import haxe.iterators.RestKeyValueIterator;
+
+private typedef NativeRest<T> = Vector<T>;
+
+@:coreApi
+abstract Rest<T>(NativeRest<T>) {
+	public var length(get, never):Int;
+
+	inline function get_length():Int
+		return this.length;
+
+	inline function new(a:NativeRest<T>) {
+		this = a;
+	}
+
+	@:arrayAccess inline function get(index:Int):T
+		return this[index];
+
+	@:from extern inline static public function of<T>(array:Array<T>):Rest<T> {
+		var result = new NativeRest(array.length);
+		for (i in 0...array.length)
+			result[i] = array[i];
+		return new Rest(result);
+	}
+
+	@:from extern inline static function fromNative<T>(a:java.NativeArray<T>):Rest<T> {
+		return new Rest(Vector.fromData(a));
+	}
+
+	extern inline public function append(item:T):Rest<T> {
+		var r = new NativeRest(length + 1);
+		Vector.blit(this, 0, r, 0, length);
+		r[length] = item;
+		return new Rest(r);
+	}
+
+	extern inline public function prepend(item:T):Rest<T> {
+		var r = new NativeRest(length + 1);
+		Vector.blit(this, 0, r, 1, length);
+		r[0] = item;
+		return new Rest(r);
+	}
+
+	public inline function iterator():RestIterator<T>
+		return new RestIterator<T>(this);
+
+	public inline function keyValueIterator():RestKeyValueIterator<T>
+		return new RestKeyValueIterator<T>(this);
+
+	@:to public inline function toArray():Array<T> {
+		return [for (i in 0...this.length) this[i]];
+	}
+
+	public inline function toString():String {
+		return toArray().toString();
+	}
+}

+ 2 - 2
tests/unit/src/unit/issues/Issue10124.hx

@@ -5,12 +5,12 @@ import utest.Assert;
 using unit.issues.Issue10124.Util;
 
 private class Util {
-	public static inline function add<T>(arr:Array<T>,...values:T) {
+	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) {
+	public static inline function addFloat<T>(arr:Array<Any>, ...values:Float) {
 		for (v in values)
 			arr.push(v);
 	}

+ 15 - 0
tests/unit/src/unit/issues/Issue10761.hx

@@ -0,0 +1,15 @@
+package unit.issues;
+
+import haxe.Rest;
+
+class Issue10761 extends Test {
+	function rest(args:Rest<Int>) {
+		return args;
+	}
+
+	function test() {
+		aeq([0, 1], rest(0, 1)); // works
+		aeq([0, 1], rest(...[0, 1])); // works
+		aeq([0, 1], rest(...[for (i in 0...2) i])); // errors
+	}
+}