Explorar o código

Merge pull request #3319 from Simn/refactor_2014

Rewrite `unify_call_args`
Simon Krajewski %!s(int64=11) %!d(string=hai) anos
pai
achega
5796744a86
Modificáronse 16 ficheiros con 306 adicións e 314 borrados
  1. 13 12
      codegen.ml
  2. 1 1
      dce.ml
  3. 1 1
      filters.ml
  4. 2 2
      genas3.ml
  5. 20 20
      gencommon.ml
  6. 10 10
      gencpp.ml
  7. 14 14
      gencs.ml
  8. 3 3
      genjava.ml
  9. 5 5
      genpy.ml
  10. 1 1
      genswf9.ml
  11. 4 2
      interp.ml
  12. 5 5
      optimizer.ml
  13. 18 17
      type.ml
  14. 15 1
      typecore.ml
  15. 5 5
      typeload.ml
  16. 189 215
      typer.ml

+ 13 - 12
codegen.ml

@@ -267,7 +267,7 @@ let generic_substitute_expr gctx e =
 	in
 	let rec build_expr e =
 		match e.eexpr with
-		| TField(e1, FInstance({cl_kind = KGeneric},cf)) ->
+		| TField(e1, FInstance({cl_kind = KGeneric},_,cf)) ->
 			build_expr {e with eexpr = TField(e1,quick_field_dynamic (generic_substitute_type gctx (e1.etype)) cf.cf_name)}
 		| _ -> map_expr_type build_expr (generic_substitute_type gctx) build_var e
 	in
@@ -909,7 +909,7 @@ let detect_usage com =
 					let p = {e.epos with pmin = e.epos.pmax - (String.length ef.ef_name)} in
 					usage := p :: !usage;
 					Type.iter expr e
-				| TField(_,(FAnon cf | FInstance (_,cf) | FStatic (_,cf) | FClosure (_,cf))) when Meta.has Meta.Usage cf.cf_meta ->
+				| TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) when Meta.has Meta.Usage cf.cf_meta ->
 					let p = {e.epos with pmin = e.epos.pmax - (String.length cf.cf_name)} in
 					usage := p :: !usage;
 					Type.iter expr e
@@ -1503,15 +1503,15 @@ struct
 
 	let rec rm_duplicates acc ret = match ret with
 		| [] -> acc
-		| ( el, t ) :: ret when List.exists (fun (_,t2) -> type_iseq t t2) acc ->
+		| ( el, t, _ ) :: ret when List.exists (fun (_,t2,_) -> type_iseq t t2) acc ->
 			rm_duplicates acc ret
 		| r :: ret ->
 			rm_duplicates (r :: acc) ret
 
-	let s_options rated =
+(* 	let s_options rated =
 		String.concat ",\n" (List.map (fun ((_,t),rate) ->
 			"( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
-		) rated)
+		) rated) *)
 
 	let count_optionals elist =
 		List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
@@ -1519,7 +1519,7 @@ struct
 	let rec fewer_optionals acc compatible = match acc, compatible with
 		| _, [] -> acc
 		| [], c :: comp -> fewer_optionals [c] comp
-		| (elist_acc, _) :: _, ((elist, _) as cur) :: comp ->
+		| (elist_acc, _, _) :: _, ((elist, _, _) as cur) :: comp ->
 			let acc_opt = count_optionals elist_acc in
 			let comp_opt = count_optionals elist in
 			if acc_opt = comp_opt then
@@ -1530,7 +1530,8 @@ struct
 				fewer_optionals [cur] comp
 
 	let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with
-		| [] -> [] | [v] -> [v]
+		| [] -> []
+		| [v] -> [v]
 		| compatible ->
 			(* convert compatible into ( rate * compatible_type ) list *)
 			let rec mk_rate acc elist args = match elist, args with
@@ -1543,8 +1544,8 @@ struct
 
 			let rated = ref [] in
 			List.iter (function
-				| (elist,TFun(args,ret)) -> (try
-					rated := ( (elist,TFun(args,ret)), mk_rate [] elist args ) :: !rated
+				| (elist,TFun(args,ret),d) -> (try
+					rated := ( (elist,TFun(args,ret),d), mk_rate [] elist args ) :: !rated
 					with | Not_found -> ())
 				| _ -> assert false
 			) compatible;
@@ -1561,10 +1562,10 @@ struct
 						loop ( (rover,rargs) :: best ) rem
 			in
 
-			List.map fst (loop [] !rated)
+			let r = loop [] !rated in
+			List.map fst r
 end;;
 
-
 module UnificationCallback = struct
 	let tf_stack = ref []
 
@@ -1691,7 +1692,7 @@ module DeprecationCheck = struct
 			| TField(e1,fa) ->
 				expr e1;
 				begin match fa with
-					| FStatic(c,cf) | FInstance(c,cf) ->
+					| FStatic(c,cf) | FInstance(c,_,cf) ->
 						check_class com c e.epos;
 						check_cf com cf e.epos
 					| FAnon cf ->

+ 1 - 1
dce.ml

@@ -352,7 +352,7 @@ and expr dce e =
 			| FStatic(c,cf) ->
 				mark_class dce c;
 				mark_field dce c cf true;
-			| FInstance(c,cf) ->
+			| FInstance(c,_,cf) ->
 				mark_class dce c;
 				mark_field dce c cf false;
 			| _ ->

+ 1 - 1
filters.ml

@@ -1034,7 +1034,7 @@ let add_field_inits ctx t =
 				match cf.cf_expr with
 				| None -> assert false
 				| Some e ->
-					let lhs = mk (TField(ethis,FInstance (c,cf))) cf.cf_type e.epos in
+					let lhs = mk (TField(ethis,FInstance (c,List.map snd c.cl_params,cf))) cf.cf_type e.epos in
 					cf.cf_expr <- None;
 					let eassign = mk (TBinop(OpAssign,lhs,e)) e.etype e.epos in
 					if is_as3 then begin

+ 2 - 2
genas3.ml

@@ -47,7 +47,7 @@ type context = {
 
 let is_var_field f =
 	match f with
-	| FStatic (_,f) | FInstance (_,f) ->
+	| FStatic (_,f) | FInstance (_,_,f) ->
 		(match f.cf_kind with Var _ -> true | _ -> false)
 	| _ ->
 		false
@@ -592,7 +592,7 @@ and gen_expr ctx e =
 		print ctx " %s " (Ast.s_binop op);
 		gen_value_op ctx e2;
 	(* variable fields on interfaces are generated as (class["field"] as class) *)
-	| TField ({etype = TInst({cl_interface = true} as c,_)} as ei,FInstance (_,{ cf_name = s }))
+	| TField ({etype = TInst({cl_interface = true} as c,_)} as ei,FInstance (_,_,{ cf_name = s }))
 		when (try (match (PMap.find s c.cl_fields).cf_kind with Var _ -> true | _ -> false) with Not_found -> false) ->
 		spr ctx "(";
 		gen_value ctx ei;

+ 20 - 20
gencommon.ml

@@ -1395,7 +1395,7 @@ let field_access gen (t:t) (field:string) : (tfield_access) =
 		| _ -> FNotFound
 
 let field_access_esp gen t field = match field with
-	| FStatic(cl,cf) | FInstance(cl,cf) when Meta.has Meta.Extern cf.cf_meta ->
+	| FStatic(cl,cf) | FInstance(cl,_,cf) when Meta.has Meta.Extern cf.cf_meta ->
 		let static = match field with
 			| FStatic _ -> true
 			| _ -> false
@@ -1410,7 +1410,7 @@ let field_access_esp gen t field = match field with
 let mk_field_access gen expr field pos =
 	match field_access gen expr.etype field with
 		| FClassField(c,p,dc,cf,false,at,_) ->
-				{ eexpr = TField(expr, FInstance(dc,cf)); etype = apply_params c.cl_params p at; epos = pos }
+				{ eexpr = TField(expr, FInstance(dc,p,cf)); etype = apply_params c.cl_params p at; epos = pos }
 		| FClassField(c,p,dc,cf,true,at,_) ->
 				{ eexpr = TField(expr, FStatic(dc,cf)); etype = at; epos = pos }
 		| FAnonField cf ->
@@ -2055,7 +2055,7 @@ struct
 							| Method(MethDynamic) ->
 								(match cf.cf_expr, cf.cf_params with
 									| Some e, [] ->
-										let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
+										let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
 										let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in
 										cf.cf_expr <- None;
 										let is_override = List.memq cf cl.cl_overrides in
@@ -2068,7 +2068,7 @@ struct
 									| Some e, _ ->
 										let params = List.map (fun _ -> t_dynamic) cf.cf_params in
 										let fn = apply_params cf.cf_params params in
-										let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
+										let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
 										let rec change_expr e =
 											Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e
 										in
@@ -3170,7 +3170,7 @@ struct
 								eexpr = TConst TThis;
 								etype = TInst(cls, List.map snd cls.cl_params);
 								epos = pos;
-							}, FInstance(cls, cf));
+							}, FInstance(cls, List.map snd cls.cl_params, cf));
 							etype = cf.cf_type;
 							epos = pos;
 						}, List.map (fun (v,_) -> mk_local v pos) tfunc.tf_args);
