Browse Source

[java/cs] Unit tests-related fixes:
- Fixed classes implementing partially-applied interfaces
- Rewritten overload handling, and fixed most issues regarding overloads ambiguity
- Fixed override-related problems, coming from Codegen.fix_overrides

Caue Waneck 12 years ago
parent
commit
db7df60b47
6 changed files with 428 additions and 151 deletions
  1. 2 1
      codegen.ml
  2. 373 138
      gencommon.ml
  3. 29 7
      gencs.ml
  4. 13 4
      genjava.ml
  5. 1 1
      main.ml
  6. 10 0
      tests/unit/unitstd/Map.unit.hx

+ 2 - 1
codegen.ml

@@ -1880,13 +1880,14 @@ let dump_types com =
 		let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 		let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 		(match mt with
 		(match mt with
 		| Type.TClassDecl c ->
 		| Type.TClassDecl c ->
-			let print_field stat f =
+			let rec print_field stat f =
 				print "\t%s%s%s%s" (if stat then "static " else "") (if f.cf_public then "public " else "") f.cf_name (params f.cf_params);
 				print "\t%s%s%s%s" (if stat then "static " else "") (if f.cf_public then "public " else "") f.cf_name (params f.cf_params);
 				print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type);
 				print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type);
 				(match f.cf_expr with
 				(match f.cf_expr with
 				| None -> ()
 				| None -> ()
 				| Some e -> print "\n\n\t = %s" (s_expr s_type e));
 				| Some e -> print "\n\n\t = %s" (s_expr s_type e));
 				print ";\n\n";
 				print ";\n\n";
+				List.iter (fun f -> print_field stat f) f.cf_overloads
 			in
 			in
 			print "%s%s%s %s%s" (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_types);
 			print "%s%s%s %s%s" (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_types);
 			(match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));
 			(match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));

+ 373 - 138
gencommon.ml

@@ -549,6 +549,8 @@ type generator_ctx =
   mutable gon_classfield_start : (unit -> unit) list;
   mutable gon_classfield_start : (unit -> unit) list;
   (* is executed once every new module type *)
   (* is executed once every new module type *)
   mutable gon_new_module_type : (unit -> unit) list;
   mutable gon_new_module_type : (unit -> unit) list;
+  (* after module filters ended *)
+  mutable gafter_mod_filters_ended : (unit -> unit) list;
   (* after expression filters ended *)
   (* after expression filters ended *)
   mutable gafter_expr_filters_ended : (unit -> unit) list;
   mutable gafter_expr_filters_ended : (unit -> unit) list;
   (* after all filters are run *)
   (* after all filters are run *)
@@ -721,6 +723,7 @@ let new_ctx con =
 
 
     gon_classfield_start = [];
     gon_classfield_start = [];
     gon_new_module_type = [];
     gon_new_module_type = [];
+    gafter_mod_filters_ended = [];
     gafter_expr_filters_ended = [];
     gafter_expr_filters_ended = [];
     gafter_filters_ended = [];
     gafter_filters_ended = [];
 
 
@@ -729,7 +732,7 @@ let new_ctx con =
     greal_type = (fun t -> t);
     greal_type = (fun t -> t);
     greal_type_param = (fun _ t -> t);
     greal_type_param = (fun _ t -> t);
 
 
-   gallow_tp_dynamic_conversion = false;
+    gallow_tp_dynamic_conversion = false;
 
 
     guse_tp_constraints = false;
     guse_tp_constraints = false;
 
 
@@ -891,6 +894,7 @@ let run_filters gen =
   in
   in
 
 
   run_mod_filter gen.gmodule_filters;
   run_mod_filter gen.gmodule_filters;
+  List.iter (fun fn -> fn()) gen.gafter_mod_filters_ended;
 
 
   let last_add_to_module = gen.gadd_to_module in
   let last_add_to_module = gen.gadd_to_module in
   gen.gcon.types <- run_filters gen.gexpr_filters;
   gen.gcon.types <- run_filters gen.gexpr_filters;
@@ -1062,6 +1066,11 @@ let mk_paren e =
 (* private *)
 (* private *)
 let tmp_count = ref 0
 let tmp_count = ref 0
 
 
+let get_real_fun gen t =
+  match follow t with
+  | TFun(args,t) -> TFun(List.map (fun (n,o,t) -> n,o,gen.greal_type t) args, gen.greal_type t)
+  | _ -> t
+
 let mk_int gen i pos = { eexpr = TConst(TInt ( Int32.of_int i)); etype = gen.gcon.basic.tint; epos = pos }
 let mk_int gen i pos = { eexpr = TConst(TInt ( Int32.of_int i)); etype = gen.gcon.basic.tint; epos = pos }
 
 
 let mk_return e = { eexpr = TReturn (Some e); etype = e.etype; epos = e.epos }
 let mk_return e = { eexpr = TReturn (Some e); etype = e.etype; epos = e.epos }
@@ -1470,15 +1479,11 @@ struct
     )
     )
 
 
   let configure gen (empty_ctor_type : t) (empty_ctor_expr : texpr) supports_ctor_inheritance =
   let configure gen (empty_ctor_type : t) (empty_ctor_expr : texpr) supports_ctor_inheritance =
-
     set_new_create_empty gen empty_ctor_expr;
     set_new_create_empty gen empty_ctor_expr;
 
 
     let basic = gen.gcon.basic in
     let basic = gen.gcon.basic in
-
     let should_change cl = not cl.cl_interface && is_hxgen (TClassDecl cl) in
     let should_change cl = not cl.cl_interface && is_hxgen (TClassDecl cl) in
-
     let static_ctor_name = gen.gmk_internal_name "hx" "ctor" in
     let static_ctor_name = gen.gmk_internal_name "hx" "ctor" in
-
     let processed = Hashtbl.create (List.length gen.gcon.types) in
     let processed = Hashtbl.create (List.length gen.gcon.types) in
 
 
     let rec change cl =
     let rec change cl =
