فهرست منبع

[java/cs] Make sure to reset old values when resizing a map

Closes #5862
Cauê Waneck 8 سال پیش
والد
کامیت
679e657839

+ 18 - 2
src/generators/gencommon/castDetect.ml

@@ -334,6 +334,17 @@ let rec handle_cast gen e real_to_t real_from_t =
 		| TInst( { cl_path = ([], "String") }, []), _ ->
 			mk_cast false to_t e
 		| TInst( ({ cl_path = (["cs"|"java"], "NativeArray") } as c_array), [tp_to] ), TInst({ cl_path = (["cs"|"java"], "NativeArray") }, [tp_from]) when not (type_iseq gen (gen.greal_type tp_to) (gen.greal_type tp_from)) ->
+				(* when running e.g. var nativeArray:NativeArray<Dynamic> = @:privateAccess someIntMap.vals, we end up with a bad cast because of the type parameters differences *)
+				(* se clean these kinds of casts *)
+				let rec clean_cast e = match e.eexpr with
+					| TCast(expr,_) -> (match gen.greal_type e.etype with
+						| TInst({ cl_path = (["cs"|"java"],"NativeArray") }, _) ->
+							clean_cast expr
+						| _ ->
+							e)
+					| TParenthesis(e) | TMeta(_,e) -> clean_cast e
+					| _ -> e
+				in
 			(* see #5751 . NativeArray is special because of its ties to Array. We could potentially deal with this for all *)
 			(* TNew expressions, but it's not that simple, since we don't want to retype the whole expression list with the *)
 			(* updated type. *)
@@ -341,7 +352,11 @@ let rec handle_cast gen e real_to_t real_from_t =
 				| TNew(c,_,el) when c == c_array ->
 					mk_cast false (TInst(c_array,[tp_to])) { e with eexpr = TNew(c, [tp_to], el); etype = TInst(c_array,[tp_to]) }
 				| _ ->
-					mk_cast true to_t e)
+					try
+						type_eq gen EqRightDynamic tp_from tp_to;
+						e
+					with | Unify_error _ ->
+						mk_cast false to_t (clean_cast e))
 
 		| TInst(cl_to, params_to), TInst(cl_from, params_from) ->
 			let ret = ref None in
@@ -1195,9 +1210,10 @@ let configure gen ?(overloads_cast_to_base = false) maybe_empty_t calls_paramete
 						| (TInst(c,tl) as tinst1), TAbstract({ a_path = ["cs"],"Pointer" }, [tinst2]) when type_iseq gen tinst1 (gen.greal_type tinst2) ->
 							run expr
 						| _ ->
+							let expr = run expr in
 							let last_unsafe = gen.gon_unsafe_cast in
 							gen.gon_unsafe_cast <- (fun t t2 pos -> ());
-							let ret = handle (run expr) e.etype expr.etype in
+							let ret = handle expr e.etype expr.etype in
 							gen.gon_unsafe_cast <- last_unsafe;
 							match ret.eexpr with
 								| TCast _ -> { ret with etype = gen.greal_type e.etype }

+ 3 - 1
std/cs/_std/haxe/ds/IntMap.hx

@@ -291,6 +291,8 @@ import cs.NativeArray;
 					var key = _keys[j];
 					var val = vals[j];
 