@@ -4271,7 +4271,7 @@ struct
 						if not (PMap.mem name cl.cl_fields) then begin
 							let reverse_params = List.map (apply_params cls.cl_params (List.map snd cparams)) reverse_params in
 							let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in
-							let field = { eexpr = TField(this, FInstance(cl,cast_cfield)); etype = apply_params cast_cfield.cf_params reverse_params cast_cfield.cf_type; epos = p } in
+							let field = { eexpr = TField(this, FInstance(cl,List.map snd cl.cl_params, cast_cfield)); etype = apply_params cast_cfield.cf_params reverse_params cast_cfield.cf_type; epos = p } in
 							let call =
 							{
 								eexpr = TCall(field, []);
@@ -4380,10 +4380,10 @@ struct
 				(* this will take all fields that were *)
 				let fields_to_cases fields =
 					List.map (fun (cf, t_cl, t_cf) ->
-						let this_field = { eexpr = TField(this, FInstance(cl, cf)); etype = t_cl; epos = pos } in
+						let this_field = { eexpr = TField(this, FInstance(cl, List.map snd cl.cl_params, cf)); etype = t_cl; epos = pos } in
 						let expr =
 						{
-							eexpr = TBinop(OpAssign, { eexpr = TField(local_new_me, FInstance(cl, cf) ); etype = t_cf; epos = pos },
+							eexpr = TBinop(OpAssign, { eexpr = TField(local_new_me, FInstance(cl, List.map snd cl.cl_params, cf) ); etype = t_cf; epos = pos },
 								try (Hashtbl.find gen.gtparam_cast (get_path t_cf)) this_field t_cf with | Not_found -> (* if not found tparam cast, it shouldn't be a valid hxgeneric *) assert false
 							);
 							etype = t_cf;
@@ -4476,7 +4476,7 @@ struct
 				let params = List.map snd cparams in
 
 				let me = alloc_var "me" me_type in
-				let field = { eexpr = TField(mk_local me p, FInstance(iface,cf)); etype = apply_params cf.cf_params params cf.cf_type; epos = p } in
+				let field = { eexpr = TField(mk_local me p, FInstance(iface, List.map snd iface.cl_params, cf)); etype = apply_params cf.cf_params params cf.cf_type; epos = p } in
 				let call =
 				{
 					eexpr = TCall(field, []);
@@ -6065,7 +6065,7 @@ struct
 							cf,declared_t,false
 					| true ->
 					let (cf, actual_t, error), is_static = match f with
-						| FInstance(c,cf) | FClosure(Some c,cf) ->
+						| 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 *)
@@ -6100,7 +6100,7 @@ struct
 				in
 				(* set the real (selected) class field *)
 				let f = match f with
-					| FInstance(c,_) -> FInstance(c,cf)
+					| FInstance(c,tl,_) -> FInstance(c,tl,cf)
 					| FClosure(c,_) -> FClosure(c,cf)
 					| FStatic(c,_) -> FStatic(c,cf)
 					| f -> f
@@ -6717,7 +6717,7 @@ struct
 	let call_super ctx fn_args ret_t cf cl this_t pos =
 		{
 			eexpr = TCall({
-				eexpr = TField({ eexpr = TConst(TSuper); etype = this_t; epos = pos }, FInstance(cl,cf));
+				eexpr = TField({ eexpr = TConst(TSuper); etype = this_t; epos = pos }, FInstance(cl,List.map snd cl.cl_params,cf));
 				etype = TFun(fun_args fn_args, ret_t);
 				epos = pos;
 			}, List.map (fun (v,_) -> mk_local v pos) fn_args);
@@ -7477,7 +7477,7 @@ struct
 						fun () ->
 							mk_return {
 								eexpr = TCall(
-									{ eexpr = TField({ eexpr = TConst TSuper; etype = t; epos = pos }, FInstance(cl, cfield)); etype = !fun_type; epos = pos },
+									{ eexpr = TField({ eexpr = TConst TSuper; etype = t; epos = pos }, FInstance(cl, List.map snd cl.cl_params, cfield)); etype = !fun_type; epos = pos },
 									(List.map (fun (v,_) -> mk_local v pos) args) );
 								etype = if is_float then basic.tfloat else t_dynamic;
 								epos = pos;
@@ -7497,7 +7497,7 @@ struct
 				in
 
 				let do_field cf cf_type is_static =
-					let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, cf)); etype = cf_type; epos = pos } in
+					let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf_type; epos = pos } in
 					let this = if is_static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
 					let value_local = if is_float then match follow cf_type with
 						| TInst({ cl_kind = KTypeParameter _ }, _) ->
@@ -7585,13 +7585,13 @@ struct
 								eexpr = TIf(
 									handle_prop_local,
 									mk_return (mk_this_call_raw ("get_" ^ cf.cf_name) (TFun(["value",false,cf.cf_type], cf.cf_type)) [	]),
-									Some { eexpr = TField (ethis, FInstance(cl, cf)); etype = cf_type; epos = pos }
+									Some { eexpr = TField (ethis, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf_type; epos = pos }
 								);
 								etype = cf_type;
 								epos = pos;
 							}
 						| Var _
-						| Method MethDynamic -> { eexpr = TField (ethis, FInstance(cl,cf)); etype = cf_type; epos = pos }
+						| Method MethDynamic -> { eexpr = TField (ethis, FInstance(cl,List.map snd cl.cl_params,cf)); etype = cf_type; epos = pos }
 						| _ ->
 								{ eexpr = TField (this, FClosure(Some cl, cf)); etype = cf_type; epos = pos }
 				in
@@ -7834,7 +7834,7 @@ struct
 							(if is_some if_not_inst then get if_not_inst else []) @
 							[{
 								eexpr = TCall(
-									{ eexpr = TField({ eexpr = TConst TSuper; etype = TInst(cl, List.map snd cl.cl_params); epos = pos }, FInstance(cl, cf)); etype = t; epos = pos },
+									{ eexpr = TField({ eexpr = TConst TSuper; etype = TInst(cl, List.map snd cl.cl_params); epos = pos }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = t; epos = pos },
 									base_arr :: (if ctx.rcf_handle_statics then [is_inst] else [])
 								);
 								etype = basic.tvoid;
@@ -8523,7 +8523,7 @@ struct
 					let expr = {
 						eexpr = TCall(
 							{
-								eexpr = (if static then TField(mk_classtype_access cl pos, FStatic(cl, cf)) else TField(this, FInstance(cl, cf)));
+								eexpr = (if static then TField(mk_classtype_access cl pos, FStatic(cl, cf)) else TField(this, FInstance(cl, List.map snd cl.cl_params, cf)));
 								etype = cf.cf_type;
 								epos = cf.cf_pos;
 							},
@@ -10640,7 +10640,7 @@ struct
 									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 field = { eexpr = TField(this, FInstance(c,List.map snd c.cl_params,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
@@ -10705,7 +10705,7 @@ struct
 												{
 													eexpr = TField(
 														{ eexpr = TConst TThis; etype = TInst(c, List.map snd c.cl_params); epos = p },
-														FInstance(c,f));
+														FInstance(c,List.map snd c.cl_params,f));
 													etype = f.cf_type;
 													epos = p
 												},

+ 10 - 10
gencpp.ml

@@ -340,7 +340,7 @@ let has_meta_key meta key =
 
 let get_field_access_meta field_access key =
 match field_access with
-   | FInstance(_,class_field)
+   | FInstance(_,_,class_field)
    | FStatic(_,class_field) -> get_meta_string class_field.cf_meta key
    | _ -> ""
 ;;
@@ -483,7 +483,7 @@ let is_addressOf_call func =
 let is_lvalue var =
    match (remove_parens var).eexpr with
    | TLocal _ -> true
-   | TField (_,FStatic(_,field) ) | TField (_,FInstance(_,field) ) -> is_var_field field
+   | TField (_,FStatic(_,field) ) | TField (_,FInstance(_,_,field) ) -> is_var_field field
    | _ -> false
 ;;
 
@@ -1823,7 +1823,7 @@ and gen_expression ctx retval expression =
                   check_array_element_cast field_object.etype "Fast" "";
 
                already_dynamic := (match field with
-                  | FInstance(_,var) when is_var_field var -> true
+                  | FInstance(_,_,var) when is_var_field var -> true
                   | _ -> false);
             end;
          end;
@@ -1936,7 +1936,7 @@ and gen_expression ctx retval expression =
       in
       let expr_type = type_string expression.etype in
       let rec is_fixed_override e = (not (is_scalar expr_type)) && match e.eexpr with
-      | TField(obj,FInstance(_,field) ) ->
+      | TField(obj,FInstance(_,_,field) ) ->
          let cpp_type = member_type ctx obj field.cf_name in
          (not (is_scalar cpp_type)) && (
             let fixed = (cpp_type<>"?") && (expr_type<>"Dynamic") && (cpp_type<>"Dynamic") &&
@@ -1950,7 +1950,7 @@ and gen_expression ctx retval expression =
       | _ -> false
       in
       let check_extern_pointer_cast e = match (remove_parens e).eexpr with
-      | TField (_,FInstance(class_def,_) )
+      | TField (_,FInstance(class_def,_,_) )
       | TField (_,FStatic(class_def,_) )
          when class_def.cl_extern ->
          (try
@@ -4655,13 +4655,13 @@ class script_writer common_ctx ctx filename =
          | TField (obj,FStatic (class_def,field) ) when is_real_function field ->
                   this#write ("CALLSTATIC " ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ^
                      argN ^ "\n");
-         | TField (obj,FInstance (_,field) ) when (is_this obj) && (is_real_function field) ->
+         | TField (obj,FInstance (_,_,field) ) when (is_this obj) && (is_real_function field) ->
                   this#write ("CALLTHIS " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^
                      argN ^ "\n");
-         | TField (obj,FInstance (_,field) ) when is_super obj ->
+         | TField (obj,FInstance (_,_,field) ) when is_super obj ->
                   this#write ("CALLSUPER " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^
                      argN ^ "\n");
-         | TField (obj,FInstance (_,field) ) when is_real_function field ->
+         | TField (obj,FInstance (_,_,field) ) when is_real_function field ->
                   this#write ("CALLMEMBER " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^
                      argN ^ "\n");
                   this#gen_expression obj;
@@ -4710,8 +4710,8 @@ class script_writer common_ctx ctx filename =
       | FDynamic name -> this#write ("FNAME " ^ typeText ^ " " ^ (this#stringText name) ^ "\n");
             this#gen_expression obj;
       | FStatic (class_def,field) -> this#write ("FSTATIC " ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) );
-      | FInstance (_,field) when is_this obj -> this#write ("FTHISINST " ^ typeText ^ " " ^ (this#stringText field.cf_name) );
-      | FInstance (_,field) -> this#write ("FLINK " ^ typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n");
+      | FInstance (_,_,field) when is_this obj -> this#write ("FTHISINST " ^ typeText ^ " " ^ (this#stringText field.cf_name) );
+      | FInstance (_,_,field) -> this#write ("FLINK " ^ typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n");
             this#gen_expression obj;
 
       | FClosure (_,field) when is_this obj -> this#write ("FTHISNAME " ^typeText ^ " " ^  (this#stringText field.cf_name) ^ "\n")

+ 14 - 14
gencs.ml

@@ -416,24 +416,24 @@ struct
 				(* end Std.int() *)
 
 				(* TODO: change cf_name *)
-				| TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = "length" })) ->
+				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "length" })) ->
 					{ e with eexpr = TField(run ef, FDynamic "Length") }
-				| TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = "toLowerCase" })) ->
+				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "toLowerCase" })) ->
 					{ e with eexpr = TField(run ef, FDynamic "ToLowerInvariant") }
