2
0
Эх сурвалжийг харах

Move some stuff around (#9774)

* [typer] move some things around

* don't forget things
Simon Krajewski 5 жил өмнө
parent
commit
5e29d884de

+ 4 - 1
src/context/abstractCast.ml

@@ -4,6 +4,7 @@ open Ast
 open Type
 open Typecore
 open Error
+open CallUnification
 
 let cast_stack = new_rec_stack()
 
@@ -307,4 +308,6 @@ let handle_abstract_casts ctx e =
 		| _ ->
 			Type.map_expr (loop ctx) e
 	in
-	loop ctx e
+	loop ctx e
+;;
+Typecore.cast_or_unify_raise_ref := cast_or_unify_raise

+ 34 - 0
src/context/typecore.ml

@@ -161,18 +161,48 @@ type 'a field_call_candidate = {
 	fc_data  : 'a;
 }
 
+type field_host =
+	| FHStatic of tclass
+	| FHInstance of tclass * tparams
+	| FHAbstract of tabstract * tparams * tclass
+	| FHAnon
+
+type field_access = {
+	(* The expression on which the field is accessed. For abstracts, this is a type expression
+	   to the implementation class. *)
+	fa_on     : texpr;
+	(* The field being accessed. *)
+	fa_field  : tclass_field;
+	(* The host of the field. *)
+	fa_host   : field_host;
+	(* Whether or not to inline the access. This can be set for non-inline fields via `inline call()` syntax. *)
+	fa_inline : bool;
+	(* The position of the field access expression in syntax. *)
+	fa_pos    : pos;
+}
+
+type static_extension_access = {
+	(* The `this` expression which should be passed as first argument. *)
+	se_this   : texpr;
+	(* The field access information. *)
+	se_access : field_access;
+}
+
 exception Forbid_package of (string * path * pos) * pos list * string
 
 exception WithTypeError of error_msg * pos
 
 let memory_marker = [|Unix.time()|]
 
+let locate_macro_error = ref true
+
 let make_call_ref : (typer -> texpr -> texpr list -> t -> ?force_inline:bool -> pos -> texpr) ref = ref (fun _ _ _ _ ?force_inline:bool _ -> die "" __LOC__)
 let type_expr_ref : (?mode:access_mode -> typer -> expr -> WithType.t -> texpr) ref = ref (fun ?(mode=MGet) _ _ _ -> die "" __LOC__)
 let type_block_ref : (typer -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ -> die "" __LOC__)
 let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> die "" __LOC__)
 let unify_min_for_type_source_ref : (typer -> texpr list -> WithType.with_type_source option -> t) ref = ref (fun _ _ _ -> die "" __LOC__)
 let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> die "" __LOC__)
+let cast_or_unify_raise_ref : (typer -> ?uctx:unification_context option -> Type.t -> texpr -> pos -> texpr) ref = ref (fun _ ?uctx _ _ _ -> assert false)
 
 let pass_name = function
 	| PBuildModule -> "build-module"
@@ -514,6 +544,10 @@ let rec can_access ctx c cf stat =
 		| _ -> false)
 	|| (Meta.has Meta.PrivateAccess ctx.meta)
 