@@ -3695,25 +3700,33 @@ struct
   (* from this info, it will infer the applied tparams for the function *)
   (* from this info, it will infer the applied tparams for the function *)
   (* this function is used by CastDetection module *)
   (* this function is used by CastDetection module *)
   let infer_params gen pos (original_args:((string * bool * t) list * t)) (applied_args:((string * bool * t) list * t)) (params:(string * t) list) impossible_tparam_is_dynamic : tparams =
   let infer_params gen pos (original_args:((string * bool * t) list * t)) (applied_args:((string * bool * t) list * t)) (params:(string * t) list) impossible_tparam_is_dynamic : tparams =
-    let args_list args = TFun( List.map (fun (n,o,t) -> (n,o,if impossible_tparam_is_dynamic then gen.greal_type t else t)) (fst args), if impossible_tparam_is_dynamic then t_dynamic else snd args ) in
-
-    let monos = List.map (fun _ -> mk_mono()) params in
-    let original = args_list original_args in
+    match params with
+    | [] -> []
+    | _ ->
+      let args_list args = (if impossible_tparam_is_dynamic then t_dynamic else snd args) :: (List.map (fun (n,o,t) -> t) (fst args)) in
 
 
-    let original = apply_params params monos original in
-    let applied = args_list applied_args in
+      let monos = List.map (fun _ -> mk_mono()) params in
+      let original = args_list (get_fun (apply_params params monos (TFun(fst original_args,snd original_args)))) in
+      let applied = args_list applied_args in
 
 
-    (try
-      unify applied original
-    with | Unify_error el ->
-        gen.gcon.warning ("This expression may be invalid") pos
-    );
+      (try
+        List.iter2 (fun a o ->
+          (* unify a o *)
+          type_eq EqStrict a o
+        ) applied original
+        (* unify applied original *)
+      with | Unify_error el ->
+          (* List.iter (fun el -> gen.gcon.warning (Typecore.unify_error_msg (print_context()) el) pos) el; *)
+          gen.gcon.warning ("This expression may be invalid") pos
+     | Invalid_argument("List.map2") ->
+          gen.gcon.warning ("This expression may be invalid") pos
+      );
 
 
-    List.map (fun t ->
-      match follow t with
-        | TMono _ -> t_empty
-        | t -> t
-    ) monos
+      List.map (fun t ->
+        match follow t with
+          | TMono _ ->  t_empty
+          | t -> t
+      ) monos
 
 
   (* ******************************************* *)
   (* ******************************************* *)
   (* Real Type Parameters Module *)
   (* Real Type Parameters Module *)
@@ -4751,6 +4764,58 @@ struct
   (* end of cast handler *)
   (* end of cast handler *)
   (* ******************* *)
   (* ******************* *)
 
 