-				| TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = "toUpperCase" })) ->
+				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "toUpperCase" })) ->
 					{ e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") }
 
 				| TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) ->
 					{ e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); mk_int gen 1 cc.epos]) }
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("charAt" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("charCodeAt" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("indexOf" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("lastIndexOf" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("split" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("substring" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("substr" as field) })) }, args ) ->
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("lastIndexOf" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("split" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("substring" as field) })) }, args )
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("substr" as field) })) }, args ) ->
 					{ e with eexpr = TCall(mk_static_field_access_infer string_ext field e.epos [], [run ef] @ (List.map run args)) }
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, { cf_name = ("toString") })) }, [] ) ->
+				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("toString") })) }, [] ) ->
 					run ef
 				| TNew( { cl_path = ([], "String") }, [], [p] ) -> run p (* new String(myString) -> myString *)
 
@@ -1125,7 +1125,7 @@ let configure gen =
 						expr_s w v
 					end else
 						do_call w e [v]
-				| TField (e, (FStatic(_, cf) | FInstance(_, cf))) when Meta.has Meta.Native cf.cf_meta ->
+				| TField (e, (FStatic(_, cf) | FInstance(_, _, cf))) when Meta.has Meta.Native cf.cf_meta ->
 					let rec loop meta = match meta with
 						| (Meta.Native, [EConst (String s), _],_) :: _ ->
 							expr_s w e; write w "."; write_field w s
@@ -1293,9 +1293,9 @@ let configure gen =
 				| TCall ({ eexpr = TLocal( { v_name = "__rethrow__" } ) }, _) ->
 					write w "throw"
 				(* operator overloading handling *)
-				| TCall({ eexpr = TField(ef, FInstance(cl,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
+				| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
 					expr_s w { e with eexpr = TArray(ef, idx) }
-				| TCall({ eexpr = TField(ef, FInstance(cl,{ cf_name = "__set" })) }, [idx; v]) when not (is_hxgen (TClassDecl cl)) ->
+				| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__set" })) }, [idx; v]) when not (is_hxgen (TClassDecl cl)) ->
 					expr_s w { e with eexpr = TBinop(Ast.OpAssign, { e with eexpr = TArray(ef, idx) }, v) }
 				| TCall({ eexpr = TField(ef, FStatic(_,cf)) }, el) when PMap.mem cf.cf_name binops_names ->
 					let _, elr = extract_tparams [] el in

+ 3 - 3
genjava.ml

@@ -555,14 +555,14 @@ struct
 					run (mk_cast basic.tint obj)
 				(* end Std.int() *)
 
-				| TField( ef, FInstance({ cl_path = ([], "String") }, { cf_name = "length" }) ) ->
+				| TField( ef, FInstance({ cl_path = ([], "String") }, _, { cf_name = "length" }) ) ->
 					{ e with eexpr = TCall(Type.map_expr run e, []) }
 				| TField( ef, field ) when field_name field = "length" && is_string ef.etype ->
 					{ e with eexpr = TCall(Type.map_expr run e, []) }
 				| TCall( ( { eexpr = TField(ef, field) } as efield ), args ) when is_string ef.etype && String.get (field_name field) 0 = '_' ->
 					let field = field_name field in
 					{ e with eexpr = TCall({ efield with eexpr = TField(run ef, FDynamic (String.sub field 1 ( (String.length field) - 1)) )}, List.map run args) }
-				| TCall( ( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, field )) } as efield ), args ) ->
+				| TCall( ( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, field )) } as efield ), args ) ->
 					let field = field.cf_name in
 					(match field with
 						| "charAt" | "charCodeAt" | "split" | "indexOf"
@@ -707,7 +707,7 @@ let rec handle_throws gen cf =
 				) ecatches;
 				if !needs_check_block then Type.iter iter etry;
 				throws := old
-			| TField(e, (FInstance(_,f) | FStatic(_,f) | FClosure(_,f))) ->
+			| TField(e, (FInstance(_,_,f) | FStatic(_,f) | FClosure(_,f))) ->
 				let tdefs = collect_throws [] f.cf_meta in
 				if tdefs <> [] && not (List.for_all (fun c -> cls_any_super c !throws) tdefs) then
 					raise Exit;

+ 5 - 5
genpy.ml

@@ -410,7 +410,7 @@ module Transformer = struct
 			) length_map [] in
 			let c_string = match !t_string with TInst(c,_) -> c | _ -> assert false in
 			let cf_length = PMap.find "length" c_string.cl_fields in
-			let ef = mk (TField(e1,FInstance(c_string,cf_length))) !t_int e1.epos in
+			let ef = mk (TField(e1,FInstance(c_string,[],cf_length))) !t_int e1.epos in
 			let res_var = alloc_var (ae.a_next_id()) ef.etype in
 			let res_local = {ef with eexpr = TLocal res_var} in
 			let var_expr = {ef with eexpr = TVar(res_var,Some ef)} in
@@ -1333,7 +1333,7 @@ module Printer = struct
 		in
 		let name = field_name fa in
 		let is_extern = (match fa with
-		| FInstance(c,_) -> c.cl_extern
+		| FInstance(c,_,_) -> c.cl_extern
 		| FStatic(c,_) -> c.cl_extern
 		| _ -> false)
 		in
@@ -1347,9 +1347,9 @@ module Printer = struct
 		in
 		match fa with
 			(* we need to get rid of these cases in the transformer, how is this handled in js *)
