Selaa lähdekoodia

[cs] Various enum-related fixes:

- Generate all non-@:nativeGen enums as classes (See #3338, Closes
- [java/cs] Cleanup how enums and enums with parameters are generated; use Vector
instead of array
- Do not make any assumptions about how the enums will be laid out at
runtime (Closes #2931)
- Added test for #3389
Cauê Waneck 10 vuotta sitten
vanhempi
commit
90ddbdfa14

+ 31 - 37
gencommon.ml

@@ -631,6 +631,9 @@ and gen_classes =
 	cl_dyn : tclass;
 
 	t_iterator : tdef;
+
+	a_vector : tabstract;
+	tvector : Type.t -> Type.t;
 }
 
 (* add here all reflection transformation additions *)
@@ -687,6 +690,9 @@ let new_ctx con =
 			cl_dyn = cl_dyn;
 
 			t_iterator = get_tdef (get_type con.types ([], "Iterator"));
+
+			a_vector = get_abstract (get_type con.types (["haxe";"ds"],"Vector"));
+			tvector = (fun t -> TAbstract(gen.gclasses.a_vector,[t]));
 		};
 		gtools = {
 			r_create_empty = (fun eclass t ->
@@ -8939,6 +8945,7 @@ struct
 		dependencies:
 			Should run before ReflectionCFs, in order to enable proper reflection access.
 			Should run before TypeParams.RealTypeParams.RealTypeParamsModf, since generic enums must be first converted to generic classes
+			It needs that the target platform implements __array__() as a shortcut to declare haxe.ds.Vector
 	*)
 
 	module EnumToClassModf =
@@ -8954,7 +8961,7 @@ struct
 			let has_meta meta = List.exists (fun (m,_,_) -> match m with Meta.Custom _ -> true | _ -> false) meta in
 			has_meta en.e_meta || pmap_exists (fun _ ef -> has_meta ef.ef_meta) en.e_constrs
 
-		let convert gen t base_class en should_be_hxgen handle_type_params =
+		let convert gen t base_class base_param_class en should_be_hxgen handle_type_params =
 			let basic = gen.gcon.basic in
 			let pos = en.e_pos in
 
@@ -8971,7 +8978,9 @@ struct
 				| _ -> ()
 			);
 
-			cl.cl_super <- Some(base_class,[]);
+			let super, has_params = if Meta.has Meta.FlatEnum en.e_meta then base_class, false else base_param_class, true in
+
+			cl.cl_super <- Some(super,[]);
 			cl.cl_extern <- en.e_extern;
 			en.e_extern <- true;
 			en.e_meta <- (Meta.Class, [], pos) :: en.e_meta;
@@ -9019,7 +9028,12 @@ struct
 						cf.cf_meta <- [];
 
 						let tf_args = List.map (fun (name,opt,t) ->  (alloc_var name t, if opt then Some TNull else None) ) params in