+  let is_static_overload c name =
+    match c.cl_super with
+    | None -> false
+    | Some (sup,_) ->
+      let rec loop c =
+        (PMap.mem name c.cl_statics) || (match c.cl_super with
+          | None -> false
+          | Some (sup,_) -> loop sup)
+      in
+      loop sup
+
+  let does_unify a b =
+    try
+      unify a b;
+      true
+    with | Unify_error _ -> false
+
+  (* this is a workaround for issue #1743, as FInstance() is returning the incorrect classfield *)
+  let select_overload gen applied_f overloads types params =
+    let rec check_arg arglist elist =
+      match arglist, elist with
+        | [], [] -> true (* it is valid *)
+        | (_,_,t) :: arglist, (_,_,et) :: elist when Type.type_iseq et t ->
+          check_arg arglist elist
+        | _ -> false
+    in
+    match follow applied_f with
+    | TFun _ ->
+      replace_mono applied_f;
+      let args, _ = get_fun applied_f in
+      let elist = List.rev args in
+      let rec check_overload overloads =
+        match overloads with
+        | (t, cf) :: overloads ->
+            let cft = apply_params types params t in
+            let cft = monomorphs cf.cf_params cft in
+            let args, _ = get_fun cft in
+            if check_arg (List.rev args) elist then
+              cf,t,false
+            else if overloads = [] then
+              cf,t,true (* no compatible overload was found *)
+            else
+              check_overload overloads
+        | [] -> assert false
+      in
+      check_overload overloads
+    | _ -> match overloads with  (* issue #1742 *)
+    | (t,cf) :: [] -> cf,t,true
+    | (t,cf) :: _ -> cf,t,false
+    | _ -> assert false
+
+
   (*
   (*
 
 
     Type parameter handling
     Type parameter handling
@@ -4784,119 +4849,131 @@ struct
     in
     in
 
 
     let real_type = gen.greal_type ef.etype in
     let real_type = gen.greal_type ef.etype in
+    (* this part was rewritten at roughly r6477 in order to correctly support overloads *)
     (match field_access gen real_type (field_name f) with
     (match field_access gen real_type (field_name f) with
-      | FClassField (cl, params, _, cf, is_static, actual_t) ->
-        (match cf.cf_kind with
-          | Method MethDynamic | Var _ ->
-            (* if it's a var, we will just try to apply the class parameters that have been changed with greal_type_param *)
-            let t = apply_params cl.cl_types (gen.greal_type_param (TClassDecl cl) params) (gen.greal_type actual_t) in
-            return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) (gen.greal_type t))
-          | _ when e = None && (try PMap.find cf.cf_name gen.gbase_class_fields == cf with Not_found -> false) ->
-            return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
+    | FClassField (cl, params, _, cf, is_static, actual_t) when e <> None && (cf.cf_kind = Method MethNormal || cf.cf_kind = Method MethInline) ->
+        let ecall = get e in
+        let is_overload = cf.cf_overloads <> [] || Meta.has Meta.Overload cf.cf_meta || (is_static && is_static_overload cl (field_name f)) in
+        let cf, actual_t, error = match is_overload with
+          | false ->
+              (* since actual_t from FClassField already applies greal_type, we're using the get_overloads helper to get this info *)
+              let overloads = Typeload.get_overloads cl (field_name f) in
+              (match overloads with
+              | [] -> cf, cf.cf_type, false
+              | _ -> try
+                  let t, cf = List.find (fun (t,f) -> f == cf) overloads in
+                  cf,t,false
+                  with | Not_found -> cf,actual_t,true)
+          | true -> match f with
+          | FInstance(c,cf) | FClosure(Some c,cf) ->
+            (* get from overloads *)
+            (* FIXME: this is a workaround for issue #1743 . Uncomment this code after it was solved *)
+            (* let t, cf = List.find (fun (t,cf2) -> cf == cf2) (Typeload.get_overloads cl (field_name f)) in *)
+            (* cf, t, false *)
+            select_overload gen e1.etype (Typeload.get_overloads cl (field_name f)) cl.cl_types params
+          | FStatic(c,f) ->
+            (* workaround for issue #1743 *)
+            (* f,f.cf_type, false *)
+            select_overload gen e1.etype ((f.cf_type,f) :: List.map (fun f -> f.cf_type,f) f.cf_overloads) [] []
           | _ ->
           | _ ->
-            let ecall = match e with | None -> trace (field_name f); trace cf.cf_name; gen.gcon.error "This field should be called immediately" ef.epos; assert false | Some ecall -> ecall in
-            match cf.cf_params with
-              | [] when cf.cf_overloads <> [] ->
-                let args, ret = get_args e1.etype in
-                let args, ret = List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret in
-                (try
-                  handle_cast gen
-                  { ecall with
-                    eexpr = TCall(
-                      { e1 with eexpr = TField(ef, f) },
-                      List.map2 (fun param (_,_,t) ->
-                        match param.eexpr with
-                          | TConst TNull -> (* when we have overloads and null const, we must force a cast otherwise we may get ambiguous call errors *)
-                            mk_cast (gen.greal_type t) param
-                          | _ ->
-                            handle_cast gen param (gen.greal_type t) (gen.greal_type param.etype)) elist args
-                    )
-                  } (gen.greal_type ecall.etype) (gen.greal_type ret)
-                with | Invalid_argument("List.map2") ->
-                  gen.gcon.warning "This expression may be invalid" ecall.epos;
-                  handle_cast gen ({ ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, elist )  }) (gen.greal_type ecall.etype) (gen.greal_type ret)
-                )
-              | _ when cf.cf_overloads <> [] ->
-                (* this case still needs Issue #915 to be solved, so we will just ignore the need to cast any parameter by now *)
-                (* TODO issue was solved, solve this issue ASAP *)
-                mk_cast ecall.etype { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, elist ) }
-              | [] ->
-                let args, ret = get_args actual_t in
-                let actual_t = TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret) in
-                let t = apply_params cl.cl_types (gen.greal_type_param (TClassDecl cl) params) actual_t in
-                let args, ret = get_args t in
-                (try
-                  handle_cast gen { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, List.map2 (fun param (_,_,t) -> handle_cast gen param (gen.greal_type t) (gen.greal_type param.etype)) elist args) } (gen.greal_type ecall.etype) (gen.greal_type ret)
-                with | Invalid_argument("List.map2") ->
-                  gen.gcon.warning "This expression may be invalid" ecall.epos;
-                  handle_cast gen ({ ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, elist )  }) (gen.greal_type ecall.etype) (gen.greal_type ret)
-                )
+            gen.gcon.warning "Overloaded classfield typed as anonymous" ecall.epos;
+            cf, actual_t, true
+        in
+        let error = error || (match follow actual_t with | TFun _ -> false | _ -> true) in
+        if error then (* if error, ignore arguments *)
+          mk_cast ecall.etype { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, elist ) }
+        else begin
+          (* infer arguments *)
+          (* let called_t = TFun(List.map (fun e -> "arg",false,e.etype) elist, ecall.etype) in *)
+          let called_t = match follow e1.etype with | TFun _ -> e1.etype | _ -> TFun(List.map (fun e -> "arg",false,e.etype) elist, ecall.etype)  in (* workaround for issue #1742 *)
+          let fparams = TypeParams.infer_params gen ecall.epos (get_fun (apply_params cl.cl_types params actual_t)) (get_fun called_t) cf.cf_params impossible_tparam_is_dynamic in
+          let real_params = gen.greal_type_param (TClassDecl cl) params in
+          let real_fparams = gen.greal_type_param (TClassDecl cl) fparams in
+          (* get what the backend actually sees *)
+          (* actual field's function *)
+          let actual_t = get_real_fun gen actual_t in
+          let function_t = apply_params cl.cl_types real_params actual_t in
+          let function_t = get_real_fun gen (apply_params cf.cf_params real_fparams function_t) in
+          let args_ft, ret_ft = get_fun function_t in
+          (* applied function *)
+          let applied = elist in
+          (* check types list *)
+          let new_ecall, elist = try
+            let elist = List.map2 (fun applied (_,_,funct) ->
+              match is_overload, applied.eexpr with
+              | true, TConst TNull ->
+                mk_cast (gen.greal_type funct) applied
+              | true, _ -> (* when not (type_iseq gen (gen.greal_type applied.etype) funct) -> *)
+                let ret = handle_cast gen applied (funct) (gen.greal_type applied.etype) in
+                (match ret.eexpr with
+                | TCast _ -> ret
+                | _ -> mk_cast (funct) ret)
               | _ ->
               | _ ->
-                let _params = TypeParams.infer_params gen ecall.epos (get_fun (apply_params cl.cl_types params cf.cf_type)) (get_fun e1.etype) cf.cf_params impossible_tparam_is_dynamic in
-                let args, ret = get_args actual_t in
-                let actual_t = TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret) in
-
-                (*
-                  because of differences on how <Dynamic> is handled on the platforms, this is a hack to be able to
-                  correctly use class field type parameters with RealTypeParams
-                *)
-                let cf_params = List.map (fun t -> match follow t with | TDynamic _ -> t_empty | _ -> t) _params in
-                let t = apply_params cl.cl_types (gen.greal_type_param (TClassDecl cl) params) actual_t in
-                let t = apply_params cf.cf_params (gen.greal_type_param (TClassDecl cl) cf_params) t in
-
-                let args, ret = get_args t in
-
-                let elist = List.map2 (fun param (_,_,t) -> handle_cast gen (param) (gen.greal_type t) (gen.greal_type param.etype)) elist args in
-                let e1 = { e1 with eexpr = TField(ef, f) } in
-                let new_ecall = gen.gparam_func_call ecall e1 _params elist in
-
-                handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret)
-        )
-      | FEnumField (en, efield, true) ->
-        let ecall = match e with | None -> trace (field_name f); trace efield.ef_name; gen.gcon.error "This field should be called immediately" ef.epos; assert false | Some ecall -> ecall in
-        (match en.e_types with
+                handle_cast gen applied (funct) (gen.greal_type applied.etype)
+            ) applied args_ft in
+            { ecall with
+              eexpr = TCall(
+                { e1 with eexpr = TField(ef, f) },
+                elist);
+            }, elist
+          with | Invalid_argument("List.map2") ->
+            gen.gcon.warning ("This expression may be invalid" ) ecall.epos;
+            { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, f) }, elist) }, elist
+          in
+          let new_ecall = if fparams <> [] then gen.gparam_func_call new_ecall { e1 with eexpr = TField(ef, f) } fparams elist else new_ecall in
+          handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret_ft)
+        end
+    | FClassField (cl,params,_,{ cf_kind = (Method MethDynamic | Var _) },_,actual_t) ->
+      (* if it's a var, we will just try to apply the class parameters that have been changed with greal_type_param *)
+      let t = apply_params cl.cl_types (gen.greal_type_param (TClassDecl cl) params) (gen.greal_type actual_t) in
+      return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) (gen.greal_type t))
+    | FClassField (cl,params,_,cf,_,actual_t) ->
+      return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
+    | FEnumField (en, efield, true) ->
+      let ecall = match e with | None -> trace (field_name f); trace efield.ef_name; gen.gcon.error "This field should be called immediately" ef.epos; assert false | Some ecall -> ecall in
+      (match en.e_types with
+        (*
+        | [] ->
+          let args, ret = get_args (efield.ef_type) in
+          let ef = { ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, []) } in
+          handle_cast gen { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, FEnum(en, efield)) }, List.map2 (fun param (_,_,t) -> handle_cast gen param (gen.greal_type t) (gen.greal_type param.etype)) elist args) } (gen.greal_type ecall.etype) (gen.greal_type ret)
+      *)
+        | _ ->
+          let pt = match e with | None -> real_type | Some _ -> snd (get_fun e1.etype) in
+          let _params = match follow pt with | TEnum(_, p) -> p | _ -> gen.gcon.warning (debug_expr e1) e1.epos; assert false in
+          let args, ret = get_args efield.ef_type in
+          let actual_t = TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret) in
           (*
           (*
-          | [] ->
-            let args, ret = get_args (efield.ef_type) in
-            let ef = { ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, []) } in
-            handle_cast gen { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, FEnum(en, efield)) }, List.map2 (fun param (_,_,t) -> handle_cast gen param (gen.greal_type t) (gen.greal_type param.etype)) elist args) } (gen.greal_type ecall.etype) (gen.greal_type ret)
-        *)
-          | _ ->
-            let pt = match e with | None -> real_type | Some _ -> snd (get_fun e1.etype) in
-            let _params = match follow pt with | TEnum(_, p) -> p | _ -> gen.gcon.warning (debug_expr e1) e1.epos; assert false in
-            let args, ret = get_args efield.ef_type in
-            let actual_t = TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret) in
-            (*
-              because of differences on how <Dynamic> is handled on the platforms, this is a hack to be able to
-              correctly use class field type parameters with RealTypeParams
-            *)
-            let cf_params = List.map (fun t -> match follow t with | TDynamic _ -> t_empty | _ -> t) _params in
-            (* params are inverted *)
-            let cf_params = List.rev cf_params in
-            let t = apply_params en.e_types (gen.greal_type_param (TEnumDecl en) cf_params) actual_t in
-            let t = apply_params efield.ef_params (List.map (fun _ -> t_dynamic) efield.ef_params) t in
+            because of differences on how <Dynamic> is handled on the platforms, this is a hack to be able to
+            correctly use class field type parameters with RealTypeParams
+          *)
+          let cf_params = List.map (fun t -> match follow t with | TDynamic _ -> t_empty | _ -> t) _params in
+          (* params are inverted *)
+          let cf_params = List.rev cf_params in
+          let t = apply_params en.e_types (gen.greal_type_param (TEnumDecl en) cf_params) actual_t in
+          let t = apply_params efield.ef_params (List.map (fun _ -> t_dynamic) efield.ef_params) t in
 
 
-            let args, ret = get_args t in
+          let args, ret = get_args t in
 
 
-            let elist = List.map2 (fun param (_,_,t) -> handle_cast gen (param) (gen.greal_type t) (gen.greal_type param.etype)) elist args in
-            let e1 = { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, _params) }, FEnum(en, efield) ) } in
-            let new_ecall = gen.gparam_func_call ecall e1 _params elist in
+          let elist = List.map2 (fun param (_,_,t) -> handle_cast gen (param) (gen.greal_type t) (gen.greal_type param.etype)) elist args in
+          let e1 = { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, _params) }, FEnum(en, efield) ) } in
+          let new_ecall = gen.gparam_func_call ecall e1 _params elist in
 
 
-            handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret)
-        )
-      | FEnumField _ when is_some e -> assert false
-      | FEnumField (en,efield,_) ->
-          return_var { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); },FEnum(en,efield)) }
-      (* no target by date will uses this.so this code may not be correct at all *)
-      | FAnonField cf ->
-        let t = gen.greal_type cf.cf_type in
-        return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) t)
-      | FNotFound
-      | FDynamicField _ ->
-        if is_some e then
-          return_var { e1 with eexpr = TField(ef, f) }
-        else
-          return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
+          handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret)
+      )
+    | FEnumField _ when is_some e -> assert false
+    | FEnumField (en,efield,_) ->
+        return_var { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); },FEnum(en,efield)) }
+    (* no target by date will uses this.so this code may not be correct at all *)
+    | FAnonField cf ->
+      let t = gen.greal_type cf.cf_type in
+      return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) t)
+    | FNotFound
+    | FDynamicField _ ->
+      if is_some e then
+        return_var { e1 with eexpr = TField(ef, f) }
+      else
+        return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
     )
     )
 
 
   (* end of type parameter handling *)
   (* end of type parameter handling *)