-			| FInstance(c,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
+			| FInstance(c,_,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
 				Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
-			| FInstance(c,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
+			| FInstance(c,_,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
 				Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
 			| FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "String")(TClassDecl c) ->
 				Printf.sprintf "HxString.fromCharCode"
@@ -1777,7 +1777,7 @@ module Generator = struct
 			| _,Some ({eexpr = TFunction f} as ef) ->
 				let ethis = mk (TConst TThis) (TInst(c,List.map snd c.cl_params)) cf.cf_pos in
 				let member_data = List.map (fun cf ->
-					let ef = mk (TField(ethis,FInstance(c, cf))) cf.cf_type cf.cf_pos in
+					let ef = mk (TField(ethis,FInstance(c,[],cf))) cf.cf_type cf.cf_pos in (* TODO *)
 					mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos
 				) member_inits in
 				let e = {f.tf_expr with eexpr = TBlock (member_data @ [f.tf_expr])} in

+ 1 - 1
genswf9.ml

@@ -2059,7 +2059,7 @@ let check_constructor ctx c f =
 		Type.iter loop e;
 		match e.eexpr with
 		| TCall ({ eexpr = TConst TSuper },_) -> raise Exit
-		| TBinop (OpAssign,{ eexpr = TField({ eexpr = TConst TThis },FInstance (cc,cf)) },_) when c != cc && (match classify ctx cf.cf_type with KFloat | KDynamic -> true | _ -> false) ->
+		| TBinop (OpAssign,{ eexpr = TField({ eexpr = TConst TThis },FInstance (cc,_,cf)) },_) when c != cc && (match classify ctx cf.cf_type with KFloat | KDynamic -> true | _ -> false) ->
 			error "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos
 		| _ -> ()
 	in

+ 4 - 2
interp.ml

@@ -4526,7 +4526,7 @@ and encode_tfunc func =
 
 and encode_field_access fa =
 	let tag,pl = match fa with
-		| FInstance(c,cf) -> 0,[encode_clref c;encode_cfref cf]
+		| FInstance(c,_,cf) -> 0,[encode_clref c;encode_cfref cf] (* TODO: breaking change, kind of *)
 		| FStatic(c,cf) -> 1,[encode_clref c;encode_cfref cf]
 		| FAnon(cf) -> 2,[encode_cfref cf]
 		| FDynamic(s) -> 3,[enc_string s]
@@ -4676,7 +4676,9 @@ let decode_efield v =
 
 let decode_field_access v =
 	match decode_enum v with
-	| 0, [c;cf] -> FInstance(decode_ref c,decode_ref cf)
+	| 0, [c;cf] ->
+		let c = decode_ref c in
+		FInstance(c,List.map snd c.cl_params,decode_ref cf) (* TODO: breaking change? *)
 	| 1, [c;cf] -> FStatic(decode_ref c,decode_ref cf)
 	| 2, [cf] -> FAnon(decode_ref cf)
 	| 3, [s] -> FDynamic(dec_string s)

+ 5 - 5
optimizer.ml

@@ -1099,7 +1099,7 @@ let rec reduce_loop ctx e =
 		| None -> reduce_expr ctx e
 		| Some e -> reduce_loop ctx e)
 	| TCall ({ eexpr = TField (o,FClosure (c,cf)) } as f,el) ->
-		let fmode = (match c with None -> FAnon cf | Some c -> FInstance (c,cf)) in
+		let fmode = (match c with None -> FAnon cf | Some c -> FInstance (c,[],cf)) in (* TODO *)
 		{ e with eexpr = TCall ({ f with eexpr = TField (o,fmode) },el) }
 	| TSwitch (e1,[[{eexpr = TConst (TBool true)}],{eexpr = TConst (TBool true)}],Some ({eexpr = TConst (TBool false)})) ->
 		(* introduced by extractors in some cases *)
@@ -1244,7 +1244,7 @@ let inline_constructors ctx e =
 								match e.eexpr with
 								| TBlock el ->
 									List.iter get_assigns el
-								| TBinop (OpAssign, { eexpr = TField ({ eexpr = TLocal vv },FInstance(_,cf)); etype = t }, e) when v == vv ->
+								| TBinop (OpAssign, { eexpr = TField ({ eexpr = TLocal vv },FInstance(_,_,cf)); etype = t }, e) when v == vv ->
 									assigns := (cf.cf_name,e,t) :: !assigns
 								| _ ->
 									raise Exit
@@ -1269,7 +1269,7 @@ let inline_constructors ctx e =
 					end
 				| None -> ()
 			end
-		| TField({eexpr = TLocal v}, (FInstance(_, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) ->
+		| TField({eexpr = TLocal v}, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) ->
 			()
 		| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
 			let (_,_,fields,_,_) = PMap.find (-v.v_id) !vars in
@@ -1279,7 +1279,7 @@ let inline_constructors ctx e =
 			begin match e1.eexpr with
 				| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 && not (is_valid_field v (Int32.to_string i)) ->
 					cancel v
-				| TField({eexpr = TLocal v}, (FInstance(_, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) when v.v_id < 0 && not (is_valid_field v s) ->
+				| TField({eexpr = TLocal v}, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) when v.v_id < 0 && not (is_valid_field v s) ->
 					cancel v
 				| _ ->
 					find_locals e1
@@ -1323,7 +1323,7 @@ let inline_constructors ctx e =
 				in
 				List.iter (fun (v,e) -> append (mk (TVar(v,Some (subst e))) ctx.t.tvoid e.epos)) (List.rev vars);
 				mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos
-			| TField ({ eexpr = TLocal v },FInstance (c,cf)) when v.v_id < 0 ->
+			| TField ({ eexpr = TLocal v },FInstance (c,_,cf)) when v.v_id < 0 ->
 				let (_, vars),el_init = PMap.find (-v.v_id) vfields in
 				(try
 					let v = PMap.find cf.cf_name vars in

+ 18 - 17
type.ml

@@ -132,7 +132,7 @@ and texpr_expr =
 	| TEnumParameter of texpr * tenum_field * int
 
 and tfield_access =
-	| FInstance of tclass * tclass_field
+	| FInstance of tclass * tparams * tclass_field
 	| FStatic of tclass * tclass_field
 	| FAnon of tclass_field
 	| FDynamic of string
@@ -616,12 +616,12 @@ let is_closed a = !(a.a_status) <> Opened
 
 let field_name f =
 	match f with
-	| FAnon f | FInstance (_,f) | FStatic (_,f) | FClosure (_,f) -> f.cf_name
+	| FAnon f | FInstance (_,_,f) | FStatic (_,f) | FClosure (_,f) -> f.cf_name
 	| FEnum (_,f) -> f.ef_name
 	| FDynamic n -> n
 
 let extract_field = function
-	| FAnon f | FInstance (_,f) | FStatic (_,f) | FClosure (_,f) -> Some f
+	| FAnon f | FInstance (_,_,f) | FStatic (_,f) | FClosure (_,f) -> Some f
 	| _ -> None
 
 let is_extern_field f =
@@ -635,19 +635,20 @@ let field_type f =
 	| [] -> f.cf_type
 	| l -> monomorphs l f.cf_type
 
-let rec raw_class_field build_type c i =
+let rec raw_class_field build_type c tl i =
+	let apply = apply_params c.cl_params tl in
 	try
 		let f = PMap.find i c.cl_fields in
-		Some c, build_type f , f
+		Some (c,tl), build_type f , f
 	with Not_found -> try (match c.cl_constructor with
-		| Some ctor when i = "new" -> Some c, build_type ctor,ctor
+		| Some ctor when i = "new" -> Some (c,tl), build_type ctor,ctor
 		| _ -> raise Not_found)
 	with Not_found -> try
 		match c.cl_super with
 		| None ->
 			raise Not_found
 		| Some (c,tl) ->
-			let c2 , t , f = raw_class_field build_type c i in
+			let c2 , t , f = raw_class_field build_type c (List.map apply tl) i in
 			c2, apply_params c.cl_params tl t , f
 	with Not_found ->
 		match c.cl_kind with
@@ -663,10 +664,10 @@ let rec raw_class_field build_type c i =
 							None, build_type f, f
 						with
 							Not_found -> loop ctl)
-					| TInst (c,pl) ->
+					| TInst (c,tl) ->
 						(try
-							let c2, t , f = raw_class_field build_type c i in
-							c2, apply_params c.cl_params pl t, f
+							let c2, t , f = raw_class_field build_type c (List.map apply tl) i in
+							c2, apply_params c.cl_params tl t, f
 						with
 							Not_found -> loop ctl)
 					| _ ->
@@ -684,7 +685,7 @@ let rec raw_class_field build_type c i =
 					raise Not_found
 				| (c,tl) :: l ->
 					try
-						let c2, t , f = raw_class_field build_type c i in
+						let c2, t , f = raw_class_field build_type c (List.map apply tl) i in
 						c2, apply_params c.cl_params tl t, f
 					with
 						Not_found -> loop l
@@ -695,9 +696,9 @@ let class_field = raw_class_field field_type
 
 let quick_field t n =
 	match follow t with
-	| TInst (c,_) ->
-		let c, _, f = raw_class_field (fun f -> f.cf_type) c n in
-		(match c with None -> FAnon f | Some c -> FInstance (c,f))
+	| TInst (c,tl) ->
+		let c, _, f = raw_class_field (fun f -> f.cf_type) c tl n in
+		(match c with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f))
 	| TAnon a ->
 		(match !(a.a_status) with
 		| EnumStatics e ->
@@ -865,7 +866,7 @@ let rec s_expr s_type e =
 	| TField (e,f) ->
 		let fstr = (match f with
 			| FStatic (c,f) -> "static(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ ")"
-			| FInstance (c,f) -> "inst(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ " : " ^ s_type f.cf_type ^ ")"
+			| FInstance (c,_,f) -> "inst(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ " : " ^ s_type f.cf_type ^ ")"
 			| FClosure (c,f) -> "closure(" ^ (match c with None -> f.cf_name | Some c -> s_type_path c.cl_path ^ "." ^ f.cf_name)  ^ ")"
 			| FAnon f -> "anon(" ^ f.cf_name ^ ")"
 			| FEnum (en,f) -> "enum(" ^ s_type_path en.e_path ^ "." ^ f.ef_name ^ ")"
@@ -1340,7 +1341,7 @@ let rec unify a b =
 			| _ -> ());
 		(try
 			PMap.iter (fun n f2 ->
-				let _, ft, f1 = (try class_field c n with Not_found -> error [has_no_field a n]) in
+				let _, ft, f1 = (try class_field c tl n with Not_found -> error [has_no_field a n]) in
 				if not (unify_kind f1.cf_kind f2.cf_kind) then error [invalid_kind n f1.cf_kind f2.cf_kind];
 				if f2.cf_public && not f1.cf_public then error [invalid_visibility n];
 				(try
@@ -1827,7 +1828,7 @@ let map_expr_type f ft fv e =
 		let v = try
 			let n = match v with
 				| FClosure _ -> raise Not_found
-				| FAnon f | FInstance (_,f) | FStatic (_,f) -> f.cf_name
+				| FAnon f | FInstance (_,_,f) | FStatic (_,f) -> f.cf_name
 				| FEnum (_,f) -> f.ef_name
 				| FDynamic n -> n
 			in

+ 15 - 1
typecore.ml

@@ -122,13 +122,20 @@ and typer = {
 	mutable on_error : typer -> string -> pos -> unit;
 }
 
-type error_msg =
+type call_error =
+	| Not_enough_arguments
+	| Too_many_arguments
+	| Could_not_unify of error_msg
+	| Cannot_skip_non_nullable of string
+
+and error_msg =
 	| Module_not_found of path
 	| Type_not_found of path * string
 	| Unify of unify_error list
 	| Custom of string
 	| Unknown_ident of string
 	| Stack of error_msg * error_msg
+	| Call_error of call_error
 
 exception Fatal_error of string * Ast.pos
 
@@ -253,6 +260,13 @@ let rec error_msg = function
 	| Unknown_ident s -> "Unknown identifier : " ^ s
 	| Custom s -> s
 	| Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
+	| Call_error err -> s_call_error err
+
+and s_call_error = function
+	| Not_enough_arguments -> "Not enough arguments"
+	| Too_many_arguments -> "Too many arguments"
+	| Could_not_unify err -> error_msg err
+	| Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
 
 let pass_name = function
 	| PBuildModule -> "build-module"

+ 5 - 5
typeload.ml

@@ -452,7 +452,7 @@ and load_complex_type ctx p t =
 					c2.cl_private <- true;
 					PMap.iter (fun f _ ->
 						try
-							ignore(class_field c f);
+							ignore(class_field c tl f);
 							error ("Cannot redefine field " ^ f) p
 						with
 							Not_found -> ()
@@ -859,9 +859,9 @@ let check_overriding ctx c =
 						) overloads
 					) true
 				) f.cf_overloads
-	  end else
+			end else
 				check_field f (fun csup i ->
-					let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup i in
+					let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup params i in
 					t, f2) false
 		) c.cl_fields
 
@@ -875,7 +875,7 @@ let class_field_no_interf c i =
 			raise Not_found
 		| Some (c,tl) ->
 			(* rec over class_field *)
-			let _, t , f = raw_class_field (fun f -> f.cf_type) c i in
+			let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in
 			apply_params c.cl_params tl t , f
 
 let rec check_interface ctx c intf params =
@@ -2107,7 +2107,7 @@ let init_class ctx c p context_init herits fields =
 			let check_method m t req_name =
 				if ctx.com.display <> DMNone then () else
 				try
-					let _, t2, f = (if stat then let f = PMap.find m c.cl_statics in Some c, f.cf_type, f else class_field c m) in
+					let _, t2, f = (if stat then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in
 					(* accessors must be public on As3 (issue #1872) *)
 					if Common.defined ctx.com Define.As3 then f.cf_meta <- (Meta.Public,[],p) :: f.cf_meta;
 					(match f.cf_kind with

+ 189 - 215
typer.ml

@@ -239,8 +239,8 @@ let field_type ctx c pl f p =
 		if not (Meta.has Meta.Generic f.cf_meta) then add_constraint_checks ctx c.cl_params pl f monos p;
 		apply_params l monos f.cf_type
 
-let class_field ctx c pl name p =
-	raw_class_field (fun f -> field_type ctx c pl f p) c name
+let class_field ctx c tl name p =
+	raw_class_field (fun f -> field_type ctx c tl f p) c tl name
 
 (* checks if we can access to a given class field using current context *)
 let rec can_access ctx ?(in_overload=false) c cf stat =
@@ -667,155 +667,133 @@ let is_forced_inline c cf =
 	| _ when Meta.has Meta.Extern cf.cf_meta -> true
 	| _ -> false
 
-let rec unify_call_args ctx ?(overloads=None) cf el args r p inline =
-	(* 'overloads' will carry a ( return_result ) list, called 'compatible' *)
-	(* it's used to correctly support an overload selection algorithm *)
-	let overloads, compatible, legacy = match cf, overloads with
-		| Some(TInst(c,pl),f), None when ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta ->
-				let overloads = List.filter (fun (_,f2) ->
-					not (f == f2) && (f2.cf_public || can_access ctx ~in_overload:true c f2 false)
-				) (Typeload.get_overloads c f.cf_name) in
-				if overloads = [] then (* is static function *)
-					let overloads = List.map (fun f -> f.cf_type, f) f.cf_overloads in
-					let is_static = f.cf_name <> "new" in
-					List.filter (fun (_,f) -> can_access ctx ~in_overload:true c f is_static) overloads, [], false
-				else
-					overloads, [], false
-		| Some(_,f), None ->
-				List.map (fun f -> f.cf_type, f) f.cf_overloads, [], true
-		| _, Some s ->
-				s
-		| _ -> [], [], true
-	in
-	let next ?retval () =
-		let compatible = Option.map_default (fun r -> r :: compatible) compatible retval in
-		match cf, overloads with
-		| Some (TInst(c,pl),_), (ft,o) :: l ->
-			let o = { o with cf_type = ft } in
-			let args, ret = (match follow (apply_params c.cl_params pl (field_type ctx c pl o p)) with (* I'm getting non-followed types here. Should it happen? *)
-				| TFun (tl,t) -> tl, t
-				| _ -> assert false
-			) in
-			Some (unify_call_args ctx ~overloads:(Some (l,compatible,legacy)) (Some (TInst(c,pl),o)) el args ret p inline)
-		| Some (t,_), (ft,o) :: l ->
-			let o = { o with cf_type = ft } in
-			let args, ret = (match Type.field_type o with
-				| TFun (tl,t) -> tl, t
-				| _ -> assert false
-			) in
-			Some (unify_call_args ctx ~overloads:(Some (l,compatible,legacy)) (Some (t, o)) el args ret p inline)
-		| _ ->
-			match compatible with
-			| [] -> None
-			| [acc,t] -> Some (List.map fst acc, t)
-			| comp ->
-				match Codegen.Overloads.reduce_compatible compatible with
-				| [acc,t] -> Some (List.map fst acc, t)
-				| (acc,t) :: _ -> (* ambiguous overload *)
-					let name = match cf with | Some(_,f) -> "'" ^ f.cf_name ^ "' " | _ -> "" in
-					let format_amb = String.concat "\n" (List.map (fun (_,t) ->
-						"Function " ^ name ^ "with type " ^ (s_type (print_context()) t)
-					) compatible) in
-					display_error ctx ("This call is ambiguous between the following methods:\n" ^ format_amb) p;
-					Some (List.map fst acc,t)
-				| [] -> None
-	in
-	let fun_details() =
-		let format_arg = (fun (name,opt,_) -> (if opt then "?" else "") ^ name) in
-		"Function " ^ (match cf with None -> "" | Some (_,f) -> "'" ^ f.cf_name ^ "' ") ^ "requires " ^ (if args = [] then "no arguments" else "arguments : " ^ String.concat ", " (List.map format_arg args))
-	in
-	let invalid_skips = ref [] in
-	let error acc txt =
-		match next() with
-		| Some l -> l
-		| None ->
-		display_error ctx (txt ^ " arguments\n" ^ (fun_details())) p;
-		List.rev (List.map fst acc), (TFun(args,r))
+let rec unify_call_args' ctx el args r p inline force_inline =
+	let call_error err p =
+		raise (Error (Call_error err,p))
 	in
 	let arg_error ul name opt p =
-		match next() with
-		| Some l -> l
-		| None -> raise (Error (Stack (Unify ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")), p))
+		let err = Stack (Unify ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in
+		call_error (Could_not_unify err) p
 	in
-	let rec no_opt = function
-		| [] -> []
-		| ({ eexpr = TConst TNull },true) :: l -> no_opt l
-		| l -> l
-	in
-	let rec default_value t po =
+	let rec default_value name t =
 		if is_pos_infos t then
 			let infos = mk_infos ctx p [] in
 			let e = type_expr ctx infos (WithType t) in
-			(e, true)
-		else begin
-			if not ctx.com.config.pf_can_skip_non_nullable_argument then begin match po with
-				| Some (name,p) when not (is_nullable t) -> invalid_skips := (name,p) :: !invalid_skips;
-				| _ -> ()
-			end;
-			(null (ctx.t.tnull t) p, true)
-		end
+			e
+		else
+			null (ctx.t.tnull t) p
 	in
-	let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in
-	let rec loop acc l l2 skip check_rest =
-		match l , l2 with
-		| [] , [] ->
-			begin match !invalid_skips with
-				| [] -> ()
-				| skips -> List.iter (fun (name,p) -> display_error ctx ("Cannot skip non-nullable argument " ^ name) p) skips
-			end;
-			let args,tf = if not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls then
-				List.rev (no_opt acc), (TFun(args,r))
-			else
-				List.rev (acc), (TFun(args,r))
-			in
-			if not legacy && ctx.com.config.pf_overload then
-				match next ~retval:(args,tf) () with
-				| Some l -> l
-				| None ->
-					display_error ctx ("No overloaded function matches the arguments. Are the arguments correctly typed?") p;
-					List.map fst args, tf
-			else
-				List.map fst args, tf
-		| l , [(name,opt,t)] when check_rest ->
-			(match follow t with
+	let skipped = ref [] in
+	let skip name ul t =
+		if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then
+			call_error (Cannot_skip_non_nullable name) p;
+		skipped := (name,ul) :: !skipped;
+		default_value name t
+	in
+	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *)
+	let force_inline, is_extern = false, false in
+	let type_against t e =
+		let e = type_expr ctx e (WithTypeResume t) in
+		(try unify_raise ctx e.etype t e.epos with Error (Unify l,p) -> raise (WithTypeError (l,p)));
+		let e = Codegen.AbstractCast.check_cast ctx t e p in
+		e
+	in
+	let rec loop el args = match el,args with
+		| [],[] ->
+			[]
+		| _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe"],"Rest"},_) -> true | _ -> false) ->
+			begin match follow t with
 				| TAbstract({a_path=(["haxe"],"Rest")},[t]) ->
-					let rec process acc el =
-						match el with
-						| [] -> acc
-						| ee :: rest ->
-							let e = type_expr ctx ee (WithTypeResume t) in
-							begin try
-								unify_raise ctx e.etype t e.epos
-							with Error (Unify ul,p) ->
-								raise (Error (Stack (Unify ul,Custom ("For rest function argument '" ^ name ^ "'")), p))
-							end;
-							process ((Codegen.AbstractCast.check_cast ctx t e p,false) :: acc) rest
-					in
-					loop (process acc l) [] [] skip false
+					(try List.map (fun e -> type_against t e,false) el with WithTypeError(ul,p) -> arg_error ul name false p)
 				| _ ->
-					loop acc l l2 skip false)
-		| [] , (_,false,_) :: _ ->
-			error (List.fold_left (fun acc (_,_,t) -> default_value t None :: acc) acc l2) "Not enough"
-		| [] , (name,true,t) :: l ->
-			loop (default_value t None :: acc) [] l skip check_rest
-		| _ , [] ->
-			(match List.rev skip with
-			| [] -> error acc "Too many"
-			| [name,ul] -> arg_error ul name true p
-			| (name,ul) :: _ -> arg_error (Unify_custom ("Invalid arguments\n" ^ fun_details()) :: ul) name true p)
-		| ee :: l, (name,opt,t) :: l2 ->
-			try
-				let e = type_expr ctx ee (WithTypeResume t) in
-				(try unify_raise ctx e.etype t e.epos with Error (Unify l,p) -> raise (WithTypeError (l,p)));
-				loop ((Codegen.AbstractCast.check_cast ctx t e p,false) :: acc) l l2 skip check_rest
+					assert false
+			end
+		| [],(_,false,_) :: _ ->
+			call_error Not_enough_arguments p
+		| [],(name,true,t) :: args ->
+			begin match loop [] args with
+				| [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls -> []
+				| args ->
+					let e_def = default_value name t in
+					(e_def,true) :: args
+			end
+		| (_,p) :: _, [] ->
+			begin match List.rev !skipped with
+				| [] -> call_error Too_many_arguments p
+				| (s,ul) :: _ -> arg_error ul s true p
+			end
+		| e :: el,(name,opt,t) :: args ->
+			begin try
+				let e = type_against t e in
+				(e,opt) :: loop el args
 			with
 				WithTypeError (ul,p) ->
 					if opt then
-						loop (default_value t (Some (name,p)) :: acc) (ee :: l) l2 ((name,ul) :: skip) check_rest
+						let e_def = skip name ul t in
+						(e_def,true) :: loop (e :: el) args
 					else
 						arg_error ul name false p
+			end
+	in
+	let el = loop el args in
+	el,TFun(args,r)
+
+let unify_call_args ctx el args r p inline force_inline =
+	let el,tf = unify_call_args' ctx el args r p inline force_inline in
+	List.map fst el,tf
+
+let unify_field_call ctx fa el args ret p inline =
+	let map_cf map cf = map (monomorphs cf.cf_params cf.cf_type),cf in
+	let expand_overloads map cf =
+		(TFun(args,ret),cf) :: (List.map (map_cf map) cf.cf_overloads)
+	in
+	let candidates,co,cf,mk_fa = match fa with
+		| FStatic(c,cf) ->
+			expand_overloads (fun t -> t) cf,Some c,cf,(fun cf -> FStatic(c,cf))
+		| FAnon cf ->
+			expand_overloads (fun t -> t) cf,None,cf,(fun cf -> FAnon cf)
+		| FInstance(c,tl,cf) ->
+			let map = apply_params c.cl_params tl in
+			let cfl = if cf.cf_name = "new" || not (Meta.has Meta.Overload cf.cf_meta && ctx.com.config.pf_overload) then
+				List.map (map_cf map) cf.cf_overloads
+			else
+				List.map (fun (t,cf) -> map (monomorphs cf.cf_params t),cf) (Typeload.get_overloads c cf.cf_name)
+			in
+			(TFun(args,ret),cf) :: cfl,None,cf,(fun cf -> FInstance(c,tl,cf))
+		| _ ->
+			error "Invalid field call" p
+	in
+	let is_forced_inline = is_forced_inline co cf in
+	let is_overload = Meta.has Meta.Overload cf.cf_meta in
+	let candidates,failures = List.fold_left (fun (candidates,failures) (t,cf) ->
+		begin try
+			begin match follow t with
+				| TFun(args,ret) ->
+				let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in
+					let mk_call ethis =
+						let ef = mk (TField(ethis,fa)) tf p in
+						make_call ctx ef (List.map fst el) ret p
+					in
+					(el,tf,mk_call)	:: candidates,failures
+				| _ ->
+					assert false
+			end
+		with Error (Call_error _,_) as err ->
+			candidates,err :: failures
+		end
+	) ([],[]) candidates in
+	let fail () = match List.rev failures with
+		| err :: _ -> raise err
+		| _ -> assert false
 	in
-	loop [] el args [] is_extern
+	if is_overload && ctx.com.config.pf_overload then begin match Codegen.Overloads.reduce_compatible candidates with
+		| [] -> fail()
+		| [el,tf,mk_call] -> List.map fst el,tf,mk_call
+		| _ -> error "Ambiguous overload" p
+	end else begin match List.rev candidates with
+		| [] -> fail()
+		| (el,tf,mk_call) :: _ -> List.map fst el,tf,mk_call
+	end
 
 let fast_enum_field e ef p =
 	let et = mk (TTypeExpr (TEnumDecl e)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }) p in
@@ -895,7 +873,7 @@ let make_call ctx e params t p =
 	try
 		let ethis, fname = (match e.eexpr with TField (ethis,f) -> ethis, field_name f | _ -> raise Exit) in
 		let f, cl = (match follow ethis.etype with
-			| TInst (c,params) -> (try let _,_,f = Type.class_field c fname in f with Not_found -> raise Exit), Some c
+			| TInst (c,params) -> (try let _,_,f = Type.class_field c params fname in f with Not_found -> raise Exit), Some c
 			| TAnon a -> (try PMap.find fname a.a_fields with Not_found -> raise Exit), (match !(a.a_status) with Statics c -> Some c | _ -> None)
 			| _ -> raise Exit
 		) in
@@ -982,7 +960,7 @@ let rec acc_get ctx g p =
 		| _ -> assert false)
 	| AKInline (e,f,fmode,t) ->
 		(* do not create a closure for static calls *)
-		let cmode = (match fmode with FStatic _ -> fmode | FInstance (c,f) -> FClosure (Some c,f) | _ -> assert false) in
+		let cmode = (match fmode with FStatic _ -> fmode | FInstance (c,_,f) -> FClosure (Some c,f) | _ -> assert false) in
 		ignore(follow f.cf_type); (* force computing *)
 		(match f.cf_expr with
 		| None ->
@@ -1106,8 +1084,8 @@ let field_access ctx mode f fmode t e p =
 			| MethMacro, MCall -> AKMacro (e,f)
 			| _ , MGet ->
 				let cmode = (match fmode with
-					| FInstance(_, cf) | FStatic(_, cf) when Meta.has Meta.Generic cf.cf_meta -> display_error ctx "Cannot create closure on generic function" p; fmode
-					| FInstance (c,cf) -> FClosure (Some c,cf)
+					| FInstance(_, _, cf) | FStatic(_, cf) when Meta.has Meta.Generic cf.cf_meta -> display_error ctx "Cannot create closure on generic function" p; fmode
+					| FInstance (c,_,cf) -> FClosure (Some c,cf)
 					| FStatic _ | FEnum _ -> fmode
 					| FAnon f -> FClosure (None, f)
 					| FDynamic _ | FClosure _ -> assert false
@@ -1285,7 +1263,7 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode =
 				let cf = { (mk_field v.v_name v.v_type e.epos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in
 				c.cl_extern <- true;
 				c.cl_fields <- PMap.add cf.cf_name cf PMap.empty;
-				AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, FInstance(c,cf), t)
+				AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, FInstance(c,[],cf), t)
 			| _ ->
 				AKExpr (mk (TLocal v) t p))
 		| _ ->
@@ -1293,8 +1271,8 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode =
 	with Not_found -> try
 		(* member variable lookup *)
 		if ctx.curfun = FunStatic then raise Not_found;
-		let c , t , f = class_field ctx ctx.curclass [] i p in
-		field_access ctx mode f (match c with None -> FAnon f | Some c -> FInstance (c,f)) t (get_this ctx p) p
+		let c , t , f = class_field ctx ctx.curclass (List.map snd ctx.curclass.cl_params) i p in
+		field_access ctx mode f (match c with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) t (get_this ctx p) p
 	with Not_found -> try
 		(* lookup using on 'this' *)
 		if ctx.curfun = FunStatic then raise Not_found;
@@ -1398,7 +1376,7 @@ and type_field ?(resume=false) ctx e i p mode =
 					with Unify_error l ->
 						display_error ctx "Field resolve has an invalid type" f.cf_pos;
 						display_error ctx (error_msg (Unify [Cannot_unify(tfield,texpect)])) f.cf_pos);
-					AKExpr (make_call ctx (mk (TField (e,FInstance (c,f))) tfield p) [Codegen.type_constant ctx.com (String i) p] t p)
+					AKExpr (make_call ctx (mk (TField (e,FInstance (c,params,f))) tfield p) [Codegen.type_constant ctx.com (String i) p] t p)
 				end else
 					AKExpr (mk (TField (e,FDynamic i)) t p)
 			| None ->
@@ -1418,14 +1396,14 @@ and type_field ?(resume=false) ctx e i p mode =
 				| MCall, _ ->
 					()
 				| MGet,Var _
-				| MSet,Var _ when (match c2 with Some { cl_extern = true; cl_path = ("flash" :: _,_) } -> true | _ -> false) ->
+				| MSet,Var _ when (match c2 with Some ({ cl_extern = true; cl_path = ("flash" :: _,_) }, _) -> true | _ -> false) ->
 					()
 				| _, Method _ ->
 					display_error ctx "Cannot create closure on super method" p
 				| _ ->
 					display_error ctx "Normal variables cannot be accessed with 'super', use 'this' instead" p);
 			if not (can_access ctx c f false) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) p;
-			field_access ctx mode f (match c2 with None -> FAnon f | Some c -> FInstance (c,f)) (apply_params c.cl_params params t) e p
+			field_access ctx mode f (match c2 with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) (apply_params c.cl_params params t) e p
 		with Not_found -> try
 			using_field ctx mode e i p
 		with Not_found -> try
@@ -1655,8 +1633,8 @@ let unify_int ctx e k =
 		match follow t with
 		| TAnon a ->
 			(try is_dynamic (PMap.find f a.a_fields).cf_type with Not_found -> false)
-		| TInst (c,pl) ->
-			(try is_dynamic (apply_params c.cl_params pl ((let _,t,_ = Type.class_field c f in t))) with Not_found -> false)
+		| TInst (c,tl) ->
+			(try is_dynamic (apply_params c.cl_params tl ((let _,t,_ = Type.class_field c tl f in t))) with Not_found -> false)
 		| _ ->
 			true
 	in
@@ -1718,7 +1696,7 @@ let type_generic_function ctx (e,cf) el ?(using_param=None) with_type p =
 		| WithTypeResume t -> (try unify_raise ctx ret t p with Error (Unify l,_) -> raise (WithTypeError(l,p)))
 		| _ -> ()
 	end;
-	let el,_ = unify_call_args ctx None el args ret p false in
+	let el,_ = unify_call_args ctx el args ret p false false in
 	let el = match using_param with None -> el | Some e -> e :: el in
 	(try
 		let gctx = Codegen.make_generic ctx cf.cf_params monos p in
@@ -1764,8 +1742,8 @@ let type_generic_function ctx (e,cf) el ?(using_param=None) with_type p =
 			cf2
 		in
 		let e = if stat then type_type ctx c.cl_path p else e in
-		let e = acc_get ctx (field_access ctx MCall cf2 (if stat then FStatic (c,cf2) else FInstance (c,cf2)) cf2.cf_type e p) p in
-		(el,ret,e)
+		let e = acc_get ctx (field_access ctx MCall cf2 (if stat then FStatic (c,cf2) else FInstance (c,tl,cf2)) cf2.cf_type e p) p in
+		make_call ctx e el ret p
 	with Codegen.Generic_Exception (msg,p) ->
 		error msg p)
 
@@ -1801,7 +1779,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 			check_assign ctx e1;
 			(match e1.eexpr , e2.eexpr with
 			| TLocal i1 , TLocal i2 when i1 == i2 -> error "Assigning a value to itself" p
-			| TField ({ eexpr = TConst TThis },FInstance (_,f1)) , TField ({ eexpr = TConst TThis },FInstance (_,f2)) when f1 == f2 ->
+			| TField ({ eexpr = TConst TThis },FInstance (_,_,f1)) , TField ({ eexpr = TConst TThis },FInstance (_,_,f2)) when f1 == f2 ->
 				error "Assigning a value to itself" p
 			| _ , _ -> ());
 			mk (TBinop (op,e1,e2)) e1.etype p
@@ -1949,7 +1927,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 				let std = type_type ctx ([],"Std") e.epos in
 				let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in
 				ignore(follow acc.etype);
-				let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,f)) } | _ -> acc) in
+				let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,[],f)) } | _ -> acc) in
 				make_call ctx acc [e] ctx.t.tstring e.epos
 			| KAbstract (a,tl) ->
 				loop (Abstract.get_underlying_type a tl)
@@ -2949,7 +2927,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let el = e1 :: el in
 		let v = gen_local ctx tmap in
 		let ev = mk (TLocal v) tmap p in
-		let ef = mk (TField(ev,FInstance(c,cf))) (tfun [tkey;tval] ctx.t.tvoid) p in
+		let ef = mk (TField(ev,FInstance(c,[tkey;tval],cf))) (tfun [tkey;tval] ctx.t.tvoid) p in
 		let el = ev :: List.fold_left (fun acc e -> match fst e with
 			| EBinop(OpArrow,e1,e2) ->
 				let e1,e2 = type_arrow e1 e2 in
@@ -3045,7 +3023,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					if fhasnext.cf_kind <> Method MethInline then raise Exit;
 					let tmp = gen_local ctx e1.etype in
 					let eit = mk (TLocal tmp) e1.etype p in
-					let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in
+					let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, pl, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in
 					let enext = mk (TVar (i,Some (make_call ctx (mk (TField (eit,FDynamic "next")) (TFun ([],pt)) p) [] pt p))) ctx.t.tvoid p in
 					let eblock = (match e2.eexpr with
 						| TBlock el -> { e2 with eexpr = TBlock (enext :: el) }
@@ -3244,7 +3222,8 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let unify_constructor_call c params f ct = match follow ct with
 			| TFun (args,r) ->
 				(try
-					fst (unify_call_args ctx (Some (TInst(c,params),f)) el args r p false)
+					let el,_,_ = unify_field_call ctx (FInstance(c,params,f)) el args r p false in
+					el
 				with Error (e,p) ->
 					display_error ctx (error_msg e) p;
 					[])
@@ -3267,14 +3246,16 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			| mt ->
 				error ((s_type_path (t_infos mt).mt_path) ^ " cannot be constructed") p
 		in
-		let ct = (match t with
-			| TAbstract (a,pl) ->
-				(match a.a_impl with
-				| None -> t
-				| Some c -> TInst (c,pl))
-			| _ -> t
-		) in
-		(match ct with
+		let build_constructor_call c tl =
+			let ct, f = get_constructor ctx c tl p in
+			if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p;
+			(match f.cf_kind with
+			| Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p)
+			| _ -> ());
+			let el = unify_constructor_call c tl f ct in
+			el,f,ct
+		in
+		(match t with
 		| TInst ({cl_kind = KTypeParameter tl} as c,params) ->
 			if not (Typeload.is_generic_parameter ctx c) then error "Only generic type parameters can be constructed" p;
 			let el = List.map (fun e -> type_expr ctx e Value) el in
@@ -3289,21 +3270,15 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| _ -> false
 			) tl) then error (s_type_path c.cl_path ^ " does not have a constructor") p;
 			mk (TNew (c,params,el)) t p
-		| TInst (c,params) ->
-			let ct, f = get_constructor ctx c params p in
-			if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p;
-			(match f.cf_kind with
-			| Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p)
-			| _ -> ());
-			let el = unify_constructor_call c params f ct in
-			(match c.cl_kind with
-			| KAbstractImpl a when not (Meta.has Meta.MultiType a.a_meta) ->
-				let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
-				let e = mk (TTypeExpr (TClassDecl c)) ta p in
-				let e = mk (TField (e,(FStatic (c,f)))) ct p in
-				make_call ctx e el t p
-			| _ ->
-				mk (TNew (c,params,el)) t p)
+		| TAbstract({a_impl = Some c} as a,tl) when not (Meta.has Meta.MultiType a.a_meta) ->
+			let el,cf,ct = build_constructor_call c tl in
+			let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
+			let e = mk (TTypeExpr (TClassDecl c)) ta p in
+			let e = mk (TField (e,(FStatic (c,cf)))) ct p in
+			make_call ctx e el t p
+		| TInst (c,params) | TAbstract({a_impl = Some c},params) ->
+			let el,_,_ = build_constructor_call c params in
+			mk (TNew (c,params,el)) t p
 		| _ ->
 			error (s_type (print_context()) t ^ " cannot be constructed") p)
 	| EUnop (op,flag,e) ->