+let check_field_access ctx c f stat p =
+	if not ctx.untyped && not (can_access ctx c f stat) then
+		display_error ctx ("Cannot access private field " ^ f.cf_name) p
+
 (** removes the first argument of the class field's function type and all its overloads *)
 let prepare_using_field cf = match follow cf.cf_type with
 	| TFun((_,_,tf) :: args,ret) ->

+ 589 - 0
src/typing/callUnification.ml

@@ -0,0 +1,589 @@
+open Globals
+open Ast
+open Type
+open Typecore
+open Error
+open FieldAccess
+
+let is_forced_inline c cf =
+	match c with
+	| Some { cl_kind = KAbstractImpl _ } -> true
+	| Some c when has_class_flag c CExtern -> true
+	| _ when has_class_field_flag cf CfExtern -> true
+	| _ -> false
+
+let relative_path ctx file =
+	let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in
+	let fpath = slashes (Path.get_full_path file) in
+	let fpath_lower = String.lowercase fpath in
+	let flen = String.length fpath_lower in
+	let rec loop = function
+		| [] -> file
+		| path :: l ->
+			let spath = String.lowercase (slashes path) in
+			let slen = String.length spath in
+			if slen > 0 && slen < flen && String.sub fpath_lower 0 slen = spath then String.sub fpath slen (flen - slen) else loop l
+	in
+	loop ctx.com.Common.class_path
+
+let mk_infos ctx p params =
+	let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Path.get_full_path p.pfile else relative_path ctx p.pfile in
+	(EObjectDecl (
+		(("fileName",null_pos,NoQuotes) , (EConst (String(file,SDoubleQuotes)) , p)) ::
+		(("lineNumber",null_pos,NoQuotes) , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) ::
+		(("className",null_pos,NoQuotes) , (EConst (String (s_type_path ctx.curclass.cl_path,SDoubleQuotes)),p)) ::
+		if ctx.curfield.cf_name = "" then
+			params
+		else
+			(("methodName",null_pos,NoQuotes), (EConst (String (ctx.curfield.cf_name,SDoubleQuotes)),p)) :: params
+	) ,p)
+
+let rec is_pos_infos = function
+	| TMono r ->
+		(match r.tm_type with
+		| Some t -> is_pos_infos t
+		| _ -> false)
+	| TLazy f ->
+		is_pos_infos (lazy_type f)
+	| TType ({ t_path = ["haxe"] , "PosInfos" },[]) ->
+		true
+	| TType (t,tl) ->
+		is_pos_infos (apply_params t.t_params tl t.t_type)
+	| TAbstract({a_path=[],"Null"},[t]) ->
+		is_pos_infos t
+	| _ ->
+		false
+
+let rec unify_call_args' ctx el args r callp inline force_inline =
+	let in_call_args = ctx.in_call_args in
+	ctx.in_call_args <- true;
+	let call_error err p =
+		raise (Error (Call_error err,p))
+	in
+	let arg_error ul name opt p =
+		let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in
+		call_error (Could_not_unify err) p
+	in
+	let mk_pos_infos t =
+		let infos = mk_infos ctx callp [] in
+		type_expr ctx infos (WithType.with_type t)
+	in
+	let rec default_value name t =
+		if is_pos_infos t then
+			mk_pos_infos t
+		else
+			null (ctx.t.tnull t) callp
+	in
+	let skipped = ref [] in
+	let invalid_skips = ref [] in
+	let skip name ul t p =
+		if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then
+			invalid_skips := name :: !invalid_skips;
+		skipped := (name,ul,p) :: !skipped;
+		default_value name t
+	in
+	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, (has_class_flag c CExtern) | _ -> false, false in *)
+	let type_against name t e =
+		try
+			let e = type_expr ctx e (WithType.with_argument t name) in
+			!cast_or_unify_raise_ref ctx t e e.epos
+		with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) ->
+			raise (WithTypeError (l,p))
+	in
+	let rec loop el args = match el,args with
+		| [],[] ->
+			begin match List.rev !invalid_skips with
+				| [] -> ()
+				| name :: _ -> call_error (Cannot_skip_non_nullable name) callp;
+			end;
+			[]
+		| _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> true | _ -> false) ->
+			begin match follow t with
+				| TAbstract({a_path=(["haxe";"extern"],"Rest")},[t]) ->
+					(try List.map (fun e -> type_against name t e,false) el with WithTypeError(ul,p) -> arg_error ul name false p)
+				| _ ->
+					die "" __LOC__
+			end
+		| [],(_,false,_) :: _ ->
+			call_error (Not_enough_arguments args) callp
+		| [],(name,true,t) :: args ->
+			begin match loop [] args with
+				| [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls ->
+					if is_pos_infos t then [mk_pos_infos t,true]
+					else []
+				| args ->
+					let e_def = default_value name t in
+					(e_def,true) :: args
+			end
+		| (e,p) :: el, [] ->
+			begin match List.rev !skipped with
+				| [] ->
+					if ctx.is_display_file && not (Diagnostics.is_diagnostics_run ctx.com p) then begin
+						ignore(type_expr ctx (e,p) WithType.value);
+						loop el []
+					end	else call_error Too_many_arguments p
+				| (s,ul,p) :: _ -> arg_error ul s true p
+			end
+		| e :: el,(name,opt,t) :: args ->
+			begin try
+				let e = type_against name t e in
+				(e,opt) :: loop el args
+			with
+				WithTypeError (ul,p)->
+					if opt && List.length el < List.length args then
+						let e_def = skip name ul t p in
+						(e_def,true) :: loop (e :: el) args
+					else
+						match List.rev !skipped with
+						| [] -> arg_error ul name opt p
+						| (s,ul,p) :: _ -> arg_error ul s true p
+			end
+	in
+	let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in
+	ctx.in_call_args <- in_call_args;
+	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
+
+type overload_kind =
+	| OverloadProper (* @:overload or overload *)
+	| OverloadMeta (* @:overload(function() {}) *)
+	| OverloadNone
+
+let unify_field_call ctx fa el_typed el p inline =
+	let expand_overloads cf =
+		cf :: cf.cf_overloads
+	in
+	let candidates,co,static,map,tmap = match fa.fa_host with
+		| FHStatic c ->
+			expand_overloads fa.fa_field,Some c,true,(fun t -> t),(fun t -> t)
+		| FHAnon ->
+			expand_overloads fa.fa_field,None,false,(fun t -> t),(fun t -> t)
+		| FHInstance(c,tl) ->
+			let cf = fa.fa_field in
+			let cfl = if cf.cf_name = "new" || not (has_class_field_flag cf CfOverload) then
+				cf :: cf.cf_overloads
+			else
+				List.map (fun (t,cf) ->
+					cf
+				) (Overloads.get_overloads ctx.com c cf.cf_name)
+			in
+			cfl,Some c,false,TClass.get_map_function c tl,(fun t -> t)
+		| FHAbstract(a,tl,c) ->
+			let map = apply_params a.a_params tl in
+			let tmap = if fa.fa_field.cf_name = "_new" (* TODO: BAD BAD BAD BAD *) then (fun t -> t) else (fun t -> map a.a_this) in
+			expand_overloads fa.fa_field,Some c,true,map,tmap
+	in
+	let is_forced_inline = is_forced_inline co fa.fa_field in
+	let overload_kind = if has_class_field_flag fa.fa_field CfOverload then OverloadProper
+		else if fa.fa_field.cf_overloads <> [] then OverloadMeta
+		else OverloadNone
+	in
+	let attempt_call cf =
+		let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+		let t = map (apply_params cf.cf_params monos cf.cf_type) in
+		match follow t with
+		| TFun(args,ret) ->
+			let rec loop acc_el acc_args tmap args el_typed = match args,el_typed with
+				| ((_,opt,t0) as arg) :: args,e :: el_typed ->
+					begin try
+						unify_raise ctx (tmap e.etype) t0 e.epos;
+					with Error(Unify _ as msg,p) ->
+						let call_error = Call_error(Could_not_unify msg) in
+						raise(Error(call_error,p))
+					end;
+					loop ((e,opt) :: acc_el) (arg :: acc_args) (fun t -> t) args el_typed
+				| _ ->
+					List.rev acc_el,List.rev acc_args,args
+			in
+			let el_typed,args_typed,args = loop [] [] tmap args el_typed in
+			let el,_ = unify_call_args' ctx el args ret p inline is_forced_inline in
+			let el = el_typed @ el in
+			let tf = TFun(args_typed @ args,ret) in
+			let mk_call () =
+				let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa cf fa.fa_host)) t fa.fa_pos in
+				let el = List.map fst el in
+				!make_call_ref ctx ef el ret ~force_inline:inline p
+			in
+			make_field_call_candidate el ret monos tf cf mk_call
+		| t ->
+			error (s_type (print_context()) t ^ " cannot be called") p
+	in
+	let maybe_raise_unknown_ident cerr p =
+		let rec loop err =
+			match err with
+			| Unknown_ident _ -> error (error_msg err) p
+			| Stack (e1,e2) -> (loop e1; loop e2)
+			| _ -> ()
+		in
+		match cerr with Could_not_unify err -> loop err | _ -> ()
+	in
+	let attempt_calls candidates =
+		let rec loop candidates = match candidates with
+			| [] -> [],[]
+			| cf :: candidates ->
+				let known_monos = List.map (fun (m,_) ->
+					m,m.tm_type,m.tm_constraints
+				) ctx.monomorphs.perfunction in
+				let current_monos = ctx.monomorphs.perfunction in
+				begin try
+					let candidate = attempt_call cf in
+					ctx.monomorphs.perfunction <- current_monos;
+					if overload_kind = OverloadProper then begin
+						let candidates,failures = loop candidates in
+						candidate :: candidates,failures
+					end else
+						[candidate],[]
+				with Error ((Call_error cerr as err),p) ->
+					List.iter (fun (m,t,constr) ->
+						if t != m.tm_type then m.tm_type <- t;
+						if constr != m.tm_constraints then m.tm_constraints <- constr;
+					) known_monos;
+					ctx.monomorphs.perfunction <- current_monos;
+					maybe_raise_unknown_ident cerr p;
+					let candidates,failures = loop candidates in
+					candidates,(cf,err,p) :: failures
+				end
+		in
+		loop candidates
+	in
+	let fail_fun () =
+		let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
+		let call () =
+			let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
+			mk (TCall(ef,[])) t_dynamic p
+		in
+		make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
+	in
+	let maybe_check_access cf =
+		(* type_field doesn't check access for overloads, so let's check it here *)
+		begin match co with
+		| Some c ->
+			check_field_access ctx c cf static p;
+		| None ->
+			()
+		end;
+	in
+	match candidates with
+	| [cf] ->
+		if overload_kind = OverloadProper then maybe_check_access cf;
+		begin try
+			attempt_call cf
+		with Error _ when ctx.com.display.dms_error_policy = EPIgnore ->
+			fail_fun();
+		end
+	| _ ->
+		let candidates,failures = attempt_calls candidates in
+		let fail () =
+			let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in
+			let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in
+			begin match failures with
+			| [_,msg,p] ->
+				error msg p
+			| _ ->
+				display_error ctx "Could not find a suitable overload, reasons follow" p;
+				List.iter (fun (cf,msg,p2) ->
+					display_error ctx ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p;
+					display_error ctx msg p2;
+				) failures;
+				error "End of overload failure reasons" p
+			end
+		in
+		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with
+			| [] -> fail()
+			| [fcc] ->
+				maybe_check_access fcc.fc_field;
+				fcc
+			| fcc :: l ->
+				display_error ctx "Ambiguous overload, candidates follow" p;
+				let st = s_type (print_context()) in
+				List.iter (fun fcc ->
+					display_error ctx (Printf.sprintf "... %s" (st fcc.fc_type)) fcc.fc_field.cf_name_pos;
+				) (fcc :: l);
+				fcc
+		end else begin match List.rev candidates with
+			| [] -> fail()
+			| fcc :: _ -> fcc
+		end
+
+let type_generic_function ctx fa el_typed el with_type p =
+	let c,stat = match fa.fa_host with
+		| FHInstance(c,tl) -> c,false
+		| FHStatic c -> c,true
+		| FHAbstract(a,tl,c) -> c,true
+		| _ -> die "" __LOC__
+	in
+	let cf = fa.fa_field in
+	if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p;
+	let fcc = unify_field_call ctx fa el_typed el p false in
+	begin match with_type with
+		| WithType.WithType(t,_) -> unify ctx fcc.fc_ret t p
+		| _ -> ()
+	end;
+	let monos = fcc.fc_monos in
+	List.iter (fun t -> match follow t with
+		| TMono m -> safe_mono_close ctx m p
+		| _ -> ()
+	) monos;
+	let el = List.map fst fcc.fc_args in
+	(try
+		let gctx = Generic.make_generic ctx cf.cf_params monos p in
+		let name = cf.cf_name ^ "_" ^ gctx.Generic.name in
+		let unify_existing_field tcf pcf = try
+			unify_raise ctx tcf fcc.fc_type p
+		with Error(Unify _,_) as err ->
+			display_error ctx ("Cannot create field " ^ name ^ " due to type mismatch") p;
+			display_error ctx (compl_msg "Conflicting field was defined here") pcf;
+			raise err
+		in
+		let fa = try
+			let cf2 = if stat then
+				let cf2 = PMap.find name c.cl_statics in
+				unify_existing_field cf2.cf_type cf2.cf_pos;
+				cf2
+			else
+				let cf2 = PMap.find name c.cl_fields in
+				unify_existing_field cf2.cf_type cf2.cf_pos;
+				cf2
+			in
+			{fa with fa_field = cf2}
+			(*
+				java.Lib.array() relies on the ability to shadow @:generic function for certain types
+				see https://github.com/HaxeFoundation/haxe/issues/8393#issuecomment-508685760
+			*)
+			(* if cf.cf_name_pos = cf2.cf_name_pos then
+				cf2
+			else
+				error ("Cannot specialize @:generic because the generated function name is already used: " ^ name) p *)
+		with Not_found ->
+			let finalize_field c cf2 =
+				ignore(follow cf.cf_type);
+				let rec check e = match e.eexpr with
+					| TNew({cl_kind = KTypeParameter _} as c,_,_) when not (TypeloadCheck.is_generic_parameter ctx c) ->
+						display_error ctx "Only generic type parameters can be constructed" e.epos;
+						display_error ctx "While specializing this call" p;
+					| _ ->
+						Type.iter check e
+				in
+				cf2.cf_expr <- (match cf.cf_expr with
+					| None ->
+						display_error ctx "Recursive @:generic function" p; None;
+					| Some e ->
+						let e = Generic.generic_substitute_expr gctx e in
+						check e;
+						Some e
+				);
+				cf2.cf_kind <- cf.cf_kind;
+				if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic;
+				cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: cf.cf_meta
+			in
+			let mk_cf2 name =
+				mk_field ~static:stat name fcc.fc_type cf.cf_pos cf.cf_name_pos
+			in
+			if stat then begin
+				if Meta.has Meta.GenericClassPerMethod c.cl_meta then begin
+					let c = Generic.static_method_container gctx c cf p in
+					let cf2 = try
+						let cf2 = PMap.find cf.cf_name c.cl_statics in
+						unify_existing_field cf2.cf_type cf2.cf_pos;
+						cf2
+					with Not_found ->
+						let cf2 = mk_cf2 cf.cf_name in
+						c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
+						c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
+						finalize_field c cf2;
+						cf2
+					in
+					{fa with fa_host = FHStatic c;fa_field = cf2;fa_on = Builder.make_static_this c p}
+				end else begin
+					let cf2 = mk_cf2 name in
+					c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
+					c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
+					finalize_field c cf2;
+					{fa with fa_field = cf2}
+				end
+			end else begin
+				let cf2 = mk_cf2 name in
+				if has_class_field_flag cf CfOverride then add_class_field_flag cf2 CfOverride;
+				c.cl_fields <- PMap.add cf2.cf_name cf2 c.cl_fields;
+				c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields;
+				finalize_field c cf2;
+				{fa with fa_field = cf2}
+			end
+		in
+		let e = FieldAccess.get_field_expr fa FCall in
+		make_call ctx e el fcc.fc_ret p
+	with Generic.Generic_Exception (msg,p) ->
+		error msg p)
+
+class call_dispatcher
+	(ctx : typer)
+	(mode : access_mode)
+	(with_type : WithType.t)
+	(p : pos)
+=
+	let is_set = match mode with MSet _ -> true | _ -> false in
+	let check_assign () = if is_set then invalid_assign p in
+
+object(self)
+
+	method private make_field_call (fa : field_access) (el_typed : texpr list) (el : expr list) =
+		let fcc = unify_field_call ctx fa el_typed el p fa.fa_inline in
+		if has_class_field_flag fcc.fc_field CfAbstract then begin match fa.fa_on.eexpr with
+			| TConst TSuper -> display_error ctx (Printf.sprintf "abstract method %s cannot be accessed directly" fcc.fc_field.cf_name) p;
+			| _ -> ()
+		end;
+		fcc.fc_data()
+
+	method private macro_call (ethis : texpr) (cf : tclass_field) (el : expr list) =
+		if ctx.macro_depth > 300 then error "Stack overflow" p;
+		ctx.macro_depth <- ctx.macro_depth + 1;
+		ctx.with_type_stack <- with_type :: ctx.with_type_stack;
+		let ethis_f = ref (fun () -> ()) in
+		let f = (match ethis.eexpr with
+		| TTypeExpr (TClassDecl c) ->
+			DeprecationCheck.check_cf ctx.com cf p;
+			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
+			| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
+			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = (!type_block_ref) ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
+			| Some e -> (fun() -> type_expr ~mode ctx e with_type))
+		| _ ->
+			(* member-macro call : since we will make a static call, let's find the actual class and not its subclass *)
+			(match follow ethis.etype with
+			| TInst (c,_) ->
+				let rec loop c =
+					if PMap.mem cf.cf_name c.cl_fields then
+						let eparam,f = push_this ctx ethis in
+						ethis_f := f;
+						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
+							| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
+							| Some e -> (fun() -> type_expr ~mode ctx e WithType.value)
+						in
+						e
+					else
+						match c.cl_super with
+						| None -> die "" __LOC__
+						| Some (csup,_) -> loop csup
+				in
+				loop c
+			| _ -> die "" __LOC__))
+		in
+		ctx.macro_depth <- ctx.macro_depth - 1;
+		ctx.with_type_stack <- List.tl ctx.with_type_stack;
+		let old = ctx.on_error in
+		ctx.on_error <- (fun ctx msg ep ->
+			(* display additional info in the case the error is not part of our original call *)
+			if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin
+				locate_macro_error := false;
+				old ctx msg ep;
+				locate_macro_error := true;
+				ctx.com.error (compl_msg "Called from macro here") p;
+			end else
+				old ctx msg ep;
+		);
+		let e = try
+			f()
+		with exc ->
+			ctx.on_error <- old;
+			!ethis_f();
+			raise exc
+		in
+		let e = Diagnostics.secure_generated_code ctx e in
+		ctx.on_error <- old;
+		!ethis_f();
+		e
+
+	(* Calls `e` with arguments `el`. Does not inspect the callee expression, so it should only be
+	   used with actual expression calls and not with something like field calls. *)
+	method expr_call (e : texpr) (el : expr list) =
+		check_assign();
+		let rec loop t = match follow t with
+		| TFun (args,r) ->
+			let el, tfunc = unify_call_args ctx el args r p false false in
+			let r = match tfunc with TFun(_,r) -> r | _ -> die "" __LOC__ in
+			mk (TCall (e,el)) r p
+		| 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 WithType.value) el in
+			unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos;
+			mk (TCall (e,el)) t p
+		| t ->
+			let el = List.map (fun e -> type_expr ctx e WithType.value) el in
+			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
+			in
+			mk (TCall (e,el)) t p
+		in
+		loop e.etype
+
+	(* Calls the resolve method represented by `sea` with an additional string-expression argument `name`. *)
+	method resolve_call (sea : static_extension_access) (name : string) =
+		let eparam = sea.se_this in
+		let e_name = Texpr.Builder.make_string ctx.t name null_pos in
+		self#field_call sea.se_access [eparam;e_name] []
+
+	(* Resolves the accessor function for `fa` and calls it with the provided arguments.
+	   If no accessor function is found (AccessorAnon case), a generic field access is generated instead.
+	*)
+	method accessor_call fa el_typed el =
+		match FieldAccess.resolve_accessor fa mode with
+			| AccessorFound fa_accessor ->
+				let dispatcher = new call_dispatcher ctx (MCall el) with_type p in
+				let e = dispatcher#field_call fa_accessor el_typed el in
+				let t = FieldAccess.get_map_function fa fa.fa_field.cf_type in
+				if not (type_iseq_strict t e.etype) then mk (TCast(e,None)) t e.epos else e
+			| AccessorAnon ->
+				let e = fa.fa_on in
+				let t = FieldAccess.get_map_function fa fa.fa_field.cf_type in
+				let el = List.map (fun e -> type_expr ctx e WithType.value) el in
+				let el_typed = el_typed @ el in
+				let tf = tfun (List.map (fun e -> e.etype) el_typed) t in
+				let name = Printf.sprintf "%s_%s" (if is_set then "set" else "get") fa.fa_field.cf_name in
+				make_call ctx (mk (TField (e,quick_field_dynamic e.etype name)) tf p) el_typed t p
+			| _ ->
+				error "Could not resolve accessor" p
+
+	(* Calls the field represented by `fa` with the typed arguments `el_typed` and the syntactic arguments `el`.
+
+	   This function inspects the nature of the field being called and dispatches the call accordingly:
+
+	   * If the field is `@:generic`, call `type_generic_function`.
+	   * If the field is a non-macro method, call it via `make_field_call`.
+	   * If the field is a property, resolve the accessor (depending on `mode`) and recurse onto it.
+	   * Otherwise, call the field as a normal expression via `expr_call`.
+	*)
+	method field_call (fa : field_access) (el_typed : texpr list) (el : expr list) =
+		match fa.fa_field.cf_kind with
+		| Method (MethNormal | MethInline | MethDynamic) ->
+			check_assign();
+			 if has_class_field_flag fa.fa_field CfGeneric then begin
+				type_generic_function ctx fa el_typed el with_type p
+			end else
+				self#make_field_call fa el_typed el
+		| Method MethMacro ->
+			begin match el_typed with
+			| [] ->
+				self#macro_call fa.fa_on fa.fa_field el
+			| el_typed ->
+				let cur = ctx.this_stack in
+				let el' = List.map (fun e -> fst (push_this ctx e)) el_typed in
+				let e = self#macro_call fa.fa_on fa.fa_field (el' @ el) in
+				ctx.this_stack <- cur;
+				e
+			end;
+		| Var v ->
+			begin match (if is_set then v.v_write else v.v_read) with
+			| AccCall ->
+				self#accessor_call fa el_typed el
+			| _ ->
+				self#expr_call (FieldAccess.get_field_expr fa FCall) el
+			end
+end