@@ -5082,15 +5159,11 @@ struct
         | TBlock el ->
         | TBlock el ->
           { e with eexpr = TBlock ( List.map (fun e -> in_value := false; run e) el ) }
           { e with eexpr = TBlock ( List.map (fun e -> in_value := false; run e) el ) }
         | TFunction(tfunc) ->
         | TFunction(tfunc) ->
-          (match follow e.etype with
-            | TFun(_,ret) ->
-              let last_ret = !current_ret_type in
-              current_ret_type := Some(ret);
-              let ret = Type.map_expr run e in
-              current_ret_type := last_ret;
-              ret
-            | _ -> trace (debug_type (follow e.etype)); trace (debug_expr e); gen.gcon.error "assert false" e.epos; assert false
-          )
+          let last_ret = !current_ret_type in
+          current_ret_type := Some(tfunc.tf_type);
+          let ret = Type.map_expr run e in
+          current_ret_type := last_ret;
+          ret
         | TCast (expr, md) when is_void (follow e.etype) ->
         | TCast (expr, md) when is_void (follow e.etype) ->
           run expr
           run expr
         | TCast (expr, md) ->
         | TCast (expr, md) ->
@@ -7976,7 +8049,7 @@ struct
         (if not (PMap.mem (gen.gmk_internal_name "hx" "invokeField") cl.cl_fields) then implement_invokeField ctx ~slow_invoke:slow_invoke cl);
         (if not (PMap.mem (gen.gmk_internal_name "hx" "invokeField") cl.cl_fields) then implement_invokeField ctx ~slow_invoke:slow_invoke cl);
         (if not (PMap.mem (gen.gmk_internal_name "hx" "classFields") cl.cl_fields) then implement_fields ctx cl);
         (if not (PMap.mem (gen.gmk_internal_name "hx" "classFields") cl.cl_fields) then implement_fields ctx cl);
         (if ctx.rcf_handle_statics && not (PMap.mem (gen.gmk_internal_name "hx" "getClassStatic") cl.cl_statics) then implement_get_class ctx cl);
         (if ctx.rcf_handle_statics && not (PMap.mem (gen.gmk_internal_name "hx" "getClassStatic") cl.cl_statics) then implement_get_class ctx cl);
