Browse Source

Deprecate Std.instance; Add Std.downcast (#8301)

* deprecate Std.instance; add Std.downcast

* fix Std.downcast() for interfaces on js

* fix cs

* fix python

* test failures on unrelated types

* fix cs

* [js] don't list `__isInterface__` in Type.getClassFields()
Aleksandr Kuzmenko 6 years ago
parent
commit
1bcb3a91d6

+ 2 - 1
src/generators/genhl.ml

@@ -2037,7 +2037,8 @@ and eval_expr ctx e =
 		get_enum_index ctx v
 		get_enum_index ctx v
 	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Type" },{ cf_name = "enumIndex" })) },[v]) when (match follow v.etype with TEnum _ -> true | _ -> false) ->
 	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Type" },{ cf_name = "enumIndex" })) },[v]) when (match follow v.etype with TEnum _ -> true | _ -> false) ->
 		get_enum_index ctx v
 		get_enum_index ctx v
-	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Std" },{ cf_name = "instance" })) },[v;vt]) ->
+	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Std" },{ cf_name = "instance" })) },[v;vt])
+	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Std" },{ cf_name = "downcast" })) },[v;vt]) ->
 		let r = eval_expr ctx v in
 		let r = eval_expr ctx v in
 		hold ctx r;
 		hold ctx r;
 		let c = eval_to ctx vt (class_type ctx ctx.base_type [] false) in
 		let c = eval_to ctx vt (class_type ctx ctx.base_type [] false) in

+ 9 - 0
src/generators/genjs.ml

@@ -1104,6 +1104,13 @@ let generate_class___name__ ctx c =
 		newline ctx;
 		newline ctx;
 	end
 	end
 
 
+let generate_class___isInterface__ ctx c =
+	if c.cl_interface && has_feature ctx "js.Boot.isInterface" then begin
+		let p = s_path ctx c.cl_path in
+		print ctx "%s.__isInterface__ = true" p;
+		newline ctx;
+	end
+
 let generate_class_es3 ctx c =
 let generate_class_es3 ctx c =
 	let p = s_path ctx c.cl_path in
 	let p = s_path ctx c.cl_path in
 	if ctx.js_flatten then
 	if ctx.js_flatten then
@@ -1130,6 +1137,7 @@ let generate_class_es3 ctx c =
 		newline ctx;
 		newline ctx;
 	end;
 	end;
 	generate_class___name__ ctx c;
 	generate_class___name__ ctx c;
+	generate_class___isInterface__ ctx c;
 
 
 	if ctx.has_instanceof then
 	if ctx.has_instanceof then
 		(match c.cl_implements with
 		(match c.cl_implements with
@@ -1284,6 +1292,7 @@ let generate_class_es6 ctx c =
 	end;
 	end;
 
 
 	generate_class___name__ ctx c;
 	generate_class___name__ ctx c;
+	generate_class___isInterface__ ctx c;
 
 
 	if ctx.has_instanceof then
 	if ctx.has_instanceof then
 		(match c.cl_implements with
 		(match c.cl_implements with

+ 4 - 0
src/generators/genpy.ml

@@ -2127,6 +2127,10 @@ module Generator = struct
 					use_pass := false;
 					use_pass := false;
 					print ctx "\n    _hx_class_name = \"%s\"" p_name
 					print ctx "\n    _hx_class_name = \"%s\"" p_name
 				end;
 				end;
+				if has_feature ctx "python._hx_is_interface" then begin
+					let value = if c.cl_interface then "True" else "False" in
+					print ctx "\n    _hx_is_interface = \"%s\"" value
+				end;
 
 
 				let print_field names field quote =
 				let print_field names field quote =
 					if has_feature ctx ("python." ^ field) then try
 					if has_feature ctx ("python." ^ field) then try

+ 4 - 1
src/macro/eval/evalStdLib.ml

@@ -2108,12 +2108,14 @@ module StdStd = struct
 		| _ -> vfalse
 		| _ -> vfalse
 	)
 	)
 
 
-	let instance = vfun2 (fun v t -> match t with
+	let downcast = vfun2 (fun v t -> match t with
 		| VPrototype proto ->
 		| VPrototype proto ->
 			if is v proto.ppath then v else vnull
 			if is v proto.ppath then v else vnull
 		| _ -> vfalse
 		| _ -> vfalse
 	)
 	)
 
 
+	let instance = downcast
+
 	let string = vfun1 (fun v -> match v with
 	let string = vfun1 (fun v -> match v with
 		| VString _ -> v
 		| VString _ -> v
 		| _ -> vstring (s_value 0 v)
 		| _ -> vstring (s_value 0 v)
@@ -3507,6 +3509,7 @@ let init_standard_library builtins =
 		"shutdown",StdSocket.shutdown;
 		"shutdown",StdSocket.shutdown;
 	];
 	];
 	init_fields builtins ([],"Std") [
 	init_fields builtins ([],"Std") [
+		"downcast",StdStd.downcast;
 		"instance",StdStd.instance;
 		"instance",StdStd.instance;
 		"int",StdStd.int;
 		"int",StdStd.int;
 		"is",StdStd.is';
 		"is",StdStd.is';

+ 3 - 0
std/Std.hx

@@ -49,6 +49,9 @@ extern class Std {
 		If `value` is null, the result is null. If `c` is null, the result is
 		If `value` is null, the result is null. If `c` is null, the result is
 		unspecified.
 		unspecified.
 	**/
 	**/
+	public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S;
+
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
 	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S;
 	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S;
 
 
 	/**
 	/**

+ 6 - 1
std/cpp/_std/Std.hx

@@ -26,10 +26,15 @@
 		return untyped __global__.__instanceof(v,t);
 		return untyped __global__.__instanceof(v,t);
 	}
 	}
 
 
-	@:keep public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	@:keep public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return Std.is(value, c) ? cast value : null;
 		return Std.is(value, c) ? cast value : null;
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	@:keep public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return inline downcast(value, c);
+	}
+
 	@:keep public static function string( s : Dynamic ) : String {
 	@:keep public static function string( s : Dynamic ) : String {
 		return untyped s==null ? "null" : s.toString();
 		return untyped s==null ? "null" : s.toString();
 	}
 	}

+ 6 - 1
std/cs/_std/Std.hx

@@ -191,10 +191,15 @@ import cs.internal.Exceptions;
 			Math.NaN;
 			Math.NaN;
 	}
 	}
 
 
-	extern inline public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	extern inline public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return cs.Lib.as(value,c);
 		return cs.Lib.as(value,c);
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	extern inline public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value,c);
+	}
+
 	public static function random( x : Int ) : Int {
 	public static function random( x : Int ) : Int {
 		if (x <= 0) return 0;
 		if (x <= 0) return 0;
 		return untyped Math.rand.Next(x);
 		return untyped Math.rand.Next(x);

+ 6 - 1
std/flash/_std/Std.hx

@@ -27,10 +27,15 @@ import flash.Boot;
 		return untyped flash.Boot.__instanceof(v,t);
 		return untyped flash.Boot.__instanceof(v,t);
 	}
 	}
 
 
-	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	public static inline function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return flash.Lib.as(value, c);
 		return flash.Lib.as(value, c);
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value, c);
+	}
+
 	public static function string( s : Dynamic ) : String {
 	public static function string( s : Dynamic ) : String {
 		return untyped flash.Boot.__string_rec(s,"");
 		return untyped flash.Boot.__string_rec(s,"");
 	}
 	}

+ 6 - 1
std/hl/_std/Std.hx

@@ -64,7 +64,12 @@ class Std {
 		return t.check(v);
 		return t.check(v);
 	}
 	}
 
 
-	extern public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S;
+	extern public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S;
+
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value, c);
+	}
 
 
 	extern public static inline function int( x : Float ) : Int {
 	extern public static inline function int( x : Float ) : Int {
 		return untyped $int(x);
 		return untyped $int(x);

+ 1 - 1
std/hl/_std/String.hx

@@ -207,7 +207,7 @@ class String {
 	}
 	}
 
 
 	@:keep function __compare( v : Dynamic ) : Int {
 	@:keep function __compare( v : Dynamic ) : Int {
-		var s = Std.instance(v, String);
+		var s = Std.downcast(v, String);
 		if( s == null )
 		if( s == null )
 			return hl.Api.comparePointer(this, v);
 			return hl.Api.comparePointer(this, v);
 		#if (hl_ver >= version("1.10"))
 		#if (hl_ver >= version("1.10"))

+ 6 - 1
std/java/_std/Std.hx

@@ -183,10 +183,15 @@ import java.internal.Exceptions;
 			Math.NaN;
 			Math.NaN;
 	}
 	}
 
 
-	inline public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	inline public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return Std.is(value, c) ? cast value : null;
 		return Std.is(value, c) ? cast value : null;
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	inline public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value, c);
+	}
+
 	public static function random( x : Int ) : Int {
 	public static function random( x : Int ) : Int {
 		if (x <= 0) return 0;
 		if (x <= 0) return 0;
 		return Std.int(Math.random() * x);
 		return Std.int(Math.random() * x);

+ 8 - 0
std/js/Boot.hx

@@ -49,6 +49,10 @@ class Boot {
 		return untyped __define_feature__("js.Boot.isClass", o.__name__);
 		return untyped __define_feature__("js.Boot.isClass", o.__name__);
 	}
 	}
 
 
+	static inline function isInterface(o:Class<Dynamic>) : Bool {
+		return untyped __define_feature__("js.Boot.isInterface", o.__isInterface__);
+	}
+
 	static inline function isEnum(e:Dynamic) : Bool {
 	static inline function isEnum(e:Dynamic) : Bool {
 		return untyped __define_feature__("js.Boot.isEnum", e.__ename__);
 		return untyped __define_feature__("js.Boot.isEnum", e.__ename__);
 	}
 	}
@@ -213,6 +217,10 @@ class Boot {
 		}
 		}
 	}
 	}
 
 
+	static inline function __implements(o : Dynamic, t : Class<Dynamic>) : Bool {
+		return o != null && isInterface(t) && __interfLoop(getClass(o), t);
+	}
+
 	@:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) {
 	@:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) {
 		if (o == null || __instanceof(o, t)) return o;
 		if (o == null || __instanceof(o, t)) return o;
 		else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
 		else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);

+ 6 - 1
std/js/_std/Std.hx

@@ -28,8 +28,13 @@ import js.Boot;
 		return @:privateAccess js.Boot.__instanceof(v,t);
 		return @:privateAccess js.Boot.__instanceof(v,t);
 	}
 	}
 
 
+	public static inline function downcast<T:{},S:T>( value : T, c : Class<S> ) : S @:privateAccess {
+		return js.Syntax.instanceof(value, c) || Boot.__implements(value, c) ? cast value : null;
+	}
+
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
 	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
 	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
-		return js.Syntax.instanceof(value, c) ? cast value : null;
+		return downcast(value, c);
 	}
 	}
 
 
 	@:pure
 	@:pure

+ 1 - 0
std/js/_std/Type.hx

@@ -186,6 +186,7 @@ enum ValueType {
 		a.remove("hx__closures__");
 		a.remove("hx__closures__");
 		a.remove("__name__");
 		a.remove("__name__");
 		a.remove("__interfaces__");
 		a.remove("__interfaces__");
+		a.remove("__isInterface__");
 		a.remove("__properties__");
 		a.remove("__properties__");
 		a.remove("__instanceFields__");
 		a.remove("__instanceFields__");
 		a.remove("__super__");
 		a.remove("__super__");

+ 6 - 1
std/jvm/_std/Std.hx

@@ -93,10 +93,15 @@ class Std {
 		}
 		}
 	}
 	}
 
 
-	inline public static function instance<T:{}, S:T>(value:T, c:Class<S>):S {
+	inline public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return Std.is(value, c) ? cast value : null;
 		return Std.is(value, c) ? cast value : null;
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	inline public static function instance<T:{}, S:T>(value:T, c:Class<S>):S {
+		return downcast(value, c);
+	}
+
 	public static function random(x:Int):Int {
 	public static function random(x:Int):Int {
 		if (x <= 0) {
 		if (x <= 0) {
 			return 0;
 			return 0;

+ 6 - 1
std/lua/_std/Std.hx

@@ -29,10 +29,15 @@ import lua.NativeStringTools;
 		return untyped lua.Boot.__instanceof(v,t);
 		return untyped lua.Boot.__instanceof(v,t);
 	}
 	}
 
 
-	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	public static inline function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return untyped lua.Boot.__instanceof(value, c) ? cast value : null;
 		return untyped lua.Boot.__instanceof(value, c) ? cast value : null;
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value, c);
+	}
+
 	@:keep
 	@:keep
 	public static function string( s : Dynamic ) : String {
 	public static function string( s : Dynamic ) : String {
 		return untyped lua.Boot.__string_rec(s);
 		return untyped lua.Boot.__string_rec(s);

+ 6 - 1
std/neko/_std/Std.hx

@@ -26,10 +26,15 @@
 		return untyped neko.Boot.__instanceof(v,t);
 		return untyped neko.Boot.__instanceof(v,t);
 	}
 	}
 
 
-	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+	public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return Std.is(value, c) ? cast value : null;
 		return Std.is(value, c) ? cast value : null;
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return inline downcast(value, c);
+	}
+
 	public static function string( s : Dynamic ) : String {
 	public static function string( s : Dynamic ) : String {
 		return new String(untyped __dollar__string(s));
 		return new String(untyped __dollar__string(s));
 	}
 	}

+ 5 - 0
std/php/_std/Std.hx

@@ -32,6 +32,11 @@ import php.Syntax;
 		return Boot.is(v, t);
 		return Boot.is(v, t);
 	}
 	}
 
 
+	public static inline function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Boot.is(value, cast c) ? cast value : null;
+	}
+
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
 	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
 	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
 		return Boot.is(value, cast c) ? cast value : null;
 		return Boot.is(value, cast c) ? cast value : null;
 	}
 	}

+ 31 - 0
std/python/Boot.hx

@@ -455,4 +455,35 @@ class Boot {
 		return name;
 		return name;
 	}
 	}
 
 
+	static inline function implementsInterface(value:Dynamic, cls:Class<Dynamic>):Bool {
+		function loop (intf) {
+			var f:Array<Dynamic> = if (Internal.hasInterfaces(intf)) Internal.fieldInterfaces(intf) else [];
+			if (f != null) {
+				for (i in f) {
+					if ( i == cls) {
+						return true;
+					} else {
+						var l = loop(i);
+						if (l) {
+							return true;
+						}
+					}
+				}
+				return false;
+			} else {
+				return false;
+			}
+		}
+		var currentClass = Syntax.field(value, "__class__");
+		var result = false;
+		while(currentClass != null) {
+			if (loop(currentClass)) {
+				result = true;
+				break;
+			}
+			currentClass = getSuperClass(currentClass);
+		}
+		return result;
+	}
+
 }
 }

+ 9 - 30
std/python/_std/Std.hx

@@ -31,14 +31,20 @@ import python.Syntax;
 @:keepInit
 @:keepInit
 @:coreApi class Std {
 @:coreApi class Std {
 
 
-	public static inline function instance<T:{}, S:T>( value : T, c : Class<S> ) : S {
+	@:access(python.Boot)
+	public static function downcast<T:{},S:T>( value : T, c : Class<S> ) : S {
 		try {
 		try {
-			return UBuiltins.isinstance(value,c) ? cast value : null;
+			return UBuiltins.isinstance(value,c) || (Inspect.isInterface(c) && Boot.implementsInterface(value, c)) ? cast value : null;
 		} catch (e:Dynamic) {
 		} catch (e:Dynamic) {
 			return null;
 			return null;
 		}
 		}
 	}
 	}
 
 
+	@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
+	public static inline function instance<T:{}, S:T>( value : T, c : Class<S> ) : S {
+		return downcast(value, c);
+	}
+
 	@:access(python.Boot)
 	@:access(python.Boot)
 	static inline function isMetaType(v:Dynamic, t:Dynamic):Bool {
 	static inline function isMetaType(v:Dynamic, t:Dynamic):Bool {
 		return Boot.isMetaType(v,t);
 		return Boot.isMetaType(v,t);
@@ -95,34 +101,7 @@ import python.Syntax;
 		}
 		}
 
 
 		if (Inspect.isclass(t)) {
 		if (Inspect.isclass(t)) {
-
-			function loop (intf)
-			{
-				var f:Array<Dynamic> = if (Internal.hasInterfaces(intf)) Internal.fieldInterfaces(intf) else [];
-				if (f != null) {
-					for (i in f) {
-						if ( i == t) {
-							return true;
-						} else {
-							var l = loop(i);
-							if (l) {
-								return true;
-							}
-						}
-					}
-					return false;
-				} else {
-					return false;
-				}
-			}
-			var currentClass = Syntax.field(v, "__class__");
-			while(currentClass != null) {
-				if (loop(currentClass)) {
-					return true;
-				}
-				currentClass = python.Boot.getSuperClass(currentClass);
-			}
-			return false;
+			return Boot.implementsInterface(v, t);
 		} else {
 		} else {
 			return false;
 			return false;
 		}
 		}

+ 0 - 2
std/python/internal/Internal.hx

@@ -96,8 +96,6 @@ class Internal {
 		return macro @:pos(Context.currentPos()) python.Syntax.field($a{args});
 		return macro @:pos(Context.currentPos()) python.Syntax.field($a{args});
 	}
 	}
 
 
-
-
 	macro public static function importAsPrefixed (o:String, x:String) {
 	macro public static function importAsPrefixed (o:String, x:String) {
 		return macro @:pos(Context.currentPos()) python.Syntax.importAs($v{o}, $v{_prefix + x});
 		return macro @:pos(Context.currentPos()) python.Syntax.importAs($v{o}, $v{_prefix + x});
 	}
 	}

+ 4 - 0
std/python/lib/Inspect.hx

@@ -30,4 +30,8 @@ extern class Inspect {
 	static function isclass(object:Dynamic):Bool;
 	static function isclass(object:Dynamic):Bool;
 	static function isfunction(object:Dynamic):Bool;
 	static function isfunction(object:Dynamic):Bool;
 	static function getsourcefile(object:Dynamic):String;
 	static function getsourcefile(object:Dynamic):String;
+
+	static public inline function isInterface(cls:Class<Dynamic>):Bool {
+		return untyped __define_feature__("python._hx_is_interface", c._hx_is_interface);
+	}
 }
 }

+ 13 - 0
tests/misc/projects/Issue5946/Main.hx

@@ -0,0 +1,13 @@
+class Main {
+	@:analyzer(ignore)
+	static function main() {
+		Std.downcast((null:One), Two);
+		Std.downcast((null:IOne), ITwo);
+	}
+}
+
+class One {}
+class Two {}
+
+interface IOne {}
+interface ITwo {}

+ 1 - 0
tests/misc/projects/Issue5946/compile-fail.hxml

@@ -0,0 +1 @@
+-main Main

+ 4 - 0
tests/misc/projects/Issue5946/compile-fail.hxml.stderr

@@ -0,0 +1,4 @@
+Main.hx:5: characters 3-15 : Constraint check failure for downcast.S
+Main.hx:5: characters 3-15 : ITwo should be IOne
+Main.hx:4: characters 3-15 : Constraint check failure for downcast.S
+Main.hx:4: characters 3-15 : Two should be One

+ 6 - 2
tests/unit/src/unit/MyClass.hx

@@ -5,6 +5,10 @@ using MyClass.UsingBase;
 using MyClass.UsingChild1;
 using MyClass.UsingChild1;
 using MyClass.UsingChild2;
 using MyClass.UsingChild2;
 
 
+
+interface IMyParent {}
+interface IMyChild extends IMyParent {}
+
 class MyClass {
 class MyClass {
 
 
 	#if as3 public #end var val : Int;
 	#if as3 public #end var val : Int;
@@ -37,7 +41,7 @@ class MyParent {
 	function b() return 20;
 	function b() return 20;
 }
 }
 
 
-class MyChild1 extends MyParent {
+class MyChild1 extends MyParent implements IMyChild {
 	public override function a() { return 12; }
 	public override function a() { return 12; }
 	override function b() return 21;
 	override function b() return 21;
 	function c() return 19;
 	function c() return 19;
@@ -296,4 +300,4 @@ class InlineCastB extends InlineCastA {
 	public function quote() {
 	public function quote() {
 		return "I am the greatest.";
 		return "I am the greatest.";
 	}
 	}
-}
+}

+ 1 - 1
tests/unit/src/unit/TestInterface.hx

@@ -84,7 +84,7 @@ class TestInterface extends Test {
 		eq( (py:Dynamic).getY(), 5 );
 		eq( (py:Dynamic).getY(), 5 );
 		eq( (py:Dynamic).foo(), "bar" );
 		eq( (py:Dynamic).foo(), "bar" );
 
 
-		var p2 = Std.instance(px,Point);
+		var p2 = Std.downcast(px,Point);
 		eq( p, p2 );
 		eq( p, p2 );
 		eq( cast(py,IX), px );
 		eq( cast(py,IX), px );
 
 

+ 5 - 5
tests/unit/src/unit/issues/Issue3403.hx

@@ -3,29 +3,29 @@ package unit.issues;
 class Issue3403 extends Test  {
 class Issue3403 extends Test  {
 	function test() {
 	function test() {
 		var val = [1,2,3,4];
 		var val = [1,2,3,4];
-		var x = Std.instance(val, Array);
+		var x = Std.downcast(val, Array);
 		eq(val,x);
 		eq(val,x);
 
 
 		var val:Dynamic = val;
 		var val:Dynamic = val;
-		x = Std.instance(val,Array);
+		x = Std.downcast(val,Array);
 		eq(val,x);
 		eq(val,x);
 		t(val != null);
 		t(val != null);
 		t(x != null);
 		t(x != null);
 
 
 		var g = new G([1,2,3,4]);
 		var g = new G([1,2,3,4]);
 		var g2:Dynamic = g;
 		var g2:Dynamic = g;
-		var g3:G<Array<Int>> = Std.instance(g2,G);
+		var g3:G<Array<Int>> = Std.downcast(g2,G);
 		eq(g,g2);
 		eq(g,g2);
 		eq(g,g3);
 		eq(g,g3);
 		t(g3 != null);
 		t(g3 != null);
 		t(g != null);
 		t(g != null);
 
 
 		g2 = "Incorrect type";
 		g2 = "Incorrect type";
-		g3 = Std.instance(g2,G);
+		g3 = Std.downcast(g2,G);
 		eq(g3,null);
 		eq(g3,null);
 
 
 		g2 = 10;
 		g2 = 10;
-		g3 = Std.instance(g2,G);
+		g3 = Std.downcast(g2,G);
 		eq(g3,null);
 		eq(g3,null);
 	}
 	}
 }
 }

+ 8 - 5
tests/unit/src/unitstd/Std.unit.hx

@@ -17,14 +17,17 @@ var unknown = null;
 
 
 // instance
 // instance
 #if !js
 #if !js
-Std.instance("", String) == "";
+Std.downcast("", String) == "";
 #end
 #end
 var a = [];
 var a = [];
-Std.instance(a, Array) == a;
+Std.downcast(a, Array) == a;
 var parent:unit.MyClass.MyParent = new MyClass.MyChild1();
 var parent:unit.MyClass.MyParent = new MyClass.MyChild1();
-Std.instance(parent, unit.MyClass.MyChild1) != null;
-Std.instance(null, Array) == null;
-Std.instance(null, String) == null;
+Std.downcast(parent, unit.MyClass.MyChild1) != null;
+Std.downcast(null, Array) == null;
+Std.downcast(null, String) == null;
+
+var parent:unit.MyClass.IMyParent = new MyClass.MyChild1();
+Std.downcast(parent, unit.MyClass.IMyChild) != null;
 
 
 // string
 // string
 var cwts = new ClassWithToString();
 var cwts = new ClassWithToString();