+					_keys[j] = 0;
+					vals[j] = cast null;
 					setIsDelTrue(flags, j);
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{
@@ -362,7 +364,7 @@ import cs.NativeArray;
 	{
 		return new IntMapValueIterator(this);
 	}
-	
+
 	public function copy() : IntMap<T> {
 		var copied = new IntMap<T>();
 		for(key in keys()) copied.set(key, get(key));

+ 3 - 1
std/cs/_std/haxe/ds/ObjectMap.hx

@@ -219,6 +219,8 @@ import cs.NativeArray;
 					var key = _keys[j];
 					var val = vals[j];
 
+					_keys[j] = null;
+					vals[j] = cast null;
 					hashes[j] = FLAG_DEL;
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{
@@ -392,7 +394,7 @@ import cs.NativeArray;
 	{
 		return new ObjectMapValueIterator(this);
 	}
-	
+
 	public function copy() : ObjectMap<K,V> {
 		var copied = new ObjectMap<K, V>();
 		for(key in keys()) copied.set(key, get(key));

+ 2 - 0
std/cs/_std/haxe/ds/StringMap.hx

@@ -218,6 +218,8 @@ import cs.NativeArray;
 					var key = _keys[j];
 					var val = vals[j];
 
+					_keys[j] = null;
+					vals[j] = cast null;
 					hashes[j] = FLAG_DEL;
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{

+ 3 - 1
std/java/_std/haxe/ds/IntMap.hx

@@ -273,6 +273,8 @@ import java.NativeArray;
 					var key = _keys[j];
 					var val = vals[j];
 
+					_keys[j] = 0;
+					vals[j] = cast null;
 					setIsDelTrue(flags, j);
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{
@@ -385,7 +387,7 @@ import java.NativeArray;
 			}
 		};
 	}
-	
+
 	public function copy() : IntMap<T> {
 		var copied = new IntMap();
 		for(key in keys()) copied.set(key, get(key));

+ 4 - 2
std/java/_std/haxe/ds/ObjectMap.hx

@@ -211,6 +211,8 @@ import java.NativeArray;
 					var key = _keys[j];
 					var val = vals[j];
 
+					_keys[j] = null;
+					vals[j] = cast null;
 					hashes[j] = FLAG_DEL;
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{
@@ -409,8 +411,8 @@ import java.NativeArray;
 			}
 		};
 	}
-	
-	
+
+
 	public function copy() : ObjectMap<K,V> {
 		var copied = new ObjectMap();
 		for(key in keys()) copied.set(key, get(key));

+ 3 - 2
std/java/_std/haxe/ds/WeakMap.hx

@@ -245,6 +245,7 @@ import java.lang.ref.ReferenceQueue;
 				{
 					var entry = entries[j];
 
+					entries[j] = null;
 					hashes[j] = FLAG_DEL;
 					while (true) /* kick-out process; sort of like in Cuckoo hashing */
 					{
@@ -447,8 +448,8 @@ import java.lang.ref.ReferenceQueue;
 			}
 		};
 	}
-	
-	
+
+
 	public function copy() : WeakMap<K,V> {
 		var copied = new WeakMap();
 		for(key in keys()) copied.set(key, get(key));

+ 107 - 0
tests/unit/src/unit/issues/Issue5862.hx

@@ -0,0 +1,107 @@
+package unit.issues;
+import haxe.ds.*;
+#if java
+import java.NativeArray;
+#elseif cs
+import cs.NativeArray;
+#end
+
+class Issue5862 extends Test {
+#if (java || cs)
+  public function test() {
+    var imap = new IntMap();
+    imap.set(0, "val1");
+    imap.set(1, "val2");
+    imap.set(2, "val3");
+    imap.set(2, "changed_val3");
+
+    var v:Vector<Dynamic> = cast @:privateAccess imap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val3");
+    }
+
+    var smap = new StringMap();
+    smap.set("v1", "val1");
+    smap.set("v2", "val2");
+    smap.set("v3", "val3");
+    smap.set("v3", "changed_val3");
+
+    var v:Vector<Dynamic> = cast @:privateAccess smap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val3");
+    }
+
+    var omap = new ObjectMap<{}, String>();
+    omap.set(imap, "val1");
+    omap.set(smap, "val2");
+    omap.set(omap, "val3");
+    omap.set(omap, "changed_val3");
+
+    var v:Vector<Dynamic> = cast @:privateAccess omap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val3");
+    }
+#if java
+    var wmap = new WeakMap<{}, String>();
+    wmap.set(imap, "val1");
+    wmap.set(smap, "val2");
+    wmap.set(omap, "val3");
+    wmap.set(omap, "changed_val3");
+
+    var v = @:privateAccess wmap.entries;
+    for (i in 0...v.length) {
+      t(v[i] == null || v[i].value != "val3");
+    }
+#end
+
+    var imap = new IntMap();
+    imap.set(0, "val1");
+    imap.set(1, "val2");
+    imap.set(2, "val3");
+    imap.set(2, "changed_val3");
+    imap.set(1, "changed_val2");
+
+    var v:Vector<Dynamic> = cast @:privateAccess imap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val2");
+    }
+
+    var smap = new StringMap();
+    smap.set("v1", "val1");
+    smap.set("v2", "val2");
+    smap.set("v3", "val3");
+    smap.set("v3", "changed_val3");
+    smap.set("v2", "changed_val2");
+
+    var v:Vector<Dynamic> = cast @:privateAccess smap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val2");
+    }
+
+    var omap = new ObjectMap<{}, String>();
+    omap.set(imap, "val1");
+    omap.set(smap, "val2");
+    omap.set(omap, "val3");
+    omap.set(omap, "changed_val3");
+    omap.set(smap, "changed_val2");
+
+    var v:Vector<Dynamic> = cast @:privateAccess omap.vals;
+    for (i in 0...v.length) {
+      t(v[i] != "val2");
+    }
+#if java
+    var wmap = new WeakMap<{}, String>();
+    wmap.set(imap, "val1");
+    wmap.set(smap, "val2");
+    wmap.set(omap, "val3");
+    wmap.set(omap, "changed_val3");
+    wmap.set(smap, "changed_val2");
+
+    var v = @:privateAccess wmap.entries;
+    for (i in 0...v.length) {
+      t(v[i] == null || v[i].value != "val2");
+    }
+#end
+  }
+#end
+}