-        (if not (PMap.mem (gen.gmk_internal_name "hx" "create") cl.cl_fields) then implement_create_empty ctx cl);
+        (if not cl.cl_interface && not (PMap.mem (gen.gmk_internal_name "hx" "create") cl.cl_fields) then implement_create_empty ctx cl);
         None
         None
       | _ -> None)
       | _ -> None)
     in
     in
@@ -8770,7 +8843,8 @@ struct
 
 
   let name = "hard_nullable"
   let name = "hard_nullable"
 
 
-  let priority = solve_deps name []
+  (* let priority = solve_deps name [] *)
+  let priority = -200.0
 
 
   let rec is_null_t gen t = match gen.greal_type t with
   let rec is_null_t gen t = match gen.greal_type t with
     | TType( { t_path = ([], "Null") }, [of_t])
     | TType( { t_path = ([], "Null") }, [of_t])
@@ -9688,6 +9762,167 @@ struct
 
 
 end;;
 end;;
 
 
+(* ******************************************* *)
+(* FixOverrides *)
+(* ******************************************* *)
+
+(*
+
+  Covariant return types, contravariant function arguments and applied type parameters may change
+  in a way that expected implementations / overrides aren't recognized as such.
+  This filter will fix that.
+
+  dependencies:
+    FixOverrides expects that the target platform is able to deal with overloaded functions
+
+*)
+
+module FixOverrides =
+struct
+
+  let name = "fix_overrides"
+
+  let priority = solve_deps name []
+
+  (*
+    if the platform allows explicit interface implementation (C#),
+    specify a explicit_fn_name function (tclass->string->string)
+    Otherwise, it expects the platform to be able to handle covariant return types
+  *)
+  let run ~explicit_fn_name gen =
+    let implement_explicitly = is_some explicit_fn_name in
+    let run md = match md with
+      | TClassDecl ( { cl_interface = true } as c ) ->
+        (* overrides can be removed from interfaces *)
+        c.cl_ordered_fields <- List.filter (fun f ->
+          try
+            if Meta.has Meta.Overload f.cf_meta then raise Not_found;
+            let f2 = Codegen.find_field c f in
+            if f2 == f then raise Not_found;
+            c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
+            false;
+          with Not_found ->
+            true
+        ) c.cl_ordered_fields;
+        md
+      | TClassDecl c ->
+        let this = { eexpr = TConst TThis; etype = TInst(c,List.map snd c.cl_types); epos = c.cl_pos } in
+        (* look through all interfaces, and try to find a type that applies exactly *)
+        let rec loop_iface (iface:tclass) itl =
+          List.iter (fun (s,stl) -> loop_iface s (List.map (apply_params iface.cl_types itl) stl)) iface.cl_implements;
+          let real_itl = gen.greal_type_param (TClassDecl iface) itl in
+          let rec loop_f f =
+            List.iter loop_f f.cf_overloads;
+            let ftype = apply_params iface.cl_types itl f.cf_type in
+            let real_ftype = get_real_fun gen (apply_params iface.cl_types real_itl f.cf_type) in
+            replace_mono real_ftype;
+            let overloads = Typeload.get_overloads c f.cf_name in
+            (* if we find a function with the exact type of real_ftype, it means this interface has already been taken care of *)
+            if not (List.exists (fun (t,_) -> replace_mono t; type_iseq (get_real_fun gen t) real_ftype) overloads) then
+              try
+                (match f.cf_kind with | Method (MethNormal | MethInline) -> () | _ -> raise Not_found);
+                let t2, f2 =
+                  match overloads with
+                  | (_, cf) :: _ when Meta.has Meta.Overload cf.cf_meta -> (* overloaded function *)
+                    (* try to find exact function *)
+                    List.find (fun (t,f2) ->
+                      Typeload.same_overload_args ftype t f f2
+                    ) overloads
+                  | _ :: _ ->
+                    (match field_access gen (TInst(c, List.map snd c.cl_types)) f.cf_name with
+                    | FClassField(_,_,_,f2,false,t) -> t,f2 (* if it's not an overload, all functions should have the same signature *)
+                    | _ -> raise Not_found)
+                  | [] -> raise Not_found
+                in
+                let t2 = get_real_fun gen t2 in
+                if List.length f.cf_params <> List.length f2.cf_params then raise Not_found;
+                replace_mono t2;
+                match follow (apply_params f2.cf_params (List.map snd f.cf_params) t2), follow real_ftype with
+                | TFun(a1,r1), TFun(a2,r2) when not implement_explicitly && not (type_iseq r1 r2) && Typeload.same_overload_args real_ftype t2 f f2 ->
+                  (* different return types are the trickiest cases to deal with *)
+                  (* check for covariant return type *)
+                  let is_covariant = match follow r1, follow r2 with
+                    | _, TDynamic _ -> true
+                    | r1, r2 -> try
+                      unify r1 r2;
+                      true
+                    with | Unify_error _ -> false
+                  in
+                  (* we only have to worry about non-covariant issues *)
+                  if not is_covariant then begin
+                    (* override return type and cast implemented function *)
+                    let args, newr = match follow t2, follow (apply_params f.cf_params (List.map snd f2.cf_params) real_ftype) with
+                      | TFun(a,_), TFun(_,r) -> a,r
+                      | _ -> assert false
+                    in
+                    f2.cf_type <- TFun(args,newr);
+                    (match f2.cf_expr with
+                    | Some ({ eexpr = TFunction tf } as e) ->
+                        f2.cf_expr <- Some { e with eexpr = TFunction { tf with tf_type = newr } }
+                    | _ -> ())
+                  end
+               | TFun(a1,r1), TFun(a2,r2) ->
+                  (* just implement a function that will call the main one *)
+                  let name, is_explicit = match explicit_fn_name with
+                    | Some fn when not (type_iseq r1 r2) && Typeload.same_overload_args real_ftype t2 f f2 ->
+                        fn iface itl f.cf_name, true
+                    | _ -> f.cf_name, false
+                  in
+                  let p = f2.cf_pos in
+                  let newf = mk_class_field name real_ftype true f.cf_pos (Method MethNormal) f.cf_params in
+                  let vars = List.map (fun (n,_,t) -> alloc_var n t) a2 in
+
+                  let args = List.map2 (fun v (_,_,t) -> mk_cast t (mk_local v f2.cf_pos)) vars a1 in
+                  let field = { eexpr = TField(this, FInstance(c,f2)); etype = TFun(a1,r1); epos = p } in
+                  let call = { eexpr = TCall(field, args); etype = r1; epos = p } in
+                  (* let call = gen.gparam_func_call call field (List.map snd f.cf_params) args in *)
+                  let is_void = is_void r2 in
+
+                  newf.cf_expr <- Some {
+                    eexpr = TFunction({
+                      tf_args = List.map (fun v -> v,None) vars;
+                      tf_type = r2;
+                      tf_expr = (if is_void then call else {
+                        eexpr = TReturn (Some (mk_cast r2 call));
+                        etype = r2;
+                        epos = p
+                      })
+                    });
+                    etype = real_ftype;
+                    epos = p;
+                  };
+                  (* delayed: add to class *)
+                  let delay () =
+                    try
+                      let fm = PMap.find f.cf_name c.cl_fields in
+                      fm.cf_overloads <- newf :: fm.cf_overloads
+                    with | Not_found ->
+                      c.cl_fields <- PMap.add f.cf_name newf c.cl_fields;
+                      c.cl_ordered_fields <- newf :: c.cl_ordered_fields
+                  in
+                  (* gen.gafter_filters_ended <- delay :: gen.gafter_filters_ended *)
+                  delay();
+                | _ -> assert false
+              with | Not_found -> ()
+          in
+          List.iter loop_f iface.cl_ordered_fields
+        in
+        List.iter (fun (iface,itl) -> loop_iface iface itl) c.cl_implements;
+        md
+      | _ -> md
+    in
+    run
+
+  let configure ?explicit_fn_name gen =
+    let delay () =
+      Hashtbl.clear gen.greal_field_types
+    in
+    gen.gafter_mod_filters_ended <- delay :: gen.gafter_mod_filters_ended;
+    let run = run ~explicit_fn_name:explicit_fn_name gen in
+    let map md = Some(run md) in
+    gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map
+end;;
+
 (*
 (*
 (* ******************************************* *)
 (* ******************************************* *)
 (* Example *)
 (* Example *)

+ 29 - 7
gencs.ml

@@ -595,6 +595,13 @@ let configure gen =
 
 
   let ttype = get_cl ( get_type gen (["System"], "Type") ) in
   let ttype = get_cl ( get_type gen (["System"], "Type") ) in
 
 
+  let has_tdyn tl =
+    List.exists (fun t -> match follow t with
+    | TDynamic _ | TMono _ -> true
+    | _ -> false
+  ) tl
+  in
+
   let rec real_type t =
   let rec real_type t =
     let t = gen.gfollow#run_f t in
     let t = gen.gfollow#run_f t in
     let ret = match t with
     let ret = match t with
@@ -609,11 +616,11 @@ let configure gen =
       | TEnum(_, [])
       | TEnum(_, [])
       | TInst(_, []) -> t
       | TInst(_, []) -> t
       | TInst(cl, params) when
       | TInst(cl, params) when
-        List.exists (fun t -> match follow t with | TDynamic _ -> true | _ -> false) params &&
+        has_tdyn params &&
         Hashtbl.mem ifaces cl.cl_path ->
         Hashtbl.mem ifaces cl.cl_path ->
           TInst(Hashtbl.find ifaces cl.cl_path, [])
           TInst(Hashtbl.find ifaces cl.cl_path, [])
       | TEnum(e, params) when
       | TEnum(e, params) when
-        List.exists (fun t -> match follow t with | TDynamic _ -> true | _ -> false) params &&
+        has_tdyn params &&
         Hashtbl.mem ifaces e.e_path ->
         Hashtbl.mem ifaces e.e_path ->
           TInst(Hashtbl.find ifaces e.e_path, [])
           TInst(Hashtbl.find ifaces e.e_path, [])
       | TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params)
       | TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params)
@@ -896,6 +903,9 @@ let configure gen =
           (match mt with
           (match mt with
             | TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
             | TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
             | TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
             | TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
+            | TClassDecl { cl_interface = true } ->
+                write w ("global::" ^ module_s mt);
+                write w "__Statics_";
             | TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_types)))
             | TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_types)))
             | TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_types)))
             | TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_types)))
             | TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_types))))
             | TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_types))))