+ 1 - 541
src/typing/calls.ml

@@ -7,13 +7,7 @@ open Typecore
 open TyperBase
 open Fields
 open Error
-
-let is_forced_inline c cf =
-	match c with
-	| Some { cl_kind = KAbstractImpl _ } -> true
-	| Some c when has_class_flag c CExtern -> true
-	| _ when has_class_field_flag cf CfExtern -> true
-	| _ -> false
+open CallUnification
 
 let make_call ctx e params t ?(force_inline=false) p =
 	try
@@ -102,544 +96,10 @@ let mk_array_set_call ctx (cf,tf,r,e1,e2o) c ebase p =
 			let ef = mk (TField(et,(FStatic(c,cf)))) tf p in
 			make_call ctx ef [ebase;e1;evalue] r p
 
-let rec unify_call_args' ctx el args r callp inline force_inline =
-	let in_call_args = ctx.in_call_args in
-	ctx.in_call_args <- true;
-	let call_error err p =
-		raise (Error (Call_error err,p))
-	in
-	let arg_error ul name opt p =
-		let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in
-		call_error (Could_not_unify err) p
-	in
-	let mk_pos_infos t =
-		let infos = mk_infos ctx callp [] in
-		type_expr ctx infos (WithType.with_type t)
-	in
-	let rec default_value name t =
-		if is_pos_infos t then
-			mk_pos_infos t
-		else
-			null (ctx.t.tnull t) callp
-	in
-	let skipped = ref [] in
-	let invalid_skips = ref [] in
-	let skip name ul t p =
-		if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then
-			invalid_skips := name :: !invalid_skips;
-		skipped := (name,ul,p) :: !skipped;
-		default_value name t
-	in
-	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, (has_class_flag c CExtern) | _ -> false, false in *)
-	let type_against name t e =
-		try
-			let e = type_expr ctx e (WithType.with_argument t name) in
-			AbstractCast.cast_or_unify_raise ctx t e e.epos
-		with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) ->
-			raise (WithTypeError (l,p))
-	in
-	let rec loop el args = match el,args with
-		| [],[] ->
-			begin match List.rev !invalid_skips with
-				| [] -> ()
-				| name :: _ -> call_error (Cannot_skip_non_nullable name) callp;
-			end;
-			[]
-		| _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> true | _ -> false) ->
-			begin match follow t with
-				| TAbstract({a_path=(["haxe";"extern"],"Rest")},[t]) ->
-					(try List.map (fun e -> type_against name t e,false) el with WithTypeError(ul,p) -> arg_error ul name false p)
-				| _ ->
-					die "" __LOC__
-			end
-		| [],(_,false,_) :: _ ->
-			call_error (Not_enough_arguments args) callp
-		| [],(name,true,t) :: args ->
-			begin match loop [] args with
-				| [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls ->
-					if is_pos_infos t then [mk_pos_infos t,true]
-					else []
-				| args ->
-					let e_def = default_value name t in
-					(e_def,true) :: args
-			end
-		| (e,p) :: el, [] ->
-			begin match List.rev !skipped with
-				| [] ->
-					if ctx.is_display_file && not (Diagnostics.is_diagnostics_run ctx.com p) then begin
-						ignore(type_expr ctx (e,p) WithType.value);
-						loop el []
-					end	else call_error Too_many_arguments p
-				| (s,ul,p) :: _ -> arg_error ul s true p
-			end
-		| e :: el,(name,opt,t) :: args ->
-			begin try
-				let e = type_against name t e in
-				(e,opt) :: loop el args
-			with
-				WithTypeError (ul,p)->
-					if opt && List.length el < List.length args then
-						let e_def = skip name ul t p in
-						(e_def,true) :: loop (e :: el) args
-					else
-						match List.rev !skipped with
-						| [] -> arg_error ul name opt p
-						| (s,ul,p) :: _ -> arg_error ul s true p
-			end
-	in
-	let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in
-	ctx.in_call_args <- in_call_args;
-	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
-
-type overload_kind =
-	| OverloadProper (* @:overload or overload *)
-	| OverloadMeta (* @:overload(function() {}) *)
-	| OverloadNone
-
-let unify_field_call ctx fa el_typed el p inline =
-	let expand_overloads cf =
-		cf :: cf.cf_overloads
-	in
-	let candidates,co,static,map,tmap = match fa.fa_host with
-		| FHStatic c ->
-			expand_overloads fa.fa_field,Some c,true,(fun t -> t),(fun t -> t)
-		| FHAnon ->
-			expand_overloads fa.fa_field,None,false,(fun t -> t),(fun t -> t)
-		| FHInstance(c,tl) ->
-			let cf = fa.fa_field in
-			let cfl = if cf.cf_name = "new" || not (has_class_field_flag cf CfOverload) then
-				cf :: cf.cf_overloads
-			else
-				List.map (fun (t,cf) ->
-					cf
-				) (Overloads.get_overloads ctx.com c cf.cf_name)
-			in
-			cfl,Some c,false,TClass.get_map_function c tl,(fun t -> t)
-		| FHAbstract(a,tl,c) ->
-			let map = apply_params a.a_params tl in
-			let tmap = if fa.fa_field.cf_name = "_new" (* TODO: BAD BAD BAD BAD *) then (fun t -> t) else (fun t -> map a.a_this) in
-			expand_overloads fa.fa_field,Some c,true,map,tmap
-	in
-	let is_forced_inline = is_forced_inline co fa.fa_field in
-	let overload_kind = if has_class_field_flag fa.fa_field CfOverload then OverloadProper
-		else if fa.fa_field.cf_overloads <> [] then OverloadMeta
-		else OverloadNone
-	in
-	let attempt_call cf =
-		let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
-		let t = map (apply_params cf.cf_params monos cf.cf_type) in
-		match follow t with
-		| TFun(args,ret) ->
-			let rec loop acc_el acc_args tmap args el_typed = match args,el_typed with
-				| ((_,opt,t0) as arg) :: args,e :: el_typed ->
-					begin try
-						unify_raise ctx (tmap e.etype) t0 e.epos;
-					with Error(Unify _ as msg,p) ->
-						let call_error = Call_error(Could_not_unify msg) in
-						raise(Error(call_error,p))
-					end;
-					loop ((e,opt) :: acc_el) (arg :: acc_args) (fun t -> t) args el_typed
-				| _ ->
-					List.rev acc_el,List.rev acc_args,args
-			in
-			let el_typed,args_typed,args = loop [] [] tmap args el_typed in
-			let el,_ = unify_call_args' ctx el args ret p inline is_forced_inline in
-			let el = el_typed @ el in
-			let tf = TFun(args_typed @ args,ret) in
-			let mk_call () =
-				let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa cf fa.fa_host)) t fa.fa_pos in
-				let el = List.map fst el in
-				make_call ctx ef el ret ~force_inline:inline p
-			in
-			make_field_call_candidate el ret monos tf cf mk_call
-		| t ->
-			error (s_type (print_context()) t ^ " cannot be called") p
-	in
-	let maybe_raise_unknown_ident cerr p =
-		let rec loop err =
-			match err with
-			| Unknown_ident _ -> error (error_msg err) p
-			| Stack (e1,e2) -> (loop e1; loop e2)
-			| _ -> ()
-		in
-		match cerr with Could_not_unify err -> loop err | _ -> ()
-	in
-	let attempt_calls candidates =
-		let rec loop candidates = match candidates with
-			| [] -> [],[]
-			| cf :: candidates ->
-				let known_monos = List.map (fun (m,_) ->
-					m,m.tm_type,m.tm_constraints
-				) ctx.monomorphs.perfunction in
-				let current_monos = ctx.monomorphs.perfunction in
-				begin try
-					let candidate = attempt_call cf in
-					ctx.monomorphs.perfunction <- current_monos;
-					if overload_kind = OverloadProper then begin
-						let candidates,failures = loop candidates in
-						candidate :: candidates,failures
-					end else
-						[candidate],[]
-				with Error ((Call_error cerr as err),p) ->
-					List.iter (fun (m,t,constr) ->
-						if t != m.tm_type then m.tm_type <- t;
-						if constr != m.tm_constraints then m.tm_constraints <- constr;
-					) known_monos;
-					ctx.monomorphs.perfunction <- current_monos;
-					maybe_raise_unknown_ident cerr p;
-					let candidates,failures = loop candidates in
-					candidates,(cf,err,p) :: failures
-				end
-		in
-		loop candidates
-	in
-	let fail_fun () =
-		let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
-		let call () =
-			let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
-			mk (TCall(ef,[])) t_dynamic p
-		in
-		make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
-	in
-	let maybe_check_access cf =
-		(* type_field doesn't check access for overloads, so let's check it here *)
-		begin match co with
-		| Some c ->
-			check_field_access ctx c cf static p;
-		| None ->
-			()
-		end;
-	in
-	match candidates with
-	| [cf] ->
-		if overload_kind = OverloadProper then maybe_check_access cf;
-		begin try
-			attempt_call cf
-		with Error _ when ctx.com.display.dms_error_policy = EPIgnore ->
-			fail_fun();
-		end
-	| _ ->
-		let candidates,failures = attempt_calls candidates in
-		let fail () =
-			let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in
-			let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in
-			begin match failures with
-			| [_,msg,p] ->
-				error msg p
-			| _ ->
-				display_error ctx "Could not find a suitable overload, reasons follow" p;
-				List.iter (fun (cf,msg,p2) ->
-					display_error ctx ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p;
-					display_error ctx msg p2;
-				) failures;
-				error "End of overload failure reasons" p
-			end
-		in
-		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with
-			| [] -> fail()
-			| [fcc] ->
-				maybe_check_access fcc.fc_field;
-				fcc
-			| fcc :: l ->
-				display_error ctx "Ambiguous overload, candidates follow" p;
-				let st = s_type (print_context()) in
-				List.iter (fun fcc ->
-					display_error ctx (Printf.sprintf "... %s" (st fcc.fc_type)) fcc.fc_field.cf_name_pos;
-				) (fcc :: l);
-				fcc
-		end else begin match List.rev candidates with
-			| [] -> fail()
-			| fcc :: _ -> fcc
-		end
-
-let type_generic_function ctx fa el_typed el with_type p =
-	let c,stat = match fa.fa_host with
-		| FHInstance(c,tl) -> c,false
-		| FHStatic c -> c,true
-		| FHAbstract(a,tl,c) -> c,true
-		| _ -> die "" __LOC__
-	in
-	let cf = fa.fa_field in
-	if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p;
-	let fcc = unify_field_call ctx fa el_typed el p false in
-	begin match with_type with
-		| WithType.WithType(t,_) -> unify ctx fcc.fc_ret t p
-		| _ -> ()
-	end;
-	let monos = fcc.fc_monos in
-	List.iter (fun t -> match follow t with
-		| TMono m -> safe_mono_close ctx m p
-		| _ -> ()
-	) monos;
-	let el = List.map fst fcc.fc_args in
-	(try
-		let gctx = Generic.make_generic ctx cf.cf_params monos p in
-		let name = cf.cf_name ^ "_" ^ gctx.Generic.name in
-		let unify_existing_field tcf pcf = try
-			unify_raise ctx tcf fcc.fc_type p
-		with Error(Unify _,_) as err ->
-			display_error ctx ("Cannot create field " ^ name ^ " due to type mismatch") p;
-			display_error ctx (compl_msg "Conflicting field was defined here") pcf;
-			raise err
-		in
-		let fa = try
-			let cf2 = if stat then
-				let cf2 = PMap.find name c.cl_statics in
-				unify_existing_field cf2.cf_type cf2.cf_pos;
-				cf2
-			else
-				let cf2 = PMap.find name c.cl_fields in
-				unify_existing_field cf2.cf_type cf2.cf_pos;
-				cf2
-			in
-			{fa with fa_field = cf2}
-			(*
-				java.Lib.array() relies on the ability to shadow @:generic function for certain types
-				see https://github.com/HaxeFoundation/haxe/issues/8393#issuecomment-508685760
-			*)
-			(* if cf.cf_name_pos = cf2.cf_name_pos then
-				cf2
-			else
-				error ("Cannot specialize @:generic because the generated function name is already used: " ^ name) p *)
-		with Not_found ->
-			let finalize_field c cf2 =
-				ignore(follow cf.cf_type);
-				let rec check e = match e.eexpr with
-					| TNew({cl_kind = KTypeParameter _} as c,_,_) when not (TypeloadCheck.is_generic_parameter ctx c) ->
-						display_error ctx "Only generic type parameters can be constructed" e.epos;
-						display_error ctx "While specializing this call" p;
-					| _ ->
-						Type.iter check e
-				in
-				cf2.cf_expr <- (match cf.cf_expr with
-					| None ->
-						display_error ctx "Recursive @:generic function" p; None;
-					| Some e ->
-						let e = Generic.generic_substitute_expr gctx e in
-						check e;
-						Some e
-				);
-				cf2.cf_kind <- cf.cf_kind;
-				if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic;
-				cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: cf.cf_meta
-			in
-			let mk_cf2 name =
-				mk_field ~static:stat name fcc.fc_type cf.cf_pos cf.cf_name_pos
-			in
-			if stat then begin
-				if Meta.has Meta.GenericClassPerMethod c.cl_meta then begin
-					let c = Generic.static_method_container gctx c cf p in
-					let cf2 = try
-						let cf2 = PMap.find cf.cf_name c.cl_statics in
-						unify_existing_field cf2.cf_type cf2.cf_pos;
-						cf2
-					with Not_found ->
-						let cf2 = mk_cf2 cf.cf_name in
-						c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
-						c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
-						finalize_field c cf2;
-						cf2
-					in
-					{fa with fa_host = FHStatic c;fa_field = cf2;fa_on = Builder.make_static_this c p}
-				end else begin
-					let cf2 = mk_cf2 name in
-					c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
-					c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
-					finalize_field c cf2;
-					{fa with fa_field = cf2}
-				end
-			end else begin
-				let cf2 = mk_cf2 name in
-				if has_class_field_flag cf CfOverride then add_class_field_flag cf2 CfOverride;
-				c.cl_fields <- PMap.add cf2.cf_name cf2 c.cl_fields;
-				c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields;
-				finalize_field c cf2;
-				{fa with fa_field = cf2}
-			end
-		in
-		let e = FieldAccess.get_field_expr fa FCall in
-		make_call ctx e el fcc.fc_ret p
-	with Generic.Generic_Exception (msg,p) ->
-		error msg p)
-
 let abstract_using_param_type sea = match follow sea.se_this.etype with
 	| TAbstract(a,tl) when has_class_field_flag sea.se_access.fa_field CfImpl -> apply_params a.a_params tl a.a_this
 	| _ -> sea.se_this.etype
 