-						let arr_decl = { eexpr = TArrayDecl(List.map (fun (v,_) -> mk_local v pos) tf_args); etype = basic.tarray t_empty; epos = pos } in
+						let special = alloc_var "__array__" t_dynamic in
+						let arr_decl = {
+							eexpr = TCall(mk_local special pos, List.map (fun (v,_) -> mk_local v pos) tf_args);
+							etype = gen.gclasses.tvector t_dynamic;
+							epos = pos
+						} in
 						let expr = {
 							eexpr = TFunction({
 								tf_args = tf_args;
@@ -9036,10 +9050,15 @@ struct
 							| TEnum(e, p) -> TEnum(e, List.map (fun _ -> t_dynamic) p)
 							| _ -> assert false
 						in
-						let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNormal }) [] in
-						cf.cf_meta <- [];
+						let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
+						let args = if has_params then
+							[mk_int gen old_i pos; null (gen.gclasses.tvector t_dynamic) pos]
+						else
+							[mk_int gen old_i pos]
+						in
+						cf.cf_meta <- [Meta.ReadOnly,[],pos];
 						cf.cf_expr <- Some {
-							eexpr = TNew(cl, List.map (fun _ -> t_empty) cl.cl_params, [mk_int gen old_i pos; { eexpr = TArrayDecl []; etype = basic.tarray t_empty; epos = pos }]);
+							eexpr = TNew(cl, List.map (fun _ -> t_empty) cl.cl_params, args);
 							etype = TInst(cl, List.map (fun _ -> t_empty) cl.cl_params);
 							epos = pos;
 						};
@@ -9090,32 +9109,7 @@ struct
 			cl.cl_fields <- PMap.add "getTag" getTag_cf cl.cl_fields;
 			cl.cl_overrides <- getTag_cf :: cl.cl_overrides;
 
-			(if should_be_hxgen then
-				cl.cl_meta <- (Meta.HxGen,[],cl.cl_pos) :: cl.cl_meta
-			else begin
-				(* create the constructor *)
-				let tf_args = [ alloc_var "index" basic.tint, None; alloc_var "params" (basic.tarray t_empty), None ] in
-				let ftype = TFun(fun_args tf_args, basic.tvoid) in
-				let ctor = mk_class_field "new" ftype true pos (Method MethNormal) [] in
-				let me = TInst(cl, List.map snd cl.cl_params) in
-				ctor.cf_expr <-
-				Some {
-					eexpr = TFunction(
-					{
-						tf_args = tf_args;
-						tf_type = basic.tvoid;
-						tf_expr = mk_block {
-							eexpr = TCall({ eexpr = TConst TSuper; etype = me; epos = pos }, List.map (fun (v,_) -> mk_local v pos) tf_args);
-							etype = basic.tvoid;
-							epos = pos;
-						}
-					});
-					etype = ftype;
-					epos = pos
-				};
-
-				cl.cl_constructor <- Some ctor
-			end);
+			if should_be_hxgen then cl.cl_meta <- (Meta.HxGen,[],cl.cl_pos) :: cl.cl_meta;
 			gen.gadd_to_module (TClassDecl cl) (max_dep);
 
 			TEnumDecl en
@@ -9128,8 +9122,8 @@ struct
 				enum_base_class : tclass - the enum base class.
 				should_be_hxgen : bool - should the created enum be hxgen?
 		*)
-		let traverse gen t convert_all convert_if_has_meta enum_base_class should_be_hxgen handle_tparams =
-			let convert e = convert gen t enum_base_class e should_be_hxgen handle_tparams in
+		let traverse gen t convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams =
+			let convert e = convert gen t enum_base_class param_enum_class e should_be_hxgen handle_tparams in
 			let run md = match md with
 				| TEnumDecl e when is_hxgen md ->
 					if convert_all then
@@ -9202,7 +9196,7 @@ struct
 						with Not_found ->
 							f
 						in
-						let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gcon.basic.tarray t_empty } in
+						let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.tvector t_dynamic } in
 						{ e with eexpr = TArray(cond_array, mk_int gen i cond_array.epos); }
 					| _ -> Type.map_expr run e
 			in
@@ -9215,9 +9209,9 @@ struct
 
 	end;;
 
-	let configure gen opt_get_native_enum_tag convert_all convert_if_has_meta enum_base_class should_be_hxgen handle_tparams =
+	let configure gen opt_get_native_enum_tag convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams =
 		let t = new_t () in
-		EnumToClassModf.configure gen (EnumToClassModf.traverse gen t convert_all convert_if_has_meta enum_base_class should_be_hxgen handle_tparams);
+		EnumToClassModf.configure gen (EnumToClassModf.traverse gen t convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams);
 		EnumToClassExprf.configure gen (EnumToClassExprf.traverse gen t opt_get_native_enum_tag)
 
 end;;

+ 9 - 2
gencs.ml

@@ -2653,7 +2653,9 @@ let configure gen =
 
 	ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (get_cl (get_type gen (["haxe";"lang"],"Function")) ));
 
-	EnumToClass.configure gen (Some (fun e -> mk_cast gen.gcon.basic.tint e)) false true (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) true false;
+	let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
+	let param_enum_base = (get_cl (get_type gen (["haxe";"lang"],"ParamEnum")) ) in
+	EnumToClass.configure gen (Some (fun e -> mk_cast gen.gcon.basic.tint e)) true true enum_base param_enum_base true false;
 
 	InterfaceVarsDeleteModf.configure gen;
 	InterfaceProps.configure gen;