@@ -1328,7 +1338,8 @@ let configure gen =
         let modifiers = modifiers @ modf in
         let modifiers = modifiers @ modf in
         let visibility, is_virtual = if is_explicit_iface then "",false else visibility, is_virtual in
         let visibility, is_virtual = if is_explicit_iface then "",false else visibility, is_virtual in
         let v_n = if is_static then "static " else if is_override && not is_interface then "override " else if is_virtual then "virtual " else "" in
         let v_n = if is_static then "static " else if is_override && not is_interface then "override " else if is_virtual then "virtual " else "" in
-        let ret_type, args = match follow cf.cf_type with | TFun (strbtl, t) -> (t, strbtl) | _ -> assert false in
+        let cf_type = if is_override && not is_overload && not (Meta.has Meta.Overload cf.cf_meta) then match field_access gen (TInst(cl, List.map snd cl.cl_types)) cf.cf_name with | FClassField(_,_,_,_,_,actual_t) -> actual_t | _ -> assert false else cf.cf_type in
+        let ret_type, args = match follow cf_type with | TFun (strbtl, t) -> (t, strbtl) | _ -> assert false in
 
 
         (* public static void funcName *)
         (* public static void funcName *)
         print w "%s %s %s %s %s" (visibility) v_n (String.concat " " modifiers) (if is_new then "" else rett_s (run_follow gen ret_type)) (change_field name);
         print w "%s %s %s %s %s" (visibility) v_n (String.concat " " modifiers) (if is_new then "" else rett_s (run_follow gen ret_type)) (change_field name);