-class call_dispatcher
-	(ctx : typer)
-	(mode : access_mode)
-	(with_type : WithType.t)
-	(p : pos)
-=
-	let is_set = match mode with MSet _ -> true | _ -> false in
-	let check_assign () = if is_set then invalid_assign p in
-
-object(self)
-
-	method private make_field_call (fa : field_access) (el_typed : texpr list) (el : expr list) =
-		let fcc = unify_field_call ctx fa el_typed el p fa.fa_inline in
-		if has_class_field_flag fcc.fc_field CfAbstract then begin match fa.fa_on.eexpr with
-			| TConst TSuper -> display_error ctx (Printf.sprintf "abstract method %s cannot be accessed directly" fcc.fc_field.cf_name) p;
-			| _ -> ()
-		end;
-		fcc.fc_data()
-
-	method private macro_call (ethis : texpr) (cf : tclass_field) (el : expr list) =
-		if ctx.macro_depth > 300 then error "Stack overflow" p;
-		ctx.macro_depth <- ctx.macro_depth + 1;
-		ctx.with_type_stack <- with_type :: ctx.with_type_stack;
-		let ethis_f = ref (fun () -> ()) in
-		let f = (match ethis.eexpr with
-		| TTypeExpr (TClassDecl c) ->
-			DeprecationCheck.check_cf ctx.com cf p;
-			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
-			| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
-			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = (!type_block_ref) ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
-			| Some e -> (fun() -> type_expr ~mode ctx e with_type))
-		| _ ->
-			(* member-macro call : since we will make a static call, let's find the actual class and not its subclass *)
-			(match follow ethis.etype with
-			| TInst (c,_) ->
-				let rec loop c =
-					if PMap.mem cf.cf_name c.cl_fields then
-						let eparam,f = push_this ctx ethis in
-						ethis_f := f;
-						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
-							| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
-							| Some e -> (fun() -> type_expr ~mode ctx e WithType.value)
-						in
-						e
-					else
-						match c.cl_super with
-						| None -> die "" __LOC__
-						| Some (csup,_) -> loop csup
-				in
-				loop c
-			| _ -> die "" __LOC__))
-		in
-		ctx.macro_depth <- ctx.macro_depth - 1;
-		ctx.with_type_stack <- List.tl ctx.with_type_stack;
-		let old = ctx.on_error in
-		ctx.on_error <- (fun ctx msg ep ->
-			(* display additional info in the case the error is not part of our original call *)
-			if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin
-				TypeloadFields.locate_macro_error := false;
-				old ctx msg ep;
-				TypeloadFields.locate_macro_error := true;
-				ctx.com.error (compl_msg "Called from macro here") p;
-			end else
-				old ctx msg ep;
-		);
-		let e = try
-			f()
-		with exc ->
-			ctx.on_error <- old;
-			!ethis_f();
-			raise exc
-		in
-		let e = Diagnostics.secure_generated_code ctx e in
-		ctx.on_error <- old;
-		!ethis_f();
-		e
-
-	(* Calls `e` with arguments `el`. Does not inspect the callee expression, so it should only be
-	   used with actual expression calls and not with something like field calls. *)
-	method expr_call (e : texpr) (el : expr list) =
-		check_assign();
-		let rec loop t = match follow t with
-		| TFun (args,r) ->
-			let el, tfunc = unify_call_args ctx el args r p false false in
-			let r = match tfunc with TFun(_,r) -> r | _ -> die "" __LOC__ in
-			mk (TCall (e,el)) r p
-		| 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 WithType.value) el in
-			unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos;
-			mk (TCall (e,el)) t p
-		| t ->
-			let el = List.map (fun e -> type_expr ctx e WithType.value) el in
-			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
-			in
-			mk (TCall (e,el)) t p
-		in
-		loop e.etype
-
-	(* Calls the resolve method represented by `sea` with an additional string-expression argument `name`. *)
-	method resolve_call (sea : static_extension_access) (name : string) =
-		let eparam = sea.se_this in
-		let e_name = Texpr.Builder.make_string ctx.t name null_pos in
-		self#field_call sea.se_access [eparam;e_name] []
-
-	(* Resolves the accessor function for `fa` and calls it with the provided arguments.
-	   If no accessor function is found (AccessorAnon case), a generic field access is generated instead.
-	*)
-	method accessor_call fa el_typed el =
-		match FieldAccess.resolve_accessor fa mode with
-			| AccessorFound fa_accessor ->
-				let dispatcher = new call_dispatcher ctx (MCall el) with_type p in
-				let e = dispatcher#field_call fa_accessor el_typed el in
-				let t = FieldAccess.get_map_function fa fa.fa_field.cf_type in
-				if not (type_iseq_strict t e.etype) then mk (TCast(e,None)) t e.epos else e
-			| AccessorAnon ->
-				let e = fa.fa_on in
-				let t = FieldAccess.get_map_function fa fa.fa_field.cf_type in
-				let el = List.map (fun e -> type_expr ctx e WithType.value) el in
-				let el_typed = el_typed @ el in
-				let tf = tfun (List.map (fun e -> e.etype) el_typed) t in
-				let name = Printf.sprintf "%s_%s" (if is_set then "set" else "get") fa.fa_field.cf_name in
-				make_call ctx (mk (TField (e,quick_field_dynamic e.etype name)) tf p) el_typed t p
-			| _ ->
-				error "Could not resolve accessor" p
-
-	(* Calls the field represented by `fa` with the typed arguments `el_typed` and the syntactic arguments `el`.
-
-	   This function inspects the nature of the field being called and dispatches the call accordingly:
-
-	   * If the field is `@:generic`, call `type_generic_function`.
-	   * If the field is a non-macro method, call it via `make_field_call`.
-	   * If the field is a property, resolve the accessor (depending on `mode`) and recurse onto it.
-	   * Otherwise, call the field as a normal expression via `expr_call`.
-	*)
-	method field_call (fa : field_access) (el_typed : texpr list) (el : expr list) =
-		match fa.fa_field.cf_kind with
-		| Method (MethNormal | MethInline | MethDynamic) ->
-			check_assign();
-			 if has_class_field_flag fa.fa_field CfGeneric then begin
-				type_generic_function ctx fa el_typed el with_type p
-			end else
-				self#make_field_call fa el_typed el
-		| Method MethMacro ->
-			begin match el_typed with
-			| [] ->
-				self#macro_call fa.fa_on fa.fa_field el
-			| el_typed ->
-				let cur = ctx.this_stack in
-				let el' = List.map (fun e -> fst (push_this ctx e)) el_typed in
-				let e = self#macro_call fa.fa_on fa.fa_field (el' @ el) in
-				ctx.this_stack <- cur;
-				e
-			end;
-		| Var v ->
-			begin match (if is_set then v.v_write else v.v_read) with
-			| AccCall ->
-				self#accessor_call fa el_typed el
-			| _ ->
-				self#expr_call (FieldAccess.get_field_expr fa FCall) el
-			end
-end
-
 let rec acc_get ctx g p =
 	let inline_read fa =
 		let cf = fa.fa_field in