@@ -3510,7 +3485,7 @@ and handle_display ctx e_ast iscall p =
 			if ctx.com.display = DMPosition then
 				raise (DisplayPosition [ef.ef_pos]);
 			ef.ef_meta <- (Meta.Usage,[],p) :: ef.ef_meta;
-		| TField(_,(FAnon cf | FInstance (_,cf) | FStatic (_,cf) | FClosure (_,cf))) ->
+		| TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) ->
 			handle_field cf;
 		| TLocal v ->
 			v.v_meta <- (Meta.Usage,[],p) :: v.v_meta;
@@ -3771,9 +3746,10 @@ and type_call ctx e el (with_type:with_type) p =
 		| None -> error "Current class does not have a super" p
 		| Some (c,params) ->
 			let ct, f = get_constructor ctx c params p in
-			let el, _ = (match follow ct with
+			let el = (match follow ct with
 			| TFun (args,r) ->
-				unify_call_args ctx (Some (TInst(c,params),f)) el args r p false
+				let el,_,_ = unify_field_call ctx (FInstance(c,params,f)) el args r p false in
+				el
 			| _ ->
 				error "Constructor is not a function" p
 			) in
@@ -3784,11 +3760,6 @@ and type_call ctx e el (with_type:with_type) p =
 		def ()
 
 and build_call ctx acc el (with_type:with_type) p =
-	let fopts t f = match follow t with
-		| (TInst (c,pl) as t) -> Some (t,f)
-		| (TAnon a) as t -> (match !(a.a_status) with Statics c -> Some (TInst(c,List.map snd c.cl_params),f) | _ -> Some (t,f))
-		| _ -> None
-	in
 	let push_this e =
 		match e.eexpr with
 			| TConst (TInt _ | TFloat _ | TString _ | TBool _) ->
@@ -3800,19 +3771,19 @@ and build_call ctx acc el (with_type:with_type) p =
 	in
 	match acc with
 	| AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta ->
-		let el,t,e = type_generic_function ctx (ethis,f) el with_type p in
-		make_call ctx e el t p
+		type_generic_function ctx (ethis,f) el with_type p
 	| AKInline (ethis,f,fmode,t) ->
-		let params, tfunc = (match follow t with
-			| TFun (args,r) -> unify_call_args ctx (fopts ethis.etype f) el args r p true
-			| _ -> error (s_type (print_context()) t ^ " cannot be called") p
-		) in
-		make_call ctx (mk (TField (ethis,fmode)) t p) params (match tfunc with TFun(_,r) -> r | _ -> assert false) p
+		(match follow t with
+			| TFun (args,r) ->
+				let _,_,mk_call = unify_field_call ctx fmode el args r p true in
+				mk_call ethis
+			| _ ->
+				error (s_type (print_context()) t ^ " cannot be called") p
+		)
 	| AKUsing (et,cl,ef,eparam) when Meta.has Meta.Generic ef.cf_meta ->
 		(match et.eexpr with
 		| TField(ec,_) ->
-			let el,t,e = type_generic_function ctx (ec,ef) el ~using_param:(Some eparam) with_type p in
-			make_call ctx e el t p
+			type_generic_function ctx (ec,ef) el ~using_param:(Some eparam) with_type p
 		| _ -> assert false)
 	| AKUsing (et,cl,ef,eparam) ->
 		begin match ef.cf_kind with
@@ -3833,7 +3804,7 @@ and build_call ctx acc el (with_type:with_type) p =
 				| TFun ((_,_,t1) :: args,r) ->
 					unify ctx tthis t1 eparam.epos;
 					let ef = prepare_using_field ef in
-					begin match unify_call_args ctx (Some (TInst(cl,[]),ef)) el args r p (ef.cf_kind = Method MethInline) with
+					begin match unify_call_args ctx el args r p (ef.cf_kind = Method MethInline) (is_forced_inline (Some cl) ef) with
 					| el,TFun(args,r) -> el,args,r,(if is_abstract_impl_call then eparam else Codegen.AbstractCast.check_cast ctx t1 eparam eparam.epos)
 					| _ -> assert false
 					end
@@ -3898,36 +3869,39 @@ and build_call ctx acc el (with_type:with_type) p =
 	| AKExpr e ->
 		let rec loop t = match follow t with
 		| TFun (args,r) ->
-			let fopts = (match acc with
-				| AKExpr {eexpr = TField(e, (FStatic (_,f) | FInstance(_,f) | FAnon(f)))} ->
-					fopts e.etype f
-				| _ ->
-					None
-			) in
-			(match fopts,acc with
-				| Some (_,cf),AKExpr({eexpr = TField(e,_)}) when Meta.has Meta.Generic cf.cf_meta ->
-					type_generic_function ctx (e,cf) el with_type p
+			begin match e.eexpr with
+				| TField(e1,fa) when not (match fa with FEnum _ -> true | _ -> false) ->
+					begin match fa with
+						| FInstance(_,_,cf) | FStatic(_,cf) when Meta.has Meta.Generic cf.cf_meta ->
+							type_generic_function ctx (e1,cf) el with_type p
+						| _ ->
+							let _,_,mk_call = unify_field_call ctx fa el args r p false in
+							mk_call e1
+					end
 				| _ ->
-					let el, tfunc = unify_call_args ctx fopts el args r p false in
-					el,(match tfunc with TFun(_,r) -> r | _ -> assert false), {e with etype = tfunc})
+					let el, tfunc = unify_call_args ctx el args r p false false in
+					let r = match tfunc with TFun(_,r) -> r | _ -> assert false in
+					mk (TCall ({e with etype = tfunc},el)) r p
+			end
 		| TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta ->
 			loop (Abstract.get_underlying_type a tl)
 		| TMono _ ->
 			let t = mk_mono() in
 			let el = List.map (fun e -> type_expr ctx e Value) el in
 			unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos;
-			el, t, e
+			mk (TCall (e,el)) t p
 		| t ->
 			let el = List.map (fun e -> type_expr ctx e Value) el in
-			el, (if t == t_dynamic then
+			let t = if t == t_dynamic then
 				t_dynamic
 			else if ctx.untyped then
 				mk_mono()
 			else
-				error (s_type (print_context()) e.etype ^ " cannot be called") e.epos), e
+				error (s_type (print_context()) e.etype ^ " cannot be called") e.epos
+			in
+			mk (TCall (e,el)) t p
 		in
-		let el , t, e = loop e.etype in
-		mk (TCall (e,el)) t p
+		loop e.etype
 
 (* ---------------------------------------------------------------------- *)
 (* FINALIZATION *)
@@ -4609,7 +4583,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 			incr index;
 			(EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p)
 		) el in
-		let elt, _ = unify_call_args mctx (Some (TInst(mclass,[]),mfield)) constants (List.map fst eargs) t_dynamic p false in
+		let elt, _ = unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false in
 		List.iter (fun f -> f()) (!todo);
 		List.map2 (fun (_,ise) e ->
 			let e, et = (match e.eexpr with
@@ -4696,7 +4670,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 
 let call_macro ctx path meth args p =
 	let mctx, (margs,_,mclass,mfield), call = load_macro ctx path meth p in
-	let el, _ = unify_call_args mctx (Some (TInst(mclass,[]),mfield)) args margs t_dynamic p false in
+	let el, _ = unify_call_args mctx args margs t_dynamic p false false in
 	call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el)
 
 let call_init_macro ctx e =