@@ -1468,6 +1479,7 @@ let configure gen =
       end
       end
     end;
     end;
     (try
     (try
+      if cl.cl_interface then raise Not_found;
       let cf = PMap.find "toString" cl.cl_fields in
       let cf = PMap.find "toString" cl.cl_fields in
       (if List.exists (fun c -> c.cf_name = "toString") cl.cl_overrides then raise Not_found);
       (if List.exists (fun c -> c.cf_name = "toString") cl.cl_overrides then raise Not_found);
       (match cf.cf_type with
       (match cf.cf_type with
@@ -1559,12 +1571,16 @@ let configure gen =
         print w "static %s() " (snd cl.cl_path);
         print w "static %s() " (snd cl.cl_path);
         expr_s w (mk_block init));
         expr_s w (mk_block init));
     (if is_some cl.cl_constructor then gen_class_field w false cl is_final (get cl.cl_constructor));
     (if is_some cl.cl_constructor then gen_class_field w false cl is_final (get cl.cl_constructor));
-    (if not cl.cl_interface then
-      List.iter (gen_class_field w true cl is_final) cl.cl_ordered_statics);
+    if not cl.cl_interface then List.iter (gen_class_field w true cl is_final) cl.cl_ordered_statics;
     List.iter (gen_class_field w false cl is_final) cl.cl_ordered_fields;
     List.iter (gen_class_field w false cl is_final) cl.cl_ordered_fields;
     check_special_behaviors w cl;
     check_special_behaviors w cl;
     end_block w;
     end_block w;
-
+    if cl.cl_interface && cl.cl_ordered_statics <> [] then begin
+      print w "public class %s__Statics_" (snd cl.cl_path);
+      begin_block w;
+      List.iter (gen_class_field w true { cl with cl_interface = false } is_final) cl.cl_ordered_statics;
+      end_block w
+    end;
     if should_close then end_block w
     if should_close then end_block w
   in
   in
 
 
@@ -1725,9 +1741,15 @@ let configure gen =
       }
       }
     )
     )
     true
     true
-    true
+    false
   );
   );
 
 
+
+  let explicit_fn_name c tl fname =
+    path_param_s (TClassDecl c) c.cl_path tl ^ "." ^ fname
+  in
+  FixOverrides.configure ~explicit_fn_name:explicit_fn_name gen;
+
   AbstractImplementationFix.configure gen;
   AbstractImplementationFix.configure gen;
 
 
   IteratorsInterface.configure gen (fun e -> e);
   IteratorsInterface.configure gen (fun e -> e);

+ 13 - 4
genjava.ml

@@ -664,7 +664,7 @@ let configure gen =
   let ti64 = match ( get_type gen (["haxe";"_Int64"], "NativeInt64") ) with | TTypeDecl t -> TType(t,[]) | _ -> assert false in
   let ti64 = match ( get_type gen (["haxe";"_Int64"], "NativeInt64") ) with | TTypeDecl t -> TType(t,[]) | _ -> assert false in
 
 
   let has_tdynamic params =
   let has_tdynamic params =