@@ -3271,7 +3273,12 @@ let get_cls = function
 	| _,_,c -> c
 
 let convert_ilenum ctx p ilcls =
-	let meta = ref [Meta.Native, [EConst (String (ilpath_s ilcls.cpath) ), p], p ] in
+	let meta = ref [
+		Meta.Native, [EConst (String (ilpath_s ilcls.cpath) ), p], p;
+		Meta.Enum, [], p;
+		Meta.CsNative, [], p;
+		Meta.Extern, [], p; (* abstracts can't be externs *)
+	] in
 	let data = ref [] in
 	List.iter (fun f -> match f.fname with
 		| "value__" -> ()

+ 3 - 1
genjava.ml

@@ -1917,7 +1917,9 @@ let configure gen =
 
 	ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (get_cl (get_type gen (["haxe";"lang"],"Function")) ));
 
-	EnumToClass.configure gen (None) false true (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) false false;
+	let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
+	let param_enum_base = (get_cl (get_type gen (["haxe";"lang"],"ParamEnum")) ) in
+	EnumToClass.configure gen (None) false true enum_base param_enum_base false false;
 
 	InterfaceVarsDeleteModf.configure gen;
 

+ 14 - 3
optimizer.ml

@@ -53,10 +53,21 @@ let mk_untyped_call name p params =
 
 let api_inline ctx c field params p =
 	match c.cl_path, field, params with
-	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)
+	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match ctx.com.platform with
+		| Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) ->
+			(* We don't want to optimize enums from external sources; as they might change unexpectedly *)
+			(* and since native C# enums don't have the concept of index - they have rather a value, *)
+			(* which can't be mapped to a native API - this kind of substitution is dangerous *)
+			None
+		| _ ->
+			Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p))
 	| ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)
+		(match ctx.com.platform with
+			| Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) ->
+				(* see comment above *)
+				None
+			| _ ->
+				Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p))
 	| ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] ->
 		Some { e with epos = p }
 	| ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l ->

+ 4 - 4
std/cs/_std/Type.hx

@@ -177,14 +177,14 @@ using StringTools;
 	@:functionCode('
 		if (name == "Bool") return typeof(bool);
 		System.Type t = resolveClass(name);
-		if (t != null && (t.BaseType.Equals(typeof(System.Enum)) || t.BaseType.Equals(typeof(haxe.lang.Enum))))
+		if (t != null && (t.BaseType.Equals(typeof(System.Enum)) || (typeof(haxe.lang.Enum)).IsAssignableFrom(t)))
 			return t;
 		return null;
 	')
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	{
-		if (name == "Bool") return Bool;
-		return cast resolveClass(name);
+		return null;
+		// if (ret != null && (ret.BaseType.Equals(cs.Lib.toNativeType(cs.system.Enum)) || ret.IsAssignableFrom(cs.Lib.toNativeType(haxe.
 	}
 
 	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T
@@ -385,7 +385,7 @@ using StringTools;
 	}
 
 	@:functionCode('
-		return ( e is System.Enum ) ? new Array<object>() : ((haxe.lang.Enum) e).@params;
+		return ( e is System.Enum ) ? new Array<object>() : ((haxe.lang.Enum) e).getParams();
 	')
 	public static function enumParameters( e : EnumValue ) : Array<Dynamic> untyped
 	{

+ 1 - 1
std/cs/internal/FieldLookup.hx

@@ -120,4 +120,4 @@ package cs.internal;
 		return ~min;
 	}
 
-}
+}

+ 37 - 10
std/cs/internal/HxObject.hx

@@ -21,6 +21,7 @@
  */
 package cs.internal;
 import cs.system.Type;
+import haxe.ds.Vector;
 private typedef StdType = std.Type;
 
 @:keep @:native('haxe.lang.HxObject')
@@ -67,27 +68,52 @@ private class DynamicObject extends HxObject implements Dynamic
 {
 }
 