+ 147 - 0
src/typing/fieldAccess.ml

@@ -0,0 +1,147 @@
+open Typecore
+open Type
+open Error
+
+type field_host =
+	(* Get the plain expression with applied field type parameters. *)
+	| FGet
+	(* Does not apply field type parameters. *)
+	| FCall
+	(* Actual reading, for FClosure and such. *)
+	| FRead
+	(* Used as lhs, no semantic difference to FGet. *)
+	| FWrite
+
+type accessor_resolution =
+	(* Accessor was found. *)
+	| AccessorFound of field_access
+	(* Accessor was not found, but access was made on anonymous structure. *)
+	| AccessorAnon
+	(* Accessor was not found. *)
+	| AccessorNotFound
+	(* Accessor resolution was attempted on a non-property. *)
+	| AccessorInvalid
+
+let create e cf fh inline p = {
+	fa_on     = e;
+	fa_field  = cf;
+	fa_host   = fh;
+	fa_inline = inline;
+	fa_pos    = p;
+}
+
+(* Creates the `tfield_access` corresponding to this field access, using the provided field. *)
+let apply_fa cf = function
+	| FHStatic c -> FStatic(c,cf)
+	| FHInstance(c,tl) -> FInstance(c,tl,cf)
+	| FHAbstract(a,tl,c) -> FStatic(c,cf)
+	| FHAnon -> FAnon cf
+
+(* Returns the mapping function to apply type parameters. *)
+let get_map_function fa = match fa.fa_host with
+	| FHStatic _ | FHAnon -> (fun t -> t)
+	| FHInstance(c,tl) -> TClass.get_map_function c tl
+	| FHAbstract(a,tl,_) -> apply_params a.a_params tl
+
+(* Converts the field access to a `TField` node, using the provided `mode`. *)
+let get_field_expr fa mode =
+	let cf = fa.fa_field in
+	let t = match mode with
+		| FCall -> cf.cf_type
+		| FGet | FRead | FWrite -> Type.field_type cf
+	in
+	let fa',t = match fa.fa_host with
+		| FHStatic c ->
+			FStatic(c,cf),t
+		| FHInstance(c,tl) ->
+			let fa = match cf.cf_kind with
+			| Method _ when mode = FRead ->
+				FClosure(Some(c,tl),cf)
+			| _ ->
+				FInstance(c,tl,cf)
+			in
+			let t = TClass.get_map_function c tl t in
+			fa,t
+		| FHAbstract(a,tl,c) ->
+			FStatic(c,cf),apply_params a.a_params tl t
+		| FHAnon ->
+			let fa = match cf.cf_kind with
+			| Method _ when mode = FRead ->
+				FClosure(None,cf)
+			| _ ->
+				FAnon cf
+			in
+			fa,t
+	in
+	mk (TField(fa.fa_on,fa')) t fa.fa_pos
+
+(* Resolves the accessor on the field access, using the provided `mode`. *)
+let resolve_accessor fa mode = match fa.fa_field.cf_kind with
+	| Var v ->
+		begin match (match mode with MSet _ -> v.v_write | _ -> v.v_read) with
+			| AccCall ->
+				let name = (match mode with MSet _ -> "set_" | _ -> "get_") ^ fa.fa_field.cf_name in
+				let forward cf_acc new_host =
+					create fa.fa_on cf_acc new_host fa.fa_inline fa.fa_pos
+				in
+				begin match fa.fa_host with
+				| FHStatic c ->
+					begin try
+						AccessorFound (forward (PMap.find name c.cl_statics) fa.fa_host)
+					with Not_found ->
+						(* TODO: Check if this is correct, there's a case in hxcpp's VirtualArray *)
+						AccessorAnon
+					end
+				| FHInstance(c,tl) ->
+					begin try
+						(* Accessors can be overridden, so we have to check the actual type. *)
+						let c,tl = match follow fa.fa_on.etype with
+							| TInst(c,tl) -> c,tl
+							| _ -> c,tl
+						in
+						let (c2,_,cf_acc) = raw_class_field (fun f -> f.cf_type) c tl name in
+						let new_host = match c2 with
+							| None -> FHAnon
+							| Some(c,tl) -> FHInstance(c,tl)
+						in
+						AccessorFound (forward cf_acc new_host)
+					with Not_found ->
+						AccessorAnon
+					end
+				| FHAbstract(a,tl,c) ->
+					begin try
+						AccessorFound (forward (PMap.find name c.cl_statics) fa.fa_host)
+					with Not_found ->
+						AccessorAnon
+					end
+				| FHAnon ->
+					AccessorAnon
+				end
+			| _ ->
+				AccessorInvalid
+		end
+	| _ ->
+		AccessorInvalid
+
+let get_constructor_access c params p =
+	match c.cl_kind with
+	| KAbstractImpl a ->
+		let cf = (try PMap.find "_new" c.cl_statics with Not_found -> raise_error (No_constructor (TAbstractDecl a)) p) in
+		create (Builder.make_static_this c p) cf (FHAbstract(a,params,c)) false p
+	| _ ->
+		let cf = (try Type.get_constructor c with Not_found -> raise_error (No_constructor (TClassDecl c)) p) in
+		create (Builder.make_static_this c p) cf (FHInstance(c,params)) false p
+
+let make_static_extension_access c cf e_this inline p =
+	let e_static = Texpr.Builder.make_static_this c p in
+	{
+		se_this = e_this;
+		se_access = create e_static cf (FHStatic c) inline p
+	}
+
+let make_abstract_static_extension_access a tl c cf e_this inline p =
+	let e_static = Texpr.Builder.make_static_this c p in
+	{
+		se_this = e_this;
+		se_access = create e_static cf (FHAbstract(a,tl,c)) inline p
+	}

+ 1 - 4
src/typing/fields.ml

@@ -5,6 +5,7 @@ open Type
 open TyperBase
 open Error
 open Typecore
+open FieldAccess
 
 module TypeFieldConfig = struct
 	type t = {
@@ -104,10 +105,6 @@ let check_no_closure_meta ctx cf fa mode p =
 	| _ ->
 		()
 
-let check_field_access ctx c f stat p =
-	if not ctx.untyped && not (can_access ctx c f stat) then
-		display_error ctx ("Cannot access private field " ^ f.cf_name) p
-
 let field_access ctx mode f famode e p =
 	let is_set = match mode with MSet _ -> true | _ -> false in
 	check_no_closure_meta ctx f famode mode p;

+ 2 - 2
src/typing/macroContext.ml

@@ -685,7 +685,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 = fst (Calls.unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false) in
+		let elt = fst (CallUnification.unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false) in
 		List.map2 (fun (_,mct) e ->
 			let e, et = (match e.eexpr with
 				(* get back our index and real expression *)
@@ -757,7 +757,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 false path meth p in
 	mctx.curclass <- null_class;
-	let el, _ = Calls.unify_call_args mctx args margs t_dynamic p false false in
+	let el, _ = CallUnification.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 =

+ 2 - 0
src/typing/operators.ml

@@ -4,8 +4,10 @@ open Type
 open TyperBase
 open Typecore
 open Error
+open CallUnification
 open Calls
 open Fields
+open FieldAccess
 
 class value_reference (ctx : typer) =
 

+ 14 - 3
src/typing/typeloadFields.ml

@@ -83,8 +83,6 @@ type field_init_ctx = {
 	mutable expr_presence_matters : bool;
 }
 
-let locate_macro_error = ref true
-
 let dump_class_context cctx =
 	Printer.s_record_fields "" [
 		"tclass",Printer.s_tclass "\t" cctx.tclass;
@@ -668,6 +666,19 @@ let transform_field (ctx,cctx) c f fields p =
 		| _ -> ());
 	f
 
+let type_var_field ctx t e stat do_display p =
+	if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember;
+	let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
+	let e = type_expr ctx e (WithType.with_type t) in
+	let e = AbstractCast.cast_or_unify ctx t e p in
+	match t with
+	| TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t }
+	| _ -> e
+
+let type_var_field ctx t e stat do_display p =
+	let save = TypeloadFunction.save_field_state ctx in
+	Std.finally save (type_var_field ctx t e stat do_display) p
+
 let build_fields (ctx,cctx) c fields =
 	let fields = ref fields in
 	let get_fields() = !fields in
@@ -806,7 +817,7 @@ let bind_var (ctx,cctx,fctx) cf e =
 				r := lazy_processing (fun() -> t);
 				cctx.context_init#run;
 				if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
-				let e = TypeloadFunction.type_var_field ctx t e fctx.is_static fctx.is_display_field p in
+				let e = type_var_field ctx t e fctx.is_static fctx.is_display_field p in
 				let maybe_run_analyzer e = match e.eexpr with
 					| TConst _ | TLocal _ | TFunction _ -> e
 					| _ -> !analyzer_run_on_expr_ref ctx.com e

+ 0 - 13
src/typing/typeloadFunction.ml

@@ -57,19 +57,6 @@ let save_field_state ctx =
 		ctx.in_function <- old_in_function;
 	)
 
-let type_var_field ctx t e stat do_display p =
-	if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember;
-	let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
-	let e = type_expr ctx e (WithType.with_type t) in
-	let e = AbstractCast.cast_or_unify ctx t e p in
-	match t with
-	| TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t }
-	| _ -> e
-
-let type_var_field ctx t e stat do_display p =
-	let save = save_field_state ctx in
-	Std.finally save (type_var_field ctx t e stat do_display) p
-
 let type_function_params ctx fd fname p =
 	let params = ref [] in
 	params := Typeload.type_type_params ctx ([],fname) (fun() -> !params) p fd.f_params;

+ 1 - 0
src/typing/typer.ml

@@ -29,6 +29,7 @@ open Error
 open Globals
 open TyperBase
 open Fields
+open CallUnification
 open Calls
 open Operators
 

+ 1 - 216
src/typing/typerBase.ml

@@ -4,33 +4,6 @@ open Type
 open Typecore
 open Error
 
-type field_host =
-	| FHStatic of tclass
-	| FHInstance of tclass * tparams
-	| FHAbstract of tabstract * tparams * tclass
-	| FHAnon
-
-type field_access = {
-	(* The expression on which the field is accessed. For abstracts, this is a type expression
-	   to the implementation class. *)
-	fa_on     : texpr;
-	(* The field being accessed. *)
-	fa_field  : tclass_field;
-	(* The host of the field. *)
-	fa_host   : field_host;
-	(* Whether or not to inline the access. This can be set for non-inline fields via `inline call()` syntax. *)
-	fa_inline : bool;
-	(* The position of the field access expression in syntax. *)
-	fa_pos    : pos;
-}
-
-type static_extension_access = {
-	(* The `this` expression which should be passed as first argument. *)
-	se_this   : texpr;
-	(* The field access information. *)
-	se_access : field_access;
-}
-
 type access_kind =
 	(* Access is not possible or allowed. *)
 	| AKNo of string
@@ -58,48 +31,6 @@ type object_decl_kind =
 let type_call_target_ref : (typer -> expr -> expr list -> WithType.t -> bool -> pos -> access_kind) ref = ref (fun _ _ _ _ _ -> die "" __LOC__)
 let type_access_ref : (typer -> expr_def -> pos -> access_mode -> WithType.t -> access_kind) ref = ref (fun _ _ _ _ _ -> assert false)
 
-let relative_path ctx file =
-	let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in
-	let fpath = slashes (Path.get_full_path file) in
-	let fpath_lower = String.lowercase fpath in
-	let flen = String.length fpath_lower in
-	let rec loop = function
-		| [] -> file
-		| path :: l ->
-			let spath = String.lowercase (slashes path) in
-			let slen = String.length spath in
-			if slen > 0 && slen < flen && String.sub fpath_lower 0 slen = spath then String.sub fpath slen (flen - slen) else loop l
-	in
-	loop ctx.com.Common.class_path
-
-let mk_infos ctx p params =
-	let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Path.get_full_path p.pfile else relative_path ctx p.pfile in
-	(EObjectDecl (
-		(("fileName",null_pos,NoQuotes) , (EConst (String(file,SDoubleQuotes)) , p)) ::
-		(("lineNumber",null_pos,NoQuotes) , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) ::
-		(("className",null_pos,NoQuotes) , (EConst (String (s_type_path ctx.curclass.cl_path,SDoubleQuotes)),p)) ::
-		if ctx.curfield.cf_name = "" then
-			params
-		else
-			(("methodName",null_pos,NoQuotes), (EConst (String (ctx.curfield.cf_name,SDoubleQuotes)),p)) :: params
-	) ,p)
-
-let rec is_pos_infos = function
-	| TMono r ->
-		(match r.tm_type with
-		| Some t -> is_pos_infos t
-		| _ -> false)
-	| TLazy f ->
-		is_pos_infos (lazy_type f)
-	| TType ({ t_path = ["haxe"] , "PosInfos" },[]) ->
-		true
-	| TType (t,tl) ->
-		is_pos_infos (apply_params t.t_params tl t.t_type)
-	| TAbstract({a_path=[],"Null"},[t]) ->
-		is_pos_infos t
-	| _ ->
-		false
-
 let is_lower_ident s p =
 	try Ast.is_lower_ident s
 	with Invalid_argument msg -> error msg p
@@ -272,150 +203,4 @@ let get_abstract_froms a pl =
 				acc)
 		| _ ->
 			acc
-	) l a.a_from_field
-
-module FieldAccess = struct
-	type field_host =
-		(* Get the plain expression with applied field type parameters. *)
-		| FGet
-		(* Does not apply field type parameters. *)
-		| FCall
-		(* Actual reading, for FClosure and such. *)
-		| FRead
-		(* Used as lhs, no semantic difference to FGet. *)
-		| FWrite
-
-	type accessor_resolution =
-		(* Accessor was found. *)
-		| AccessorFound of field_access
-		(* Accessor was not found, but access was made on anonymous structure. *)
-		| AccessorAnon
-		(* Accessor was not found. *)
-		| AccessorNotFound
-		(* Accessor resolution was attempted on a non-property. *)
-		| AccessorInvalid
-
-	let create e cf fh inline p = {
-		fa_on     = e;
-		fa_field  = cf;
-		fa_host   = fh;
-		fa_inline = inline;
-		fa_pos    = p;
-	}
-
-	(* Creates the `tfield_access` corresponding to this field access, using the provided field. *)
-	let apply_fa cf = function
-		| FHStatic c -> FStatic(c,cf)
-		| FHInstance(c,tl) -> FInstance(c,tl,cf)
-		| FHAbstract(a,tl,c) -> FStatic(c,cf)
-		| FHAnon -> FAnon cf
-
-	(* Returns the mapping function to apply type parameters. *)
-	let get_map_function fa = match fa.fa_host with
-		| FHStatic _ | FHAnon -> (fun t -> t)
-		| FHInstance(c,tl) -> TClass.get_map_function c tl
-		| FHAbstract(a,tl,_) -> apply_params a.a_params tl
-
-	(* Converts the field access to a `TField` node, using the provided `mode`. *)
-	let get_field_expr fa mode =
-		let cf = fa.fa_field in
-		let t = match mode with
-			| FCall -> cf.cf_type
-			| FGet | FRead | FWrite -> Type.field_type cf
-		in
-		let fa',t = match fa.fa_host with
-			| FHStatic c ->
-				FStatic(c,cf),t
-			| FHInstance(c,tl) ->
-				let fa = match cf.cf_kind with
-				| Method _ when mode = FRead ->
-					FClosure(Some(c,tl),cf)
-				| _ ->
-					FInstance(c,tl,cf)
-				in
-				let t = TClass.get_map_function c tl t in
-				fa,t
-			| FHAbstract(a,tl,c) ->
-				FStatic(c,cf),apply_params a.a_params tl t
-			| FHAnon ->
-				let fa = match cf.cf_kind with
-				| Method _ when mode = FRead ->
-					FClosure(None,cf)
-				| _ ->
-					FAnon cf
-				in
-				fa,t
-		in
-		mk (TField(fa.fa_on,fa')) t fa.fa_pos
-
-	(* Resolves the accessor on the field access, using the provided `mode`. *)
-	let resolve_accessor fa mode = match fa.fa_field.cf_kind with
-		| Var v ->
-			begin match (match mode with MSet _ -> v.v_write | _ -> v.v_read) with
-				| AccCall ->
-					let name = (match mode with MSet _ -> "set_" | _ -> "get_") ^ fa.fa_field.cf_name in
-					let forward cf_acc new_host =
-						create fa.fa_on cf_acc new_host fa.fa_inline fa.fa_pos
-					in
-					begin match fa.fa_host with
-					| FHStatic c ->
-						begin try
-							AccessorFound (forward (PMap.find name c.cl_statics) fa.fa_host)
-						with Not_found ->
-							(* TODO: Check if this is correct, there's a case in hxcpp's VirtualArray *)
-							AccessorAnon
-						end
-					| FHInstance(c,tl) ->
-						begin try
-							(* Accessors can be overridden, so we have to check the actual type. *)
-							let c,tl = match follow fa.fa_on.etype with
-								| TInst(c,tl) -> c,tl
-								| _ -> c,tl
-							in
-							let (c2,_,cf_acc) = raw_class_field (fun f -> f.cf_type) c tl name in
-							let new_host = match c2 with
-								| None -> FHAnon
-								| Some(c,tl) -> FHInstance(c,tl)
-							in
-							AccessorFound (forward cf_acc new_host)
-						with Not_found ->
-							AccessorAnon
-						end
-					| FHAbstract(a,tl,c) ->
-						begin try
-							AccessorFound (forward (PMap.find name c.cl_statics) fa.fa_host)
-						with Not_found ->
-							AccessorAnon
-						end
-					| FHAnon ->
-						AccessorAnon
-					end
-				| _ ->
-					AccessorInvalid
-			end
-		| _ ->
-			AccessorInvalid
-
-	let get_constructor_access c params p =
-		match c.cl_kind with
-		| KAbstractImpl a ->
-			let cf = (try PMap.find "_new" c.cl_statics with Not_found -> raise_error (No_constructor (TAbstractDecl a)) p) in
-			create (Builder.make_static_this c p) cf (FHAbstract(a,params,c)) false p
-		| _ ->
-			let cf = (try Type.get_constructor c with Not_found -> raise_error (No_constructor (TClassDecl c)) p) in
-			create (Builder.make_static_this c p) cf (FHInstance(c,params)) false p
-end
-
-let make_static_extension_access c cf e_this inline p =
-	let e_static = Texpr.Builder.make_static_this c p in
-	{
-		se_this = e_this;
-		se_access = FieldAccess.create e_static cf (FHStatic c) inline p
-	}
-
-let make_abstract_static_extension_access a tl c cf e_this inline p =
-	let e_static = Texpr.Builder.make_static_this c p in
-	{
-		se_this = e_this;
-		se_access = FieldAccess.create e_static cf (FHAbstract(a,tl,c)) inline p
-	}
+	) l a.a_from_field

+ 1 - 0
src/typing/typerDisplay.ml

@@ -15,6 +15,7 @@ open Type
 open Typecore
 open TyperBase
 open Fields
+open CallUnification
 open Calls
 open Error
 open FieldAccess