-    List.exists (fun e -> match e with | TDynamic _ -> true | _ -> false) params
+    List.exists (fun e -> match run_follow gen e with | TDynamic _ -> true | _ -> false) params
   in
   in
 
 
   (*
   (*
@@ -773,13 +773,15 @@ let configure gen =
       | TAbstract( { a_path = ([], "Class") }, p  )
       | TAbstract( { a_path = ([], "Class") }, p  )
       | TAbstract( { a_path = ([], "Enum") }, p  )
       | TAbstract( { a_path = ([], "Enum") }, p  )
       | TInst( { cl_path = ([], "Class") }, p  )
       | TInst( { cl_path = ([], "Class") }, p  )
-      | TInst( { cl_path = ([], "Enum") }, p  ) -> TInst(cl_cl,[t_dynamic])
+      | TInst( { cl_path = ([], "Enum") }, p  ) -> TInst(cl_cl,p)
       | TEnum _
       | TEnum _
       | TInst _ -> t
       | TInst _ -> t
       | TType({ t_path = ([], "Null") }, [t]) when is_java_basic_type t -> t_dynamic
       | TType({ t_path = ([], "Null") }, [t]) when is_java_basic_type t -> t_dynamic
       | TType({ t_path = ([], "Null") }, [t]) ->
       | TType({ t_path = ([], "Null") }, [t]) ->
         (match follow t with
         (match follow t with
-          | TInst( { cl_kind = KTypeParameter _ }, []) -> t_dynamic
+          | TInst( { cl_kind = KTypeParameter _ }, []) ->
+              (* t_dynamic *)
+              real_type t
           | _ -> real_type t
           | _ -> real_type t
         )
         )
       | TType _ | TAbstract _ -> t
       | TType _ | TAbstract _ -> t
@@ -1727,6 +1729,7 @@ let configure gen =
 
 
   StubClosureImpl.configure gen (StubClosureImpl.default_implementation gen float_cl 10 (fun e _ _ -> e));*)
   StubClosureImpl.configure gen (StubClosureImpl.default_implementation gen float_cl 10 (fun e _ _ -> e));*)
 
 
+  FixOverrides.configure gen;
   AbstractImplementationFix.configure gen;
   AbstractImplementationFix.configure gen;
 
 
   IteratorsInterface.configure gen (fun e -> e);
   IteratorsInterface.configure gen (fun e -> e);
@@ -2395,6 +2398,10 @@ let convert_java_field ctx p jc field =
     | JKMethod ->
     | JKMethod ->
       match field.jf_signature with
       match field.jf_signature with
       | TMethod (args, ret) ->
       | TMethod (args, ret) ->
+        let old_types = ctx.jtparams in
+        (match ctx.jtparams with
+        | c :: others -> ctx.jtparams <- (c @ field.jf_types) :: others
+        | [] -> ctx.jtparams <- field.jf_types :: []);
         let i = ref 0 in
         let i = ref 0 in
         let args = List.map (fun s ->
         let args = List.map (fun s ->
           incr i;
           incr i;
@@ -2417,6 +2424,7 @@ let convert_java_field ctx p jc field =
               tp_constraints = List.map (convert_signature ctx p) (impl);
               tp_constraints = List.map (convert_signature ctx p) (impl);
             }
             }
         ) field.jf_types in
         ) field.jf_types in
+        ctx.jtparams <- old_types;
 
 
         FFun ({
         FFun ({
           f_params = types;
           f_params = types;
@@ -2533,7 +2541,8 @@ let normalize_jclass com cls =
   (* we won't be able to deal correctly with field's type parameters *)
   (* we won't be able to deal correctly with field's type parameters *)
   (* since java sometimes overrides / implements crude (ie no type parameters) versions *)
   (* since java sometimes overrides / implements crude (ie no type parameters) versions *)
   (* and interchanges between them *)
   (* and interchanges between them *)
-  let methods = List.map (fun f -> let f = del_override f in  if f.jf_types <> [] then { f with jf_types = []; jf_signature = f.jf_vmsignature } else f ) cls.cmethods in
+  (* let methods = List.map (fun f -> let f = del_override f in  if f.jf_types <> [] then { f with jf_types = []; jf_signature = f.jf_vmsignature } else f ) cls.cmethods in *)
+  let methods = List.map (fun f -> del_override f ) cls.cmethods in
   let cmethods = ref methods in
   let cmethods = ref methods in
   let all_methods = ref methods in
   let all_methods = ref methods in
   let all_fields = ref cls.cfields in
   let all_fields = ref cls.cfields in

+ 1 - 1
main.ml

@@ -1227,7 +1227,7 @@ try
 		| Some file ->
 		| Some file ->
 			Common.log com ("Generating xml : " ^ file);
 			Common.log com ("Generating xml : " ^ file);
 			Genxml.generate com file);
 			Genxml.generate com file);
-		if com.platform = Flash || com.platform = Cpp || com.platform = Cs then List.iter (Codegen.fix_overrides com) com.types;
+		if com.platform = Flash || com.platform = Cpp then List.iter (Codegen.fix_overrides com) com.types;
 		if Common.defined com Define.Dump then Codegen.dump_types com;
 		if Common.defined com Define.Dump then Codegen.dump_types com;
 		if Common.defined com Define.DumpDependencies then Codegen.dump_dependencies com;
 		if Common.defined com Define.DumpDependencies then Codegen.dump_dependencies com;
 		t();
 		t();

+ 10 - 0
tests/unit/unitstd/Map.unit.hx

@@ -5,6 +5,10 @@ map.get("foo") == null;
 map.set("foo", 1);
 map.set("foo", 1);
 map.set("bar", 2);
 map.set("bar", 2);
 map.set("baz", 3);
 map.set("baz", 3);
+var dynmap:Dynamic = map;
+var map2:Map.IMap<Dynamic,Dynamic> = dynmap;
+var map3:Map.IMap<String, Dynamic> = dynmap;
+var map4:Map.IMap<String, Int> = dynmap;
 Std.is(map, haxe.ds.StringMap) == true;
 Std.is(map, haxe.ds.StringMap) == true;
 map.exists("foo") == true;
 map.exists("foo") == true;
 map.exists("bar") == true;
 map.exists("bar") == true;
@@ -12,6 +16,12 @@ map.exists("baz") == true;
 map.get("foo") == 1;
 map.get("foo") == 1;
 map.get("bar") == 2;
 map.get("bar") == 2;
 map.get("baz") == 3;
 map.get("baz") == 3;
+map2.exists("foo") == true;
+map2.get("foo") == 1;
+map3.exists("foo") == true;
+map3.get("foo") == 1;
+map4.exists("foo") == true;
+map4.get("foo") == 1;
 var values = [];
 var values = [];
 for (val in map) {
 for (val in map) {
 	values.push(val);
 	values.push(val);