Browse Source

[typer] disallow `implements Dynamic` on non-extern classes

see #6191
see #6586
Simon Krajewski 7 years ago
parent
commit
db08b2fd72

+ 1 - 0
extra/CHANGES.txt

@@ -13,6 +13,7 @@ XXXX-XX-XX:
 
 	all : disallowed get_x/set_x property syntax (#4699)
 	all : disallowed default values on interface variables (#4087)
+	all : disallowed `implements Dynamic` on non-extern classes (#6191)
 
 	Bugfixes:
 

+ 0 - 1
src/codegen/codegen.ml

@@ -339,7 +339,6 @@ module Dump = struct
 				print "%s%s%s%s %s%s" (s_metas c.cl_meta "") (if c.cl_private then "private " else "") (if c.cl_extern then "extern " else "") (if c.cl_interface then "interface" else "class") (s_type_path path) (params c.cl_params);
 				(match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));
 				List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements;
-				(match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t));
 				(match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t));
 				print " {\n";
 				(match c.cl_constructor with

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

@@ -687,7 +687,7 @@ let implement_final_lookup ctx cl =
 	let pos = cl.cl_pos in
 	let is_override = is_override cl in
 
-	let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in
+	(* let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in *)
 
 	let mk_throw str pos =
 		let e = ctx.rcf_mk_exception str pos in

+ 1 - 13
src/codegen/genxml.ml

@@ -236,11 +236,7 @@ let rec gen_type_decl com pos t =
 		let meta = gen_meta c.cl_meta in
 		let ext = (if c.cl_extern then [("extern","1")] else []) in
 		let interf = (if c.cl_interface then [("interface","1")] else []) in
-		let dynamic = (match c.cl_dynamic with
-			| None -> []
-			| Some t -> [node "haxe_dynamic" [] [gen_type t]]
-		) in
-		node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_params c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta @ dynamic)
+		node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_params c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta)
 	| TEnumDecl e ->
 		let doc = gen_doc_opt e.e_doc in
 		let meta = gen_meta e.e_meta in
@@ -492,14 +488,6 @@ let generate_type com t =
 		| Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))]
 		) in
 		let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in
