소스 검색

unit tests for cast to interface (#7658)

* unit tests for cast to interface

* always allow cast null in js/lua

* Update TestCasts.hx

* disable as3 for now

* don't test null

* [eval] collect interface chains

* try to enable as3 again

* [cpp] fix block-level safe-casts

* try to figure out Java/C#

* not like this

* [lua] add proper cast behavior inside blocks
Nicolas Cannasse 6 년 전
부모
커밋
80f42bdc38

+ 1 - 1
src/codegen/gencommon/expressionUnwrap.ml

@@ -292,7 +292,7 @@ and expr_kind expr =
 		| TObjectDecl (sel) ->
 			aggregate true (List.map snd sel)
 		| TCast (e,_) ->
-			aggregate true [e]
+			aggregate false [e]
 		| _ -> trace (debug_expr expr); assert false (* should have been read as Statement by shallow_expr_type *)
 
 let get_kinds (statement:texpr) =

+ 3 - 2
src/generators/gencpp.ml

@@ -3088,7 +3088,8 @@ let retype_expression ctx request_type function_args function_type expression_tr
                baseCpp.cppexpr, baseCpp.cpptype (* nothing to do *)
             else (match return_type with
             | TCppNativePointer(klass) -> CppCastNative(baseCpp), return_type
-            | TCppVoid -> baseCpp.cppexpr, TCppVoid
+            | TCppVoid ->
+				CppTCast(baseCpp, cpp_type_of expr.etype), return_type
             | TCppDynamic ->
                   baseCpp.cppexpr, baseCpp.cpptype
             | _ ->
@@ -7387,7 +7388,7 @@ class script_writer ctx filename asciiOut =
       this#gen_expression expr;
    end
 
-   method gen_func_args args = 
+   method gen_func_args args =
       let gen_inits = ref [] in
       List.iter (fun(arg,init) ->
          this#write (indent ^ indent_str );

+ 1 - 1
src/generators/gencs.ml

@@ -3107,7 +3107,7 @@ let generate con =
 
 		ExpressionUnwrap.configure gen;
 
-		UnnecessaryCastsRemoval.configure gen;
+		(* UnnecessaryCastsRemoval.configure gen; *)
 
 		IntDivisionSynf.configure gen;
 

+ 1 - 1
src/generators/genjava.ml

@@ -2585,7 +2585,7 @@ let generate con =
 
 	ExpressionUnwrap.configure gen;
 
-	UnnecessaryCastsRemoval.configure gen;
+	(* UnnecessaryCastsRemoval.configure gen; *)
 
 	IntDivisionSynf.configure gen;
 

+ 7 - 1
src/generators/genlua.ml

@@ -1044,7 +1044,13 @@ and gen_block_element ctx e  =
     begin match e.eexpr with
         | TTypeExpr _ | TConst _ | TLocal _ | TFunction _ ->
             ()
-        | TCast (e',_) | TParenthesis e' | TMeta (_,e') ->
+        | TCast (e1, Some t)->
+            print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" }));
+            gen_expr ctx e1;
+            spr ctx " , ";
+            spr ctx (ctx.type_accessor t);
+            spr ctx ")"
+        | TCast (e', None) | TParenthesis e' | TMeta (_,e') ->
             gen_block_element ctx e'
         | TArray (e1,e2) ->
             gen_block_element ctx e1;

+ 5 - 1
src/macro/eval/evalPrototype.ml

@@ -186,7 +186,11 @@ let create_static_prototype ctx mt =
 			| None -> None
 			| Some(csup,_) -> Some (get_static_prototype ctx (path_hash csup.cl_path) c.cl_pos)
 		in
-		let interfaces = List.map (fun (c,_) -> path_hash c.cl_path) c.cl_implements in
+		let rec collect_interfaces acc (c,_) =
+			let acc = List.fold_left (fun acc c -> collect_interfaces acc c) acc c.cl_implements in
+			path_hash c.cl_path :: acc
+		in
+		let interfaces = collect_interfaces [] (c,[]) in
 		let pctx = PrototypeBuilder.create ctx key pparent (PClass interfaces) meta in
 		let fields = List.filter (fun cf -> not (is_removable_field cf)) c.cl_ordered_statics in
 		let delays = DynArray.create() in

+ 1 - 1
std/js/Boot.hx

@@ -215,7 +215,7 @@ class Boot {
 	}
 
 	@:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) {
-		if (__instanceof(o, t)) return o;
+		if (o == null || __instanceof(o, t)) return o;
 		else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
 	}
 

+ 1 - 1
std/lua/Boot.hx

@@ -135,7 +135,7 @@ class Boot {
 
 	@:ifFeature("typed_cast")
 	private static function __cast(o : Dynamic, t : Dynamic) {
-		if (__instanceof(o, t)) return o;
+		if (o == null || __instanceof(o, t)) return o;
 		else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
 	}
 

+ 26 - 1
tests/unit/src/unit/TestCasts.hx

@@ -13,4 +13,29 @@ class TestCasts extends Test  {
 		eq( f(123), 123);
 	}
 
-}
+	function testInterfaces() {
+
+		var v = new MyClass.CI1();
+		eq( cast(v,MyClass.I1), v );
+		exc( function() cast(v,MyClass.I2) );
+
+		var v = new MyClass.ClassI2();
+		eq( cast(v,MyClass.I1), v );
+		eq( cast(v,MyClass.I2), v );
+
+		var v = cast(v,MyClass.I2);
+		eq( cast(v,MyClass.I1), v );
+		exc( function() cast(v,MyClass.CovI) );
+
+		var v : MyClass.CovI = new MyClass.Cov2();
+		eq( cast(v,MyClass.CovI), v );
+
+		var v = new MyClass.Cov3();
+		eq( cast(v,MyClass.CovI), v );
+		eq( cast(v,MyClass.CovI2), v );
+
+		exc(function() { cast(new MyClass.Cov1(), MyClass.CovI); });
+
+	}
+
+}