-@:native('haxe.lang.Enum')
-@:keep @:skipCtor
+@:keep @:native('haxe.lang.Enum') @:nativeGen
 #if core_api_serialize
 @:meta(System.Serializable)
 #end
 private class Enum
 {
 	@:readOnly private var index(default,never):Int;
-	@:readOnly private var params(default,never):Array<{}>;
 
-	public function new(index:Int, params:Array<{}>)
+	public function new(index:Int)
 	{
 		untyped this.index = index;
-		untyped this.params = params;
 	}
+
 	public function getTag():String
 	{
-		var cl:Dynamic = StdType.getClass(this);
-		return cl.constructs[index];
+		return throw 'Not Implemented';
+	}
+
+	public function getParams():Array<{}>
+	{
+		return [];
 	}
+
 	public function toString():String
+	{
+		return getTag();
+	}
+}
+
+@:keep @:native('haxe.lang.ParamEnum') @:nativeGen
+private class ParamEnum extends Enum
+{
+	@:readOnly private var params(default,never):Vector<Dynamic>;
+
+	public function new(index:Int, params:Vector<Dynamic>)
+	{
+		super(index);
+		untyped this.params = params;
+	}
+
+	override public function getParams():Array<{}>
+	{
+		return params == null ? [] : cs.Lib.array(params.toData());
+	}
+
+	override public function toString():String
 	{
 		if (params == null || params.length == 0) return getTag();
 		var ret = new StringBuf();
@@ -104,11 +130,12 @@ private class Enum
 		ret.add(")");
 		return ret.toString();
 	}
+
 	public function Equals(obj:Dynamic)
 	{
 		if (obj == this) //we cannot use == as .Equals !
 			return true;
-		var obj:Enum = cast obj;
+		var obj:ParamEnum = Std.instance(obj, ParamEnum);
 		var ret = obj != null && Std.is(obj, StdType.getClass(this)) && obj.index == this.index;
 		if (!ret)
 			return false;
@@ -127,12 +154,12 @@ private class Enum
 
 	public function GetHashCode():Int
 	{
-		var h = 19;
+		var h:Int = 19;
 		if (params != null) for (p in params)
 		{
 			h = h * 31;
 			if (p != null)
-				h += untyped p.GetHashCode();
+				untyped h += p.GetHashCode();
 		}
 		h += index;
 		return h;

+ 1 - 1
std/cs/internal/StringExt.hx

@@ -23,7 +23,7 @@ package cs.internal;
 import cs.internal.Function;
 private typedef NativeString = String;
 
-@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt
+@:keep @:nativeGen @:native("haxe.lang.StringExt") class StringExt
 {
 
 	@:functionCode('

+ 2 - 2
std/java/_std/Type.hx

@@ -119,7 +119,7 @@
 	@:functionCode('
 		if ("Bool".equals(name)) return boolean.class;
 		Class r = resolveClass(name);
-		if (r != null && (r.getSuperclass() == java.lang.Enum.class || r.getSuperclass() == haxe.lang.Enum.class))
+		if (r != null && (r.getSuperclass() == java.lang.Enum.class || haxe.lang.Enum.class.isAssignableFrom(r)))
 			return r;
 		return null;
 	')
@@ -398,7 +398,7 @@
 	}
 
 	@:functionCode('
-		return ( e instanceof java.lang.Enum ) ? new haxe.root.Array() : ((haxe.lang.Enum) e).params;
+		return ( e instanceof java.lang.Enum ) ? new haxe.root.Array() : ((haxe.lang.Enum) e).getParams();
 	')
 	public static function enumParameters( e : EnumValue ) : Array<Dynamic> untyped
 	{

+ 37 - 11
std/java/internal/HxObject.hx

@@ -21,6 +21,8 @@
  */
 package java.internal;
 import java.internal.IEquatable;
+import haxe.ds.Vector;
+
 private typedef StdType = Type;
 
 @:native('haxe.lang.HxObject')
@@ -64,26 +66,49 @@ private class DynamicObject extends HxObject implements Dynamic
 	}
 }
 
-@:native('haxe.lang.Enum')
-//@:skipCtor
-@:nativeGen
-@:keep
+@:keep @:native('haxe.lang.Enum') @:nativeGen
 private class Enum
 {
 	@:readOnly private var index(default,never):Int;
-	@:readOnly private var params(default,never):Array<{}>;
 
-	public function new(index:Int, params:Array<{}>)
+	public function new(index:Int)
 	{
 		untyped this.index = index;
-		untyped this.params = params;
 	}
+
 	public function getTag():String
 	{
-		var cl:Dynamic = StdType.getEnum(cast this);
-		return cl.constructs[index];
+		return throw 'Not Implemented';
 	}
+
+	public function getParams():Array<{}>
+	{
+		return [];
+	}
+
 	public function toString():String
+	{
+		return getTag();
+	}
+}
+
+@:keep @:native('haxe.lang.ParamEnum') @:nativeGen
+private class ParamEnum extends Enum
+{
+	@:readOnly private var params(default,never):Vector<Dynamic>;
+
+	public function new(index:Int, params:Vector<Dynamic>)
+	{
+		super(index);
+		untyped this.params = params;
+	}
+
+	override public function getParams():Array<{}>
+	{
+		return params == null ? [] : cast params.toArray();
+	}
+
+	override public function toString():String
 	{
 		if (params == null || params.length == 0) return getTag();
 		var ret = new StringBuf();
@@ -100,11 +125,12 @@ private class Enum
 		ret.add(")");
 		return ret.toString();
 	}
+
 	public function equals(obj:Dynamic)
 	{
 		if (obj == this) //we cannot use == as .Equals !
 			return true;
-		var obj:Enum = cast obj;
+		var obj:ParamEnum = Std.is(obj,ParamEnum) ? cast obj : null;
 		var ret = obj != null && Std.is(obj, StdType.getEnum(cast this)) && obj.index == this.index;
 		if (!ret)
 			return false;
@@ -128,7 +154,7 @@ private class Enum
 		{
 			h = h * 31;
 			if (p != null)
-				h += untyped p.hashCode();
+				untyped h += p.hashCode();
 		}
 		h += index;
 		return h;

+ 9 - 0
tests/unit/native_cs/src/haxe/test/TEnumWithValue.cs

@@ -6,4 +6,13 @@ public enum TEnumWithValue
 	TVA = 0x100,TVB = 0x1,TVD = 0x10, TVC = 0x20
 }
 
+public enum TEnumWithBigValue : ulong
+{
+	TBA = 0x1000000000L, 
+	TBD = 0x200000000000L, 
+	TBB = 0x100000000L, 
+	TBC = 0x3000000000000L, 
+}
+
 }
+

+ 30 - 22
tests/unit/src/unit/TestCSharp.hx

@@ -4,6 +4,7 @@ import haxe.test.Base;
 import haxe.test.Base.Base_InnerClass;
 import haxe.test.TEnum;
 import haxe.test.TEnumWithValue;
+import haxe.test.TEnumWithBigValue;
 import haxe.test.IEditableTextBuffer;
 import haxe.test.LowerCaseClass;
 
@@ -302,32 +303,34 @@ class TestCSharp extends Test
 		}
 		eq("TA",Type.enumConstructor(e));
 
-		eq(0, Type.enumIndex(TEnum.TA));
-		eq(0, Type.enumIndex(getTA()));
-		eq(3, Type.enumIndex(TEnumWithValue.TVA));
-		eq(3, Type.enumIndex(getTVA()));
+		eq(Type.enumIndex(getTA()), Type.enumIndex(TEnum.TA));
+		eq(Type.enumIndex(getTVA()), Type.enumIndex(TEnumWithValue.TVA));
+		eq(Type.enumIndex(getTBA()), Type.enumIndex(TEnumWithBigValue.TBA));
 
-		eq(0, Type.enumIndex(TEnumWithValue.TVB));
-		eq(0, Type.enumIndex(getTVB()));
-		eq(1, Type.enumIndex(TEnum.TB));
-		eq(1, Type.enumIndex(getTB()));
+		eq(Type.enumIndex(getTVB()), Type.enumIndex(TEnumWithValue.TVB));
+		eq(Type.enumIndex(getTBB()), Type.enumIndex(TEnumWithBigValue.TBB));
+		eq(Type.enumIndex(getTB()), Type.enumIndex(TEnum.TB));
 
-		eq(2, Type.enumIndex(TEnum.TC));
-		eq(2, Type.enumIndex(getTC()));
-		eq(2, Type.enumIndex(TEnumWithValue.TVC));
-		eq(2, Type.enumIndex(getTVC()));
+		eq(Type.enumIndex(getTC()), Type.enumIndex(TEnum.TC));
+		eq(Type.enumIndex(getTVC()), Type.enumIndex(TEnumWithValue.TVC));
+		eq(Type.enumIndex(getTBC()), Type.enumIndex(TEnumWithBigValue.TBC));
 
-		eq(1, Type.enumIndex(TEnumWithValue.TVD));
-		eq(1, Type.enumIndex(getTVD()));
+		eq(Type.enumIndex(getTVD()), Type.enumIndex(TEnumWithValue.TVD));
+		eq(Type.enumIndex(getTBD()), Type.enumIndex(TEnumWithBigValue.TBD));
 
-		checkEnum(TEnum,0,TEnum.TA);
-		checkEnum(TEnum,1,TEnum.TB);
-		checkEnum(TEnum,2,TEnum.TC);
+		checkEnum(TEnum,TEnum.TA);
+		checkEnum(TEnum,TEnum.TB);
+		checkEnum(TEnum,TEnum.TC);
 
-		checkEnum(TEnumWithValue,3,TEnumWithValue.TVA);
-		checkEnum(TEnumWithValue,0,TEnumWithValue.TVB);
-		checkEnum(TEnumWithValue,2,TEnumWithValue.TVC);
-		checkEnum(TEnumWithValue,1,TEnumWithValue.TVD);
+		checkEnum(TEnumWithValue,TEnumWithValue.TVA);
+		checkEnum(TEnumWithValue,TEnumWithValue.TVB);
+		checkEnum(TEnumWithValue,TEnumWithValue.TVC);
+		checkEnum(TEnumWithValue,TEnumWithValue.TVD);
+
+		checkEnum(TEnumWithBigValue,TEnumWithBigValue.TBA);
+		checkEnum(TEnumWithBigValue,TEnumWithBigValue.TBB);
+		checkEnum(TEnumWithBigValue,TEnumWithBigValue.TBC);
+		checkEnum(TEnumWithBigValue,TEnumWithBigValue.TBD);
 	}
 
 	private static function getArray(arr:cs.system.Array)
@@ -335,18 +338,23 @@ class TestCSharp extends Test
 		return [ for (i in 0...arr.Length) arr.GetValue(i) ];
 	}
 
-	function checkEnum<T>(e:Enum<T>,idx:Int,v:T,?pos:haxe.PosInfos)
+	function checkEnum<T : EnumValue>(e:Enum<T>,v:T,?pos:haxe.PosInfos)
 	{
+		var idx = Type.enumIndex(v);
 		eq(v,Type.createEnumIndex(e,idx),pos);
 	}
 
 	function getTA() return TEnum.TA;
 	function getTVA() return TEnumWithValue.TVA;
+	function getTBA() return TEnumWithBigValue.TBA;
 	function getTB() return TEnum.TB;
 	function getTVB() return TEnumWithValue.TVB;
+	function getTBB() return TEnumWithBigValue.TBB;
 	function getTC() return TEnum.TC;
 	function getTVC() return TEnumWithValue.TVC;
+	function getTBC() return TEnumWithBigValue.TBC;
 	function getTVD() return TEnumWithValue.TVD;
+	function getTBD() return TEnumWithBigValue.TBD;
 
 	@:skipReflection private function refTest(i:cs.Ref<Int>):Void
 	{

+ 22 - 0
tests/unit/src/unit/issues/Issue3389.hx

@@ -0,0 +1,22 @@
+package unit.issues;
+
+class Issue3389 extends Test
+{
+	public function test()
+	{
+		eq(Type.allEnums(ETest).join(','),'A,B');
+		eq(Type.allEnums(ETest2).join(','),'A2,B2');
+	}
+}
+
+private enum ETest
+{
+	A;
+	B;
+}
+
+@:nativeGen private enum ETest2
+{
+	A2;
+	B2;
+}

+ 21 - 0
tests/unit/src/unit/issues/Issue3860.hx

@@ -0,0 +1,21 @@
+package unit.issues;
+
+class Issue3860 extends Test
+{
+	public function test()
+	{
+		var a = ETest.A;
+		t(Std.is(a,ETest));
+		f(Std.is(a,Int));
+
+		var dyn:Dynamic = a;
+		t(Std.is(dyn,ETest));
+		f(Std.is(dyn,Int));
+	}
+}
+
+private enum ETest
+{
+	A;
+	B;
+}