-		let ext = (match c.cl_dynamic with
-			| None -> ext
-			| Some t ->
-				(match c.cl_path with
-				| ["flash";"errors"], _ -> ext
-				| _ when t == t_dynamic -> " implements Dynamic" :: ext
-				| _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext)
-		) in
 		let ext = (match c.cl_path with
 			| ["flash";"utils"], "ByteArray" -> " implements ArrayAccess<Int>" :: ext
 			| ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess<Dynamic>"]

+ 0 - 1
src/core/type.ml

@@ -1433,7 +1433,6 @@ module Printer = struct
 			"cl_interface",string_of_bool c.cl_interface;
 			"cl_super",s_opt (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_super;
 			"cl_implements",s_list ", " (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_implements;
-			"cl_dynamic",s_opt s_type c.cl_dynamic;
 			"cl_array_access",s_opt s_type c.cl_array_access;
 			"cl_overrides",s_list "," (fun cf -> cf.cf_name) c.cl_overrides;
 			"cl_init",s_opt (s_expr_ast true "" s_type) c.cl_init;

+ 1 - 1
src/generators/genas3.ml

@@ -1096,7 +1096,7 @@ let generate_class ctx c =
 	define_getset ctx false c;
 	ctx.local_types <- List.map snd c.cl_params;
 	let pack = open_block ctx in
-	print ctx "\tpublic %s%s%s %s " (if c.cl_final then " final " else "") (match c.cl_dynamic with None -> "" | Some _ -> if c.cl_interface then "" else "dynamic ") (if c.cl_interface then "interface" else "class") (snd c.cl_path);
+	print ctx "\tpublic %s%s%s %s " (if c.cl_final then " final " else "") "" (if c.cl_interface then "interface" else "class") (snd c.cl_path);
 	(match c.cl_super with
 	| None -> ()
 	| Some (csup,_) -> print ctx "extends %s " (s_path ctx true csup.cl_path c.cl_pos));

+ 7 - 41
src/generators/gencpp.ml

@@ -985,18 +985,6 @@ let rec is_dynamic_accessor name acc field class_def =
    && (match class_def.cl_super with None -> true | Some (parent,_) -> is_dynamic_accessor name acc field parent )
 ;;
 
-
-(* Check to see if we are the first object in the parent tree to implement a dynamic interface *)
-let implement_dynamic_here class_def =
-   let implements_dynamic c = match c.cl_dynamic with None -> false | _ -> true  in
-   let rec super_implements_dynamic c = match c.cl_super with
-      | None -> false
-      | Some (csup, _) -> if (implements_dynamic csup) then true else
-            super_implements_dynamic csup;
-   in
-   ( (implements_dynamic class_def) && (not (super_implements_dynamic class_def) ) );;
-
-
 let gen_hash32 seed str =
    let h = ref (Int32.of_int seed) in
    let cycle = Int32.of_int 223 in
@@ -5191,14 +5179,12 @@ let list_iteri func in_list =
 ;;
 
 let has_new_gc_references ctx class_def =
-   match class_def.cl_dynamic with
-   | Some _ -> true
-   | _ -> (
+   (
       let is_gc_reference field =
       (should_implement_field field) && (is_data_member field) && not (ctx_cant_be_null ctx field.cf_type)
       in
       List.exists is_gc_reference class_def.cl_ordered_fields
-      )
+   )
 ;;
 
 
@@ -5254,7 +5240,7 @@ let is_writable class_def field =
 let statics_except_meta class_def = (List.filter (fun static -> static.cf_name <> "__meta__" && static.cf_name <> "__rtti") class_def.cl_ordered_statics);;
 
 let has_set_member_field class_def =
-   implement_dynamic_here class_def || (
+   (
       let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in
       let reflect_writable = List.filter (is_writable class_def) reflect_fields in
       List.exists variable_field reflect_writable
@@ -5270,14 +5256,14 @@ let has_set_static_field class_def =
 
 
 let has_get_fields class_def =
-   implement_dynamic_here class_def || (
+   (
       let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in
       List.exists is_data_field class_def.cl_ordered_fields
    )
 ;;
 
 let has_get_member_field class_def =
-   implement_dynamic_here class_def || (
+   (
       let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in
       List.exists (is_readable class_def) reflect_fields
    )
@@ -5523,7 +5509,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
    let classIdTxt = Printf.sprintf "0x%08lx" classId in
 
    (* Config *)
-   let implement_dynamic = implement_dynamic_here class_def in
    let override_iteration = (not nativeGen) && (has_new_gc_references baseCtx class_def) in
    let dynamic_interface_closures =  (Common.defined baseCtx.ctx_common Define.DynamicInterfaceClosures) in
 
@@ -5892,8 +5877,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
          (* MARK function - explicitly mark all child pointers *)
          output_cpp ("void " ^ class_name ^ "::__Mark(HX_MARK_PARAMS)\n{\n");
          output_cpp ("\tHX_MARK_BEGIN_CLASS(" ^ smart_class_name ^ ");\n");
-         if (implement_dynamic) then
-            output_cpp "\tHX_MARK_DYNAMIC;\n";
          List.iter (dump_field_iterator "HX_MARK_MEMBER_NAME") implemented_instance_fields;
          (match super_needs_iteration with
          | "" -> ()
@@ -5903,8 +5886,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
 
          (* Visit function - explicitly visit all child pointers *)
          output_cpp ("void " ^ class_name ^ "::__Visit(HX_VISIT_PARAMS)\n{\n");
-         if (implement_dynamic) then
-            output_cpp "\tHX_VISIT_DYNAMIC;\n";
          List.iter (dump_field_iterator "HX_VISIT_MEMBER_NAME") implemented_instance_fields;
          (match super_needs_iteration with
          | "" -> ()
@@ -5966,8 +5947,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
             ) ) )
          in
          dump_quick_field_test (get_field_dat reflect_member_readable);
-         if (implement_dynamic) then
-            output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n";
          output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n");
 
       end;
@@ -6022,12 +6001,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
          ) in
 
          dump_quick_field_test (set_field_dat reflect_write_member_variables);
-         if (implement_dynamic) then begin
-            output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n");
-            output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n");
-            output_cpp "\treturn inValue;\n}\n\n";
-         end else
-            output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n");
+         output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n");
       end;
 
       if (has_set_static_field class_def) then begin
@@ -6064,8 +6038,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
 
          output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n");
          List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields);
-         if (implement_dynamic) then
-            output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n";
          output_cpp "\tsuper::__GetFields(outFields);\n";
          output_cpp "};\n\n";
       end;
@@ -6259,8 +6231,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
             output_cpp ("   HX_DEFINE_SCRIPTABLE_INTERFACE\n")
          else begin
             output_cpp ("   HX_DEFINE_SCRIPTABLE(HX_ARR_LIST" ^ (string_of_int (List.length constructor_var_list) ) ^ ")\n");
-            if (not implement_dynamic) then
-               output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n";
+            output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n";
          end;
       end;
 
@@ -6540,8 +6511,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
       if (has_get_fields class_def) then
          output_h ("\t\tvoid __GetFields(Array< ::String> &outFields);\n");
 
-      if (implement_dynamic) then
-         output_h ("\t\tHX_DECLARE_IMPLEMENT_DYNAMIC;\n");
       output_h ("\t\tstatic void __register();\n");
       if (override_iteration) then begin
          output_h ("\t\tvoid __Mark(HX_MARK_PARAMS);\n");
@@ -8047,7 +8016,6 @@ let generate_script_class common_ctx script class_def =
    script#write ((string_of_int ( (List.length ordered_fields) +
                                  (List.length ordered_statics) +
                                  (match class_def.cl_constructor with Some _ -> 1 | _ -> 0 ) +
-                                 (if (implement_dynamic_here class_def) then 1 else 0) +
                                  (match class_def.cl_init with Some _ -> 1 | _ -> 0 ) ) )
                                  ^ "\n");
 
@@ -8088,8 +8056,6 @@ let generate_script_class common_ctx script class_def =
 
    List.iter (generate_field false) ordered_fields;
    List.iter (generate_field true) ordered_statics;
-   if (implement_dynamic_here class_def) then
-      script#implDynamic;
    script#write "\n";
 ;;
 

+ 0 - 1
src/generators/genpy.ml

@@ -2152,7 +2152,6 @@ module Generator = struct
 						) c.cl_ordered_fields
 					in
 					let field_names = List.map (fun f -> handle_keywords f.cf_name) real_fields in
-					let field_names = match c.cl_dynamic with Some _ -> "__dict__" :: field_names | None -> field_names in
 					use_pass := false;
 					print ctx "\n    __slots__ = (";
 					(match field_names with

+ 1 - 1
src/generators/genswf9.ml

@@ -2172,7 +2172,7 @@ let generate_class ctx c =
 		} :: statics
 	in
 	let rec is_dynamic c =
-		if c.cl_dynamic <> None || c.cl_array_access <> None then true
+		if c.cl_array_access <> None then true
 		else match c.cl_super with
 		| None -> false
 		| Some (c,_) -> is_dynamic c

+ 1 - 1
src/typing/generic.ml

@@ -247,7 +247,7 @@ let rec build_generic ctx c p tl =
 			cf_new.cf_type <- TLazy r;
 			cf_new
 		in
-		if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
+		if c.cl_init <> None then error "This class can't be generic" p;
 		List.iter (fun cf -> match cf.cf_kind with
 			| Method MethMacro when not ctx.in_macro -> ()
 			| _ -> error "A generic class can't have static fields" cf.cf_pos

+ 1 - 0
src/typing/typeloadCheck.ml

@@ -448,6 +448,7 @@ module Inheritance = struct
 					)
 				| TDynamic t ->
 					if c.cl_dynamic <> None then error "Cannot have several dynamics" p;
+					if not c.cl_extern then display_error ctx "In haxe 4, implements Dynamic is only supported on externs" p;
 					c.cl_dynamic <- Some t;
 					(fun () -> ())
 				| _ ->

+ 1 - 1
std/flash/Boot.hx

@@ -22,7 +22,7 @@
 package flash;
 
 #if !as3
-@:keep private class RealBoot extends Boot implements Dynamic {
+@:keep private class RealBoot extends Boot {
 	#if swc
 	public function new() {
 		super();

+ 0 - 12
tests/unit/src/unit/MyClass.hx

@@ -37,18 +37,6 @@ class MyParent {
 	function b() return 20;
 }
 
-class MyDynamicChildWithToString extends MyParent implements Dynamic
-{
-	public function toString()
-	{
-		return "Custom toString";
-	}
-}
-
-class MyDynamicChildWithoutToString extends MyParent implements Dynamic
-{
-}
-
 class MyChild1 extends MyParent {
 	public override function a() { return 12; }
 	override function b() return 21;

+ 0 - 2
tests/unit/src/unit/TestSpecification.hx

@@ -48,8 +48,6 @@ typedef T = {
 
 class CChild extends C { }
 
-class CDyn extends C implements Dynamic { }
-
 private class EmptyClass {
 	public function new() { }
 }

+ 1 - 1
tests/unit/src/unit/issues/Issue5608.hx

@@ -1,6 +1,6 @@
 package unit.issues;
 
-class Issue5608 extends unit.Test implements Dynamic<Bool> {
+class Issue5608 extends unit.Test {
 	var fields:Array<String>;
 
 	function test() {

+ 0 - 2
tests/unit/src/unitstd/Reflect.unit.hx

@@ -122,7 +122,6 @@ Reflect.isObject({v:"f"}) == true;
 Reflect.isObject(new C()) == true;
 Reflect.isObject(new C2()) == true;
 Reflect.isObject(new CChild()) == true;
-Reflect.isObject(new CDyn()) == true;
 Reflect.isObject(new EmptyClass()) == true;
 Reflect.isObject(Type.createEmptyInstance(ReallyEmptyClass)) == true;
 Reflect.isObject("foo") == true;
@@ -147,7 +146,6 @@ Reflect.isEnumValue({v:"f"}) == false;
 Reflect.isEnumValue(new C()) == false;
 Reflect.isEnumValue(new C2()) == false;
 Reflect.isEnumValue(new CChild()) == false;
-Reflect.isEnumValue(new CDyn()) == false;
 Reflect.isEnumValue(new EmptyClass()) == false;
 Reflect.isEnumValue(Type.createEmptyInstance(ReallyEmptyClass)) == false;
 Reflect.isEnumValue("foo") == false;

+ 0 - 10
tests/unit/src/unitstd/Type.unit.hx

@@ -107,16 +107,6 @@ var requiredFields = ["func", "v", "prop"];
 for (f in fields)
 	t(requiredFields.remove(f));
 requiredFields == [];
-#if (!cs && !java && !hl && !eval) // no support for implements Dynamic yet
-var cdyn = new CDyn();
-cdyn.foo = "1";
-Reflect.setField(cdyn, "bar", 1);
-var fields = Type.getInstanceFields(Type.getClass(cdyn));
-var requiredFields = ["func", "v", "prop"];
-for (f in fields)
-	t(requiredFields.remove(f));
-#end
-requiredFields == [];
 var fields = Type.getClassFields(C);
 var requiredFields = #if as3 ["staticVar"] #else ["staticFunc", "staticVar", "staticProp"] #end;
 for (f in fields)