فهرست منبع

Merge branch 'development' into out_of_curiosity_(don't_freak_out)

# Conflicts:
#	src/context/common.ml
#	src/typing/generic.ml
#	src/typing/typeload.ml
Simon Krajewski 1 سال پیش
والد
کامیت
95f56cf0b7
92فایلهای تغییر یافته به همراه1502 افزوده شده و 826 حذف شده
  1. 27 0
      extra/CHANGES.txt
  2. 1 1
      extra/haxelib_src
  3. 7 0
      src-json/define.json
  4. 7 9
      src/compiler/compiler.ml
  5. 7 1
      src/context/common.ml
  6. 2 2
      src/context/display/displayTexpr.ml
  7. 1 1
      src/context/display/syntaxExplorer.ml
  8. 68 30
      src/context/typecore.ml
  9. 5 5
      src/core/inheritDoc.ml
  10. 7 4
      src/core/tFunctions.ml
  11. 2 2
      src/core/tType.ml
  12. 13 0
      src/core/texpr.ml
  13. 6 6
      src/filters/exceptions.ml
  14. 7 7
      src/filters/filters.ml
  15. 1 1
      src/generators/gencpp.ml
  16. 7 5
      src/generators/hl2c.ml
  17. 1 1
      src/optimization/inline.ml
  18. 23 13
      src/typing/callUnification.ml
  19. 1 16
      src/typing/calls.ml
  20. 4 1
      src/typing/fields.ml
  21. 2 2
      src/typing/finalization.ml
  22. 176 133
      src/typing/generic.ml
  23. 26 19
      src/typing/instanceBuilder.ml
  24. 8 10
      src/typing/macroContext.ml
  25. 0 101
      src/typing/magicTypes.ml
  26. 1 1
      src/typing/matcher/exprToPattern.ml
  27. 149 140
      src/typing/operators.ml
  28. 148 132
      src/typing/typeload.ml
  29. 1 2
      src/typing/typeloadCheck.ml
  30. 11 28
      src/typing/typeloadFields.ml
  31. 2 3
      src/typing/typeloadFunction.ml
  32. 4 6
      src/typing/typeloadModule.ml
  33. 0 1
      src/typing/typeloadParse.ml
  34. 59 55
      src/typing/typer.ml
  35. 20 2
      src/typing/typerBase.ml
  36. 1 1
      src/typing/typerDisplay.ml
  37. 3 0
      std/hl/_std/haxe/NativeStackTrace.hx
  38. 0 1
      tests/misc/eventLoop/build-hl.hxml
  39. 37 0
      tests/misc/hl/reservedKeywords/Macro.macro.hx
  40. 4 0
      tests/misc/hl/reservedKeywords/Main.hx
  41. 1 0
      tests/misc/hl/reservedKeywords/compile.hxml
  42. 6 0
      tests/misc/projects/Issue11152/Generic.hx
  43. 3 0
      tests/misc/projects/Issue11152/Main.hx
  44. 5 0
      tests/misc/projects/Issue11152/NotMain.hx
  45. 2 0
      tests/misc/projects/Issue11152/compile.hxml
  46. 8 0
      tests/misc/projects/Issue11342/Main.hx
  47. 1 0
      tests/misc/projects/Issue11342/compile-fail.hxml
  48. 1 0
      tests/misc/projects/Issue11342/compile-fail.hxml.stderr
  49. 7 0
      tests/misc/projects/Issue11372/Macro.hx
  50. 3 0
      tests/misc/projects/Issue11372/MainBad.hx
  51. 3 0
      tests/misc/projects/Issue11372/MainGood.hx
  52. 11 0
      tests/misc/projects/Issue11372/MyEnumAbstract.hx
  53. 16 0
      tests/misc/projects/Issue11372/ValuePrinter.hx
  54. 2 0
      tests/misc/projects/Issue11372/compile-bad-fail.hxml
  55. 2 0
      tests/misc/projects/Issue11372/compile-bad-fail.hxml.stderr
  56. 2 0
      tests/misc/projects/Issue11372/compile-good.hxml
  57. 10 0
      tests/misc/projects/Issue3864/Base.hx
  58. 28 0
      tests/misc/projects/Issue3864/Macro.hx
  59. 14 0
      tests/misc/projects/Issue3864/Main.hx
  60. 2 0
      tests/misc/projects/Issue3864/compile.hxml
  61. 3 0
      tests/misc/projects/Issue3864/compile.hxml.stdout
  62. 1 1
      tests/misc/projects/Issue7227/compile-fail.hxml.stderr
  63. 9 0
      tests/runci/System.hx
  64. 46 8
      tests/runci/targets/Hl.hx
  65. 13 0
      tests/server/src/cases/issues/Issue9358.hx
  66. 16 0
      tests/server/test/templates/issues/Issue9358/Main.hx
  67. 12 0
      tests/server/test/templates/issues/Issue9358/StateHandler.hx
  68. 18 0
      tests/sys/compile-hlc.hxml
  69. 1 0
      tests/sys/gen_test_res.py
  70. 5 1
      tests/sys/src/ExitCode.hx
  71. 5 1
      tests/sys/src/TestArguments.hx
  72. 8 0
      tests/sys/src/TestCommandBase.hx
  73. 5 1
      tests/sys/src/TestUnicode.hx
  74. 13 1
      tests/sys/src/UtilityProcess.hx
  75. 1 2
      tests/unit/compile-hl.hxml
  76. 0 5
      tests/unit/compile-hlc.hxml
  77. 102 59
      tests/unit/src/unit/TestDCE.hx
  78. 4 0
      tests/unit/src/unit/TestExceptions.hx
  79. 2 1
      tests/unit/src/unit/issues/Issue10109.hx
  80. 24 0
      tests/unit/src/unit/issues/Issue10528.hx
  81. 43 0
      tests/unit/src/unit/issues/Issue11010.hx
  82. 24 0
      tests/unit/src/unit/issues/Issue11379.hx
  83. 9 0
      tests/unit/src/unit/issues/Issue11385.hx
  84. 5 3
      tests/unit/src/unit/issues/Issue2016.hx
  85. 32 0
      tests/unit/src/unit/issues/Issue5482.hx
  86. 17 0
      tests/unit/src/unit/issues/Issue5536.hx
  87. 43 0
      tests/unit/src/unit/issues/Issue6761.hx
  88. 19 0
      tests/unit/src/unit/issues/Issue7574.hx
  89. 21 0
      tests/unit/src/unit/issues/Issue9395.hx
  90. 1 1
      tests/unit/src/unit/issues/Issue9678.hx
  91. 7 0
      tests/unit/src/unit/issues/misc/Issue11385LibraryData.hx
  92. 17 0
      tests/unit/src/unit/issues/misc/Issue5536Macro.hx

+ 27 - 0
extra/CHANGES.txt

@@ -1,3 +1,30 @@
+2023-09-17 4.3.3
+
+	General improvements:
+
+	all : improve extra field error range (#11335)
+	all : better error messages for --connect
+	hl : improve error message when hl_version is missing (#11086)
+	hl/c : compiler now adds hlc define when targeting hl/c (#11382)
+	macro : update macro API restriction warnings when using -D haxe-next (#11377)
+
+	Bugfixes:
+
+	all : handle non existing files for positions in pretty errors (#11364)
+	all : metadata support for local static vars
+	all : catch trailing invalid syntax in string interpolation (#10287)
+	eval : fix Array.resize retaining values (#11317)
+	eval/hl : fix catching haxe.ValueException (#11321)
+	hl : make genhl respect Meta.NoExpr (#11257)
+	hl : don't add bindings for non existing methods
+	hl/c : add missing I64 mod support
+	hl/c : rework reserved keywords (#11293, #11378)
+	hl/c : fix Int64 unsigned right shift overflow (#11382)
+	java/cs: fix stack overflow from closures constraints (#11350)
+	js : DOMElement insertAdjacentElement should not be pure (#11333)
+	macro : catch trailing invalid syntax in Context.parseInlineString (#11368)
+	macro : fix TDAbstract without flags in haxe.macro.Printer
+
 2023-09-01 4.3.2
 
 	General improvements:

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit f17fffa97554b1bdba37750e3418051f017a5bc2
+Subproject commit 70ff6b69a5b35049d767056555c0bf7a54e8ad4e

+ 7 - 0
src-json/define.json

@@ -242,6 +242,13 @@
 		"platforms": ["cpp"],
 		"params": ["name"]
 	},
+	{
+		"name": "Hlc",
+		"define": "hlc",
+		"doc": "Defined by compiler when using hl/c target.",
+		"platforms": ["hl"],
+		"reserved": true
+	},
 	{
 		"name": "HlVer",
 		"define": "hl-ver",

+ 7 - 9
src/compiler/compiler.ml

@@ -269,13 +269,13 @@ let do_type ctx mctx actx display_file_dot_path macro_cache_enabled =
 	let t = Timer.timer ["typing"] in
 	let cs = com.cs in
 	CommonCache.maybe_add_context_sign cs com "before_init_macros";
-	com.stage <- CInitMacrosStart;
+	enter_stage com CInitMacrosStart;
 	ServerMessage.compiler_stage com;
 
 	let mctx = List.fold_left (fun mctx path ->
 		Some (MacroContext.call_init_macro ctx.com mctx path)
 	) mctx (List.rev actx.config_macros) in
-	com.stage <- CInitMacrosDone;
+	enter_stage com CInitMacrosDone;
 	ServerMessage.compiler_stage com;
 	MacroContext.macro_enable_cache := macro_cache_enabled;
 
@@ -295,7 +295,7 @@ let do_type ctx mctx actx display_file_dot_path macro_cache_enabled =
 	end with TypeloadParse.DisplayInMacroBlock ->
 		ignore(DisplayProcessing.load_display_module_in_macro tctx display_file_dot_path true)
 	);
-	com.stage <- CTypingDone;
+	enter_stage com CTypingDone;
 	ServerMessage.compiler_stage com;
 	(* If we are trying to find references, let's syntax-explore everything we know to check for the
 		identifier we are interested in. We then type only those modules that contain the identifier. *)
@@ -309,7 +309,7 @@ let do_type ctx mctx actx display_file_dot_path macro_cache_enabled =
 let finalize_typing ctx tctx =
 	let t = Timer.timer ["finalize"] in
 	let com = ctx.com in
-	com.stage <- CFilteringStart;
+	enter_stage com CFilteringStart;
 	ServerMessage.compiler_stage com;
 	let main, types, modules = run_or_diagnose ctx Finalization.generate tctx in
 	com.main <- main;
@@ -348,7 +348,7 @@ let compile ctx actx callbacks =
 	let t = Timer.timer ["init"] in
 	List.iter (fun f -> f()) (List.rev (actx.pre_compilation));
 	t();
-	com.stage <- CInitialized;
+	enter_stage com CInitialized;
 	ServerMessage.compiler_stage com;
 	if actx.classes = [([],"Std")] && not actx.force_typing then begin
 		if actx.cmds = [] && not actx.did_something then actx.raise_usage();
@@ -361,10 +361,10 @@ let compile ctx actx callbacks =
 		filter ctx tctx;
 		if ctx.has_error then raise Abort;
 		Generate.check_auxiliary_output com actx;
-		com.stage <- CGenerationStart;
+		enter_stage com CGenerationStart;
 		ServerMessage.compiler_stage com;
 		if not actx.no_output then Generate.generate ctx tctx ext actx;
-		com.stage <- CGenerationDone;
+		enter_stage com CGenerationDone;
 		ServerMessage.compiler_stage com;
 	end;
 	Sys.catch_break false;
@@ -401,8 +401,6 @@ with
 		end
 	| Error.Error err ->
 		error_ext ctx err
-	| Generic.Generic_Exception(m,p) ->
-		error ctx m p
 	| Arg.Bad msg ->
 		error ctx ("Error: " ^ msg) null_pos
 	| Failure msg when not Helper.is_debug_run ->

+ 7 - 1
src/context/common.ml

@@ -432,6 +432,10 @@ type context = {
 	memory_marker : float array;
 }
 
+let enter_stage com stage =
+	(* print_endline (Printf.sprintf "Entering stage %s" (s_compiler_stage stage)); *)
+	com.stage <- stage
+
 exception Abort of Error.error
 
 let ignore_error com =
@@ -478,7 +482,7 @@ let external_defined_value ctx k =
 	Define.raw_defined_value ctx.defines (convert_define k)
 
 let reserved_flags = [
-	"true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";
+	"true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";"hl";"hlc";
 	"swc";"macro";"sys";"static";"utf16";"haxe";"haxe_ver"
 ]
 
@@ -930,6 +934,8 @@ let init_platform com =
 		define com Define.Swc
 	| Jvm ->
 		raw_define com "java"
+	| Hl ->
+		if Path.file_extension com.file = "c" then define com Define.Hlc;
 	| _ ->
 		()
 	end;

+ 2 - 2
src/context/display/displayTexpr.ml

@@ -63,7 +63,7 @@ let actually_check_display_field ctx c cff p =
 	let display_modifier = Typeload.check_field_access ctx cff in
 	let fctx = TypeloadFields.create_field_context ctx cctx cff true display_modifier in
 	let cf = TypeloadFields.init_field (ctx,cctx,fctx) cff in
-	flush_pass ctx PTypeField "check_display_field";
+	flush_pass ctx PTypeField ("check_display_field",(fst c.cl_path @ [snd c.cl_path;fst cff.cff_name]));
 	ignore(follow cf.cf_type)
 
 let check_display_field ctx sc c cf =
@@ -90,7 +90,7 @@ let check_display_class ctx decls c =
 		ignore(Typeload.type_type_params ctx TPHType c.cl_path (fun() -> c.cl_params) null_pos sc.d_params);
 		List.iter (function
 			| (HExtends(ct,p) | HImplements(ct,p)) when display_position#enclosed_in p ->
-				ignore(Typeload.load_instance ~allow_display:true ctx (ct,p) false)
+				ignore(Typeload.load_instance ~allow_display:true ctx (ct,p) ParamNormal)
 			| _ ->
 				()
 		) sc.d_flags;

+ 1 - 1
src/context/display/syntaxExplorer.ml

@@ -177,7 +177,7 @@ let explore_uncached_modules tctx cs symbols =
 			begin try
 				let m = tctx.g.do_load_module tctx (cfile.c_package,module_name) null_pos in
 				(* We have to flush immediately so we catch exceptions from weird modules *)
-				Typecore.flush_pass tctx Typecore.PFinal "final";
+				Typecore.flush_pass tctx Typecore.PFinal ("final",cfile.c_package @ [module_name]);
 				m :: acc
 			with _ ->
 				acc

+ 68 - 30
src/context/typecore.ml

@@ -72,9 +72,23 @@ type delay = {
 	delay_functions : (unit -> unit) list;
 }
 
+type build_kind =
+	| BuildNormal
+	| BuildGeneric of tclass
+	| BuildGenericBuild
+	| BuildMacroType
+
+type build_info = {
+	build_kind : build_kind;
+	build_path : path;
+	build_params : type_params;
+	build_extern : bool;
+	build_apply : Type.t list -> Type.t;
+}
+
 type typer_globals = {
 	mutable delayed : delay list;
-	mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list;
+	mutable debug_delayed : (typer_pass * ((unit -> unit) * (string * string list) * typer) list) list;
 	doinline : bool;
 	retain_meta : bool;
 	mutable core_api : typer option;
@@ -89,12 +103,11 @@ type typer_globals = {
 	mutable load_only_cached_modules : bool;
 	functional_interface_lut : (path,tclass_field) lookup;
 	(* api *)
-	do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool;
 	do_macro : typer -> macro_mode -> path -> string -> expr list -> pos -> expr option;
 	do_load_macro : typer -> bool -> path -> string -> pos -> ((string * bool * t) list * t * tclass * Type.tclass_field);
 	do_load_module : typer -> path -> pos -> module_def;
 	do_load_type_def : typer -> pos -> type_path -> module_type;
-	do_build_instance : typer -> module_type -> pos -> (typed_type_param list * path * (t list -> t));
+	get_build_info : typer -> module_type -> pos -> build_info;
 	do_format_string : typer -> string -> pos -> Ast.expr;
 	do_load_core_class : typer -> tclass -> tclass;
 }
@@ -200,6 +213,14 @@ type dot_path_part = {
 	pos : pos
 }
 
+let make_build_info kind path params extern apply = {
+	build_kind = kind;
+	build_path = path;
+	build_params = params;
+	build_extern = extern;
+	build_apply = apply;
+}
+
 exception Forbid_package of (string * path * pos) * pos list * string
 
 exception WithTypeError of error
@@ -422,7 +443,7 @@ let delay_if_mono ctx p t f = match follow t with
 	| _ ->
 		f()
 
-let rec flush_pass ctx p (where:string) =
+let rec flush_pass ctx p where =
 	match ctx.g.delayed with
 	| delay :: rest when delay.delay_pass <= p ->
 		(match delay.delay_functions with
@@ -440,10 +461,11 @@ let make_pass ctx f = f
 let init_class_done ctx =
 	ctx.pass <- PTypeField
 
-let exc_protect ?(force=true) ctx f (where:string) =
+let make_lazy ?(force=true) ctx t_proc f where =
 	let r = ref (lazy_available t_dynamic) in
 	r := lazy_wait (fun() ->
 		try
+			r := lazy_processing t_proc;
 			let t = f r in
 			r := lazy_available t;
 			t
@@ -762,8 +784,8 @@ let create_deprecation_context ctx = {
 }
 
 (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
-(*/*
 
+(*
 let delay_tabs = ref ""
 
 let context_ident com =
@@ -774,28 +796,42 @@ let context_ident com =
 	else
 		"  out "
 
-let debug com str =
+let debug_paths = [
+	(* ["Main"] *)
+]
+
+let debug com (path : string list) str =
 	if Common.raw_defined com "cdebug" then begin
-		let s = (context_ident com ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) in
-		match com.json_out with
-		| None -> print_endline s
-		| Some _ -> DynArray.add com.pass_debug_messages s
+		let emit () =
+			let s = (context_ident com ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) in
+			match com.json_out with
+			| None -> print_endline s
+			| Some _ -> DynArray.add com.pass_debug_messages s
+		in
+		match debug_paths,path with
+		| [],_
+		| _,[] ->
+			emit()
+		| l ->
+			if List.exists (Ast.match_path false path) debug_paths then emit();
 	end
 
 let init_class_done ctx =
-	debug ctx.com ("init_class_done " ^ s_type_path ctx.curclass.cl_path);
+	let path = fst ctx.curclass.cl_path @ [snd ctx.curclass.cl_path] in
+	debug ctx.com path ("init_class_done " ^ s_type_path ctx.curclass.cl_path);
 	init_class_done ctx
 
 let ctx_pos ctx =
-	let inf = s_type_path ctx.m.curmod.m_path in
-	let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf ^ "." ^ n) in
-	let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in
+	let inf = fst ctx.m.curmod.m_path @ [snd ctx.m.curmod.m_path]in
+	let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf @ [n]) in
+	let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf @ [n]) in
 	inf
 
 let pass_infos ctx p =
-	let inf = pass_name p ^ " ("  ^ ctx_pos ctx ^ ")" in
+	let path = ctx_pos ctx in
+	let inf = pass_name p ^ " ("  ^ String.concat "." path ^ ")" in
 	let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in
-	inf
+	inf,path
 
 let delay ctx p f =
 	let inf = pass_infos ctx p in
@@ -810,7 +846,7 @@ let delay ctx p f =
 				(p,[f,inf,ctx]) :: (p2,l) :: rest
 	in
 	ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
-	debug ctx.com ("add " ^ inf)
+	debug ctx.com (snd inf) ("add " ^ (fst inf))
 
 let delay_late ctx p f =
 	let inf = pass_infos ctx p in
@@ -823,7 +859,7 @@ let delay_late ctx p f =
 				(p,[f,inf,ctx]) :: (p2,l) :: rest
 	in
 	ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
-	debug ctx.com ("add late " ^ inf)
+	debug ctx.com (snd inf) ("add late " ^ (fst inf))
 
 let pending_passes ctx =
 	let rec loop acc = function
@@ -832,20 +868,20 @@ let pending_passes ctx =
 	in
 	match loop [] ctx.g.debug_delayed with
 	| [] -> ""
-	| l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]"
+	| l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,(i,_),_) -> i) l) ^ "]"
 
 let display_error com ?(depth=0) msg p =
-	debug com ("ERROR " ^ msg);
+	debug com [] ("ERROR " ^ msg);
 	display_error com ~depth msg p
 
 let display_error_ext com err =
-	debug com ("ERROR " ^ (error_msg err.err_message));
+	debug com [] ("ERROR " ^ (error_msg err.err_message));
 	display_error_ext com err
 
 let make_pass ?inf ctx f =
-	let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
+	let inf,path = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
 	(fun v ->
-		debug ctx.com ("run " ^ inf ^ pending_passes ctx);
+		debug ctx.com path ("run " ^ inf ^ pending_passes ctx);
 		let old = !delay_tabs in
 		delay_tabs := !delay_tabs ^ "\t";
 		let t = (try
@@ -855,7 +891,7 @@ let make_pass ?inf ctx f =
 				delay_tabs := old;
 				raise exc
 			| exc when not (Common.raw_defined ctx.com "stack") ->
-				debug ctx.com ("FATAL " ^ Printexc.to_string exc);
+				debug ctx.com path ("FATAL " ^ Printexc.to_string exc);
 				delay_tabs := old;
 				raise exc
 		) in
@@ -882,21 +918,23 @@ let rec flush_pass ctx p where =
 	match ctx.g.debug_delayed with
 	| (p2,_) :: _ when p2 <= p ->
 		let old = !delay_tabs in
-		debug ctx.com ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
+		debug ctx.com (snd where) ("flush " ^ pass_name p ^ "(" ^ (fst where) ^ ")");
 		delay_tabs := !delay_tabs ^ "\t";
 		loop();
 		delay_tabs := old;
-		debug ctx.com "flush-done";
+		debug ctx.com (snd where) "flush-done";
 	| _ ->
 		()
 
 let make_where ctx where =
-	where ^ " (" ^ ctx_pos ctx ^ ")"
+	let inf = ctx_pos ctx in
+	where ^ " (" ^ String.concat "." inf ^ ")",inf
 
-let exc_protect ?(force=true) ctx f (where:string) =
+let make_lazy ?(force=true) ctx t f (where:string) =
 	let r = ref (lazy_available t_dynamic) in
 	r := lazy_wait (make_pass ~inf:(make_where ctx where) ctx (fun() ->
 		try
+			r := lazy_processing t;
 			let t = f r in
 			r := lazy_available t;
 			t
@@ -907,7 +945,7 @@ let exc_protect ?(force=true) ctx f (where:string) =
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
 
-*/*)
+*)
 (* --------------------------------------------------- *)
 
 

+ 5 - 5
src/core/inheritDoc.ml

@@ -34,8 +34,8 @@ let rec get_class_field c field_name =
 		| None -> raise Not_found
 		| Some (csup, _) -> get_class_field csup field_name
 
-let find_type ctx tp allow_no_params =
-	try Typeload.load_instance' ctx tp allow_no_params
+let find_type ctx tp =
+	try Typeload.load_instance' ctx tp ParamSpawnMonos
 	with _ -> raise Not_found
 
 (**
@@ -160,7 +160,7 @@ and get_target_doc ctx e_target =
 			| _ ->
 				mk_type_path path
 		in
-		let t = (find_type ctx (tp,snd e_target) true) in
+		let t = (find_type ctx (tp,snd e_target)) in
 		try
 			match follow t with
 			| TInst (c, _) ->
@@ -207,11 +207,11 @@ and get_target_doc ctx e_target =
 	in
 	let resolve_type () =
 		let tp = mk_type_path path, snd e_target in
-		resolve_type_t (find_type ctx tp true)
+		resolve_type_t (find_type ctx tp)
 	in
 	let resolve_sub_type sub =
 		let tp = mk_type_path ~sub path, snd e_target in
-		resolve_type_t (find_type ctx tp true)
+		resolve_type_t (find_type ctx tp)
 	in
 	try
 		match sub with

+ 7 - 4
src/core/tFunctions.ml

@@ -271,11 +271,11 @@ let add_descendant c descendant =
 
 let lazy_type f =
 	match !f with
-	| LAvailable t -> t
-	| LProcessing f | LWait f -> f()
+	| LAvailable t | LProcessing t -> t
+	| LWait f -> f()
 
 let lazy_available t = LAvailable t
-let lazy_processing f = LProcessing f
+let lazy_processing t = LProcessing t
 let lazy_wait f = LWait f
 
 let map loop t =
@@ -506,7 +506,10 @@ let rec follow t =
 		| Some t -> follow t
 		| _ -> t)
 	| TLazy f ->
-		follow (lazy_type f)
+		(match !f with
+		| LAvailable t -> follow t
+		| _ -> follow (lazy_type f)
+		)
 	| TType (t,tl) ->
 		follow (apply_typedef t tl)
 	| TAbstract({a_path = [],"Null"},[t]) ->

+ 2 - 2
src/core/tType.ml

@@ -83,7 +83,7 @@ and tmono_constraint_kind =
 
 and tlazy =
 	| LAvailable of t
-	| LProcessing of (unit -> t)
+	| LProcessing of t
 	| LWait of (unit -> t)
 
 and tsignature = (string * bool * t) list * t
@@ -461,7 +461,7 @@ type flag_tclass_field =
 
 (* Order has to match declaration for printing*)
 let flag_tclass_field_names = [
-	"CfPublic";"CfStatic";"CfExtern";"CfFinal";"CfModifiesThis";"CfOverride";"CfAbstract";"CfOverload";"CfImpl";"CfEnum";"CfGeneric";"CfDefault"
+	"CfPublic";"CfStatic";"CfExtern";"CfFinal";"CfModifiesThis";"CfOverride";"CfAbstract";"CfOverload";"CfImpl";"CfEnum";"CfGeneric";"CfDefault";"CfPostProcessed"
 ]
 
 type flag_tvar =

+ 13 - 0
src/core/texpr.ml

@@ -189,6 +189,19 @@ let map_expr_type f ft fv e =
 		{ e with eexpr = TEnumParameter (f e1,ef,i); etype = ft e.etype }
 	| TEnumIndex e1 ->
 		{ e with eexpr = TEnumIndex (f e1); etype = ft e.etype }
+	| TField (e1,(FClosure(None,cf) as fa)) ->
+		let e1 = f e1 in
+		let fa = try
+			begin match quick_field e1.etype cf.cf_name with
+				| FInstance(c,tl,cf) ->
+					FClosure(Some(c,tl),cf)
+				| _ ->
+					raise Not_found
+			end
+		with Not_found ->
+			fa
+		in
+		{ e with eexpr = TField (e1,fa); etype = ft e.etype }
 	| TField (e1,v) ->
 		let e1 = f e1 in
 		let v = try

+ 6 - 6
src/filters/exceptions.ml

@@ -532,23 +532,23 @@ let filter tctx =
 				(mk_type_path (pack,name), null_pos)
 		in
 		let wildcard_catch_type =
-			let t = Typeload.load_instance tctx (tp config.ec_wildcard_catch) true in
+			let t = Typeload.load_instance tctx (tp config.ec_wildcard_catch) ParamSpawnMonos in
 			if is_dynamic t then t_dynamic
 			else t
 		and base_throw_type =
-			let t = Typeload.load_instance tctx (tp config.ec_base_throw) true in
+			let t = Typeload.load_instance tctx (tp config.ec_base_throw) ParamSpawnMonos in
 			if is_dynamic t then t_dynamic
 			else t
 		and haxe_exception_type, haxe_exception_class =
-			match Typeload.load_instance tctx (tp haxe_exception_type_path) true with
+			match Typeload.load_instance tctx (tp haxe_exception_type_path) ParamSpawnMonos with
 			| TInst(cls,_) as t -> t,cls
 			| _ -> raise_typing_error "haxe.Exception is expected to be a class" null_pos
 		and value_exception_type, value_exception_class =
-			match Typeload.load_instance tctx (tp value_exception_type_path) true with
+			match Typeload.load_instance tctx (tp value_exception_type_path) ParamSpawnMonos with
 			| TInst(cls,_) as t -> t,cls
 			| _ -> raise_typing_error "haxe.ValueException is expected to be a class" null_pos
 		and haxe_native_stack_trace =
-			match Typeload.load_instance tctx (tp (["haxe"],"NativeStackTrace")) true with
+			match Typeload.load_instance tctx (tp (["haxe"],"NativeStackTrace")) ParamSpawnMonos with
 			| TInst(cls,_) -> cls
 			| TAbstract({ a_impl = Some cls },_) -> cls
 			| _ -> raise_typing_error "haxe.NativeStackTrace is expected to be a class or an abstract" null_pos
@@ -665,7 +665,7 @@ let insert_save_stacks tctx =
 *)
 let patch_constructors tctx =
 	let tp = (mk_type_path haxe_exception_type_path, null_pos) in
-	match Typeload.load_instance tctx tp true with
+	match Typeload.load_instance tctx tp ParamSpawnMonos with
 	(* Add only if `__shiftStack` method exists *)
 	| TInst(cls,_) when PMap.mem "__shiftStack" cls.cl_fields ->
 		(fun mt ->

+ 7 - 7
src/filters/filters.ml

@@ -672,7 +672,7 @@ let destruction tctx detail_times main locals =
 			check_remove_metadata t;
 		) com.types;
 	);
-	com.stage <- CDceStart;
+	enter_stage com CDceStart;
 	with_timer detail_times "dce" None (fun () ->
 		(* DCE *)
 		let dce_mode = try Common.defined_value com Define.Dce with _ -> "no" in
@@ -684,7 +684,7 @@ let destruction tctx detail_times main locals =
 		in
 		Dce.run com main dce_mode;
 	);
-	com.stage <- CDceDone;
+	enter_stage com CDceDone;
 	(* PASS 3: type filters post-DCE *)
 	List.iter
 		(run_expression_filters
@@ -719,7 +719,7 @@ let destruction tctx detail_times main locals =
 		) com.types;
 	);
 	com.callbacks#run com.error_ext com.callbacks#get_after_filters;
-	com.stage <- CFilteringDone
+	enter_stage com CFilteringDone
 
 let update_cache_dependencies com t =
 	let visited_anons = ref [] in
@@ -926,9 +926,9 @@ let run tctx main =
 	with_timer detail_times "type 1" None (fun () ->
 		List.iter (fun f -> List.iter f new_types) filters;
 	);
-	com.stage <- CAnalyzerStart;
+	enter_stage com CAnalyzerStart;
 	if com.platform <> Cross then Analyzer.Run.run_on_types com new_types;
-	com.stage <- CAnalyzerDone;
+	enter_stage com CAnalyzerDone;
 	let locals = RenameVars.init com in
 	let filters = [
 		"sanitize",Optimizer.sanitize com;
@@ -943,14 +943,14 @@ let run tctx main =
 	with_timer detail_times "callbacks" None (fun () ->
 		com.callbacks#run com.error_ext com.callbacks#get_before_save;
 	);
-	com.stage <- CSaveStart;
+	enter_stage com CSaveStart;
 	with_timer detail_times "save state" None (fun () ->
 		List.iter (fun mt ->
 			update_cache_dependencies com mt;
 			save_class_state com mt
 		) new_types;
 	);
-	com.stage <- CSaveDone;
+	enter_stage com CSaveDone;
 	with_timer detail_times "callbacks" None (fun () ->
 		com.callbacks#run com.error_ext com.callbacks#get_after_save;
 	);

+ 1 - 1
src/generators/gencpp.ml

@@ -4280,7 +4280,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_
       | OpBoolOr -> "||"
       | OpShl -> "<<"
       | OpShr -> ">>"
-      | OpUShr -> "<<<"
+      | OpUShr -> ">>>"
       | OpMod -> "%"
       | OpInterval -> "..."
       | OpArrow -> "->"

+ 7 - 5
src/generators/hl2c.ml

@@ -91,8 +91,7 @@ let keywords =
 	(* Values *)
 	"NULL";"true";"false";
 	(* MS specific *)
-	"__asm";"dllimport2";"__int8";"naked2";"__based1";"__except";"__int16";"__stdcall";"__cdecl";"__fastcall";"__int32";
-	"thread2";"__declspec";"__finally";"__int64";"__try";"dllexport2";"__inline";"__leave";"asm";
+	"asm";"dllimport2";"dllexport2";"naked2";"thread2";
 	(* reserved by HLC *)
 	"t";
 	(* GCC *)
@@ -105,7 +104,7 @@ let keywords =
 	List.iter (fun i -> Hashtbl.add h i ()) c_kwds;
 	h
 
-let ident i = if Hashtbl.mem keywords i then "_" ^ i else i
+let ident i = if (Hashtbl.mem keywords i) || (ExtString.String.starts_with "__" i) then "_hx_" ^ i else i
 
 let s_comp = function
 	| CLt -> "<"
@@ -122,7 +121,7 @@ let core_types =
 
 let tname str =
 	let n = String.concat "__" (ExtString.String.nsplit str ".") in
-	if Hashtbl.mem keywords ("_" ^ n) then "__" ^ n else n
+	ident n
 
 let is_gc_ptr = function
 	| HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HType | HRef _ | HMethod _ | HPacked _ -> false
@@ -844,7 +843,10 @@ let generate_function ctx f =
 		| OSShr (r,a,b) ->
 			sexpr "%s = %s >> %s" (reg r) (reg a) (reg b)
 		| OUShr (r,a,b) ->
-			sexpr "%s = ((unsigned)%s) >> %s" (reg r) (reg a) (reg b)
+			(match rtype r with
+			| HI64 -> sexpr "%s = ((uint64_t)%s) >> %s" (reg r) (reg a) (reg b)
+			| _ -> sexpr "%s = ((unsigned)%s) >> %s" (reg r) (reg a) (reg b)
+			);
 		| OAnd (r,a,b) ->
 			sexpr "%s = %s & %s" (reg r) (reg a) (reg b)
 		| OOr (r,a,b) ->

+ 1 - 1
src/optimization/inline.ml

@@ -853,7 +853,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 	let tl = arg_types params f.tf_args in
 	let e = state#finalize e tl tret has_params map_type p in
 	if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin
-		let se t = s_expr_pretty true t true (s_type (print_context())) in
+		let se t = s_expr_ast true t (s_type (print_context())) in
 		print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s"
 			cf.cf_name
 			(String.concat "" (List.map (fun (i,e) -> Printf.sprintf "\n\t\t%s<%i> = %s" (i.i_subst.v_name) (i.i_subst.v_id) (se "\t\t" e)) state#inlined_vars))

+ 23 - 13
src/typing/callUnification.ml

@@ -307,10 +307,16 @@ let unify_field_call ctx fa el_typed el p inline =
 		| t ->
 			raise_typing_error (s_type (print_context()) t ^ " cannot be called") p
 	in
-	let maybe_raise_unknown_ident err =
+	let unknown_ident_error = ref None in
+	let remember_unknown_ident_error =
+		fun err -> match !unknown_ident_error with
+			| None -> unknown_ident_error := Some err
+			| Some _ -> ()
+	in
+	let check_unknown_ident err =
 		let rec loop err =
 			match err.err_message with
-			| Call_error (Could_not_unify Unknown_ident _) | Unknown_ident _ -> raise_typing_error_ext err
+			| Call_error (Could_not_unify Unknown_ident _) | Unknown_ident _ -> remember_unknown_ident_error err
 			| _ -> List.iter loop err.err_sub
 		in
 		loop err
@@ -337,7 +343,7 @@ let unify_field_call ctx fa el_typed el p inline =
 						if constr != m.tm_down_constraints then m.tm_down_constraints <- constr;
 					) known_monos;
 					ctx.monomorphs.perfunction <- current_monos;
-					maybe_raise_unknown_ident err;
+					check_unknown_ident err;
 					let candidates,failures = loop candidates in
 					candidates,(cf,err,extract_delayed_display()) :: failures
 				end
@@ -384,17 +390,21 @@ let unify_field_call ctx fa el_typed el p inline =
 			| [_,err] ->
 				raise_typing_error_ext err
 			| _ ->
-				let sub = List.fold_left (fun acc (cf,err) ->
-					(make_error
-						~depth:1 (* pretty much optional here *)
-						~sub:[err]
-						(Custom ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)))
-						p
-					) :: acc
-				) [] failures in
+				match !unknown_ident_error with
+				| None ->
+					let sub = List.fold_left (fun acc (cf,err) ->
+						(make_error
+							~depth:1 (* pretty much optional here *)
+							~sub:[err]
+							(Custom ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)))
+							p
+						) :: acc
+					) [] failures in
 
-				display_error_ext ctx.com (make_error ~sub (Custom "Could not find a suitable overload, reasons follow") p);
-				raise_typing_error_ext (make_error ~depth:1 (Custom "End of overload failure reasons") p)
+					display_error_ext ctx.com (make_error ~sub (Custom "Could not find a suitable overload, reasons follow") p);
+					raise_typing_error_ext (make_error ~depth:1 (Custom "End of overload failure reasons") p)
+				| Some err ->
+					raise_typing_error_ext err
 			end
 		in
 		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with

+ 1 - 16
src/typing/calls.ml

@@ -192,22 +192,7 @@ let rec acc_get ctx g =
 		else acc_get ctx acc;
 	| AKExpr e -> e
 	| AKSafeNav sn ->
-		(* generate null-check branching for the safe navigation chain *)
-		let eobj = sn.sn_base in
-		let enull = Builder.make_null eobj.etype sn.sn_pos in
-		let eneq = Builder.binop OpNotEq eobj enull ctx.t.tbool sn.sn_pos in
-		let ethen = acc_get ctx sn.sn_access in
-		let tnull = ctx.t.tnull ethen.etype in
-		let ethen = if not (is_nullable ethen.etype) then
-			mk (TCast(ethen,None)) tnull ethen.epos
-		else
-			ethen
-		in
-		let eelse = Builder.make_null tnull sn.sn_pos in
-		let eif = mk (TIf(eneq,ethen,Some eelse)) tnull sn.sn_pos in
-		(match sn.sn_temp_var with
-		| None -> eif
-		| Some evar -> { eif with eexpr = TBlock [evar; eif] })
+		safe_nav_branch ctx sn (fun () -> acc_get ctx sn.sn_access)
 	| AKAccess _ -> die "" __LOC__
 	| AKResolve(sea,name) ->
 		(dispatcher sea.se_access.fa_pos)#resolve_call sea name

+ 4 - 1
src/typing/fields.ml

@@ -533,7 +533,8 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 			)
 		| _ -> raise Not_found
 	in
-	let type_field_by_module e t = match e.eexpr with
+	let type_field_by_module e t =
+		match e.eexpr with
 		| TTypeExpr mt ->
 			let infos = t_infos mt in
 			if snd infos.mt_path <> snd infos.mt_module.m_path then raise Not_found;
@@ -541,6 +542,8 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 			begin match infos.mt_module.m_statics with
 			| Some c when PMap.mem i c.cl_statics ->
 				let cf = PMap.find i c.cl_statics in
+				(* We cannot use e here because in the case of module statics the type could be different (issue #11385). *)
+				let e = type_module_type ctx (TClassDecl c) e.epos in
 				field_access e cf (FHStatic c)
 			| _ ->
 				let t = Typeload.find_type_in_module infos.mt_module i in

+ 2 - 2
src/typing/finalization.ml

@@ -79,7 +79,7 @@ let get_main ctx types =
 		Some main
 
 let finalize ctx =
-	flush_pass ctx PFinal "final";
+	flush_pass ctx PFinal ("final",[]);
 	match ctx.com.callbacks#get_after_typing with
 		| [] ->
 			()
@@ -91,7 +91,7 @@ let finalize ctx =
 					()
 				| new_types ->
 					List.iter (fun f -> f new_types) fl;
-					flush_pass ctx PFinal "final";
+					flush_pass ctx PFinal ("final",[]);
 					loop all_types
 			in
 			loop []

+ 176 - 133
src/typing/generic.ml

@@ -6,17 +6,16 @@ open Type
 open Typecore
 open Error
 
-exception Generic_Exception of string * pos
-
 type generic_context = {
 	ctx : typer;
 	subst : (t * (t * texpr option)) list;
 	name : string;
 	p : pos;
 	mutable mg : module_def option;
+	generic_debug : bool;
 }
 
-let make_generic ctx ps pt p =
+let make_generic ctx ps pt debug p =
 	let subst s = "_" ^ string_of_int (Char.code (String.get (Str.matched_string s) 0)) ^ "_" in
 	let ident_safe = Str.global_substitute (Str.regexp "[^a-zA-Z0-9_]") subst in
 	let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
@@ -27,7 +26,7 @@ let make_generic ctx ps pt p =
 					| KExpr e ->
 						let name = ident_safe (Ast.Printer.s_expr e) in
 						let e = type_expr {ctx with locals = PMap.empty} e WithType.value in
-						name,(e.etype,Some e)
+						name,(t,Some e)
 					| _ ->
 						((ident_safe (s_type_path_underscore c.cl_path)) ^ (loop_tl top tl),(t,None))
 				end
@@ -62,7 +61,7 @@ let make_generic ctx ps pt p =
 	in
 	let rec loop acc_name acc_subst ttpl tl = match ttpl,tl with
 		| ttp :: ttpl,t :: tl ->
-			let name,t = try process t with Exit -> raise (Generic_Exception (("Could not determine type for parameter " ^ ttp.ttp_name), p)) in
+			let name,t = try process t with Exit -> raise_typing_error ("Could not determine type for parameter " ^ ttp.ttp_name) p in
 			loop (name :: acc_name) ((follow ttp.ttp_type,t) :: acc_subst) ttpl tl
 		| [],[] ->
 			let name = String.concat "_" (List.rev acc_name) in
@@ -77,22 +76,33 @@ let make_generic ctx ps pt p =
 		name = name;
 		p = p;
 		mg = None;
+		generic_debug = debug;
 	}
 
-let rec generic_substitute_type gctx t =
+let rec generic_substitute_type' gctx allow_expr t =
 	match t with
 	| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
 		(* maybe loop, or generate cascading generics *)
-		let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
-		let t = f (List.map (generic_substitute_type gctx) tl2) in
+		let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c2) gctx.p in
+		let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl2) in
 		(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
 		t
 	| _ ->
 		try
-			let t,_ = List.assq t gctx.subst in
-			generic_substitute_type gctx t
+			let t,eo = List.assq t gctx.subst in
+			(* Somewhat awkward: If we allow expression types, use the original KExpr one. This is so
+			   recursing into further KGeneric expands correctly. *)
+			begin match eo with
+			| Some e when not allow_expr ->
+				e.etype
+			| _ ->
+				generic_substitute_type' gctx false t
+			end
 		with Not_found ->
-			Type.map (generic_substitute_type gctx) t
+			Type.map (generic_substitute_type' gctx allow_expr) t
+
+let generic_substitute_type gctx t =
+	generic_substitute_type' gctx false t
 
 let generic_substitute_expr gctx e =
 	let vars = Hashtbl.create 0 in
@@ -108,8 +118,8 @@ let generic_substitute_expr gctx e =
 	let rec build_expr e =
 		let e = match e.eexpr with
 		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
-			let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in
-			let t = f (List.map (generic_substitute_type gctx) tl) in
+			let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c) gctx.p in
+			let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl) in
 			begin match follow t with
 			| TInst(c',_) when c == c' ->
 				(* The @:generic class wasn't expanded, let's not recurse to avoid infinite loop (#6430) *)
@@ -159,7 +169,7 @@ let static_method_container gctx c cf p =
 	let pack = fst c.cl_path in
 	let name = (snd c.cl_path) ^ "_" ^ cf.cf_name ^ "_" ^ gctx.name in
 	try
-		let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) true in
+		let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) ParamSpawnMonos in
 		match t with
 		| TInst(cg,_) -> cg
 		| _ -> raise_typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
@@ -213,7 +223,15 @@ let set_type_parameter_dependencies mg tl =
 	in
 	List.iter loop tl
 
-let rec build_generic_class ctx c p tl =
+let build_instances ctx t p =
+	let rec loop t =
+		let t = Typeload.maybe_build_instance ctx t ParamNormal p in
+		Type.map loop t
+	in
+	loop t
+
+
+let build_generic_class ctx c p tl =
 	let pack = fst c.cl_path in
 	let recurse = ref false in
 	let rec check_recursive t =
@@ -233,15 +251,29 @@ let rec build_generic_class ctx c p tl =
 	if !recurse || not (ctx.com.display.dms_full_typing) then begin
 		TInst (c,tl) (* build a normal instance *)
 	end else begin
-	let gctx = make_generic ctx c.cl_params tl p in
+	let gctx = make_generic ctx c.cl_params tl (Meta.has (Meta.Custom ":debug.generic") c.cl_meta) p in
 	let name = (snd c.cl_path) ^ "_" ^ gctx.name in
 	try
-		let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) false in
+		let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) ParamNormal in
 		match t with
 		| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
 		| _ -> raise_typing_error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p
 	with Error { err_message = Module_not_found path } when path = (pack,name) ->
 		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
+		if gctx.generic_debug then begin
+			print_endline (Printf.sprintf "[GENERIC] Building @:generic class %s as %s with:" (s_type_path c.cl_path) name);
+			List.iter (fun (t1,(t2,eo)) ->
+				let name = match follow t1 with
+					| TInst(c,_) -> snd c.cl_path
+					| _ -> die "" __LOC__
+				in
+				let expr = match eo with
+					| None -> ""
+					| Some e -> Printf.sprintf " (expr: %s)" (s_expr_debug e)
+				in
+				print_endline (Printf.sprintf "[GENERIC]   %s: %s%s" name (s_type_kind t2) expr);
+			) gctx.subst
+		end;
 		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		let mg = {
 			m_id = alloc_mid();
@@ -256,11 +288,12 @@ let rec build_generic_class ctx c p tl =
 			| Meta.Access | Allow
 			| Final
 			| Hack
-			| Keep
+			| Keep | KeepSub
 			| NoClosure | NullSafety
 			| Pure
 			| Struct | StructInit
-			| Using ->
+			| Using
+			| AutoBuild ->
 				true
 			| _ ->
 				false
@@ -281,8 +314,7 @@ let rec build_generic_class ctx c p tl =
 				| _ -> die "" __LOC__
 			) ([],[]) cf_old.cf_params in
 			let gctx = {gctx with subst = param_subst @ gctx.subst} in
-			let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *)
-			remove_class_field_flag cf_new CfPostProcessed;
+			let cf_new = {cf_old with cf_pos = cf_old.cf_pos; cf_expr_unoptimized = None} in (* copy *)
 			(* Type parameter constraints are substituted here. *)
 			cf_new.cf_params <- List.rev_map (fun tp -> match follow tp.ttp_type with
 				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
@@ -292,28 +324,41 @@ let rec build_generic_class ctx c p tl =
 				| _ -> die "" __LOC__
 			) params;
 			let f () =
+				ignore(follow cf_old.cf_type);
+				(* We update here because the follow could resolve some TLazy things that end up modifying flags, such as
+				   the inferred CfOverride from #11010. *)
+				cf_new.cf_flags <- cf_old.cf_flags;
+				remove_class_field_flag cf_new CfPostProcessed;
+				if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] expanding %s" cf_old.cf_name);
 				let t = generic_substitute_type gctx cf_old.cf_type in
-				ignore (follow t);
-				begin try (match cf_old.cf_expr with
-					| None ->
-						begin match cf_old.cf_kind with
-							| Method _ when not (has_class_flag c CInterface) && not (has_class_flag c CExtern) && not (has_class_field_flag cf_old CfAbstract) ->
-								(* TODO use sub error *)
-								display_error ctx.com (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos;
-								display_error ctx.com (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p;
-							| _ ->
-								()
-						end
+				let update_expr e =
+					cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
+				in
+				begin match cf_old.cf_expr with
 					| Some e ->
-						cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
-				) with Unify_error l ->
-					raise_typing_error (error_msg (Unify l)) cf_new.cf_pos
+						update_expr e
+					| None ->
+						(* There can be cases like #11152 where cf_expr isn't ready yet. It should be safe to delay this to the end
+						   of the PTypeField pass. *)
+						delay_late ctx PTypeField (fun () -> match cf_old.cf_expr with
+							| Some e ->
+								update_expr e
+							| None ->
+								begin match cf_old.cf_kind with
+									| Method _ when not (has_class_flag c CInterface) && not (has_class_flag c CExtern) && not (has_class_field_flag cf_old CfAbstract) ->
+										(* TODO use sub error *)
+										display_error ctx.com (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos;
+										display_error ctx.com (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p;
+									| _ ->
+										()
+								end
+						);
 				end;
+				if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass_field "  " cf_new));
 				t
 			in
-			let r = exc_protect ctx (fun r ->
-				let t = spawn_monomorph ctx p in
-				r := lazy_processing (fun() -> t);
+			let t = spawn_monomorph ctx p in
+			let r = make_lazy ctx t (fun r ->
 				let t0 = f() in
 				unify_raise t0 t p;
 				link_dynamic t0 t;
@@ -330,14 +375,9 @@ let rec build_generic_class ctx c p tl =
 		cg.cl_super <- (match c.cl_super with
 			| None -> None
 			| Some (cs,pl) ->
-				let ts = follow (apply_params c.cl_params tl (TInst(cs,pl))) in
-				let cs,pl = TypeloadCheck.Inheritance.check_extends ctx c ts p in
-				match cs.cl_kind with
-				| KGeneric ->
-					(match build_generic_class ctx cs p pl with
-					| TInst (cs,pl) -> Some (cs,pl)
-					| _ -> die "" __LOC__)
-				| _ -> Some(cs,pl)
+				let ts = build_instances ctx (follow (apply_params c.cl_params tl (TInst(cs,pl)))) p in
+				let cs,tl = TypeloadCheck.Inheritance.check_extends ctx c ts p in
+				Some(cs,tl)
 		);
 		TypeloadFunction.add_constructor ctx cg false p;
 		cg.cl_kind <- KGenericInstance (c,tl);
@@ -364,6 +404,8 @@ let rec build_generic_class ctx c p tl =
 			let n = get_short_name () in
 			cg.cl_meta <- (Meta.Native,[EConst(String (n,SDoubleQuotes)),p],null_pos) :: cg.cl_meta;
 		end;
+		cg.cl_using <- c.cl_using;
+		if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass "  " cg));
 		TInst (cg,[])
 	end
 
@@ -377,8 +419,11 @@ let type_generic_function ctx fa fcc with_type p =
 	let cf = fcc.fc_field in
 	if cf.cf_params = [] then raise_typing_error "Function has no type parameters and cannot be generic" p;
 	begin match with_type with
-		| WithType.WithType(t,_) -> unify ctx fcc.fc_ret t p
-		| _ -> ()
+		| WithType.WithType(t,_) ->
+			(* In cases like #5482, we might have a return type that still needs expansion. *)
+			unify ctx (build_instances ctx fcc.fc_ret p) t p
+		| _ ->
+			()
 	end;
 	let monos = fcc.fc_monos in
 	List.iter (fun t -> match follow t with
@@ -386,102 +431,100 @@ let type_generic_function ctx fa fcc with_type p =
 		| _ -> ()
 	) monos;
 	let el = fcc.fc_args in
-	(try
-		let gctx = make_generic ctx cf.cf_params monos p in
-		let name = cf.cf_name ^ "_" ^ gctx.name in
-		let unify_existing_field tcf pcf = try
-			unify_raise tcf fcc.fc_type p
-		with Error ({ err_message = Unify _; err_depth = depth } as err) ->
-			raise (Error { err with err_sub = (make_error
-				~depth
-				~sub:[make_error ~depth:(depth+1) (Custom (compl_msg "Conflicting field was defined here")) pcf]
-				(Custom ("Cannot create field " ^ name ^ " due to type mismatch"))
-				p
-			) :: err.err_sub })
+	let gctx = make_generic ctx cf.cf_params monos (Meta.has (Meta.Custom ":debug.generic") cf.cf_meta) p in
+	let fc_type = build_instances ctx fcc.fc_type p in
+	let name = cf.cf_name ^ "_" ^ gctx.name in
+	let unify_existing_field tcf pcf = try
+		unify_raise tcf fc_type p
+	with Error ({ err_message = Unify _; err_depth = depth } as err) ->
+		raise (Error { err with err_sub = (make_error
+			~depth
+			~sub:[make_error ~depth:(depth+1) (Custom (compl_msg "Conflicting field was defined here")) pcf]
+			(Custom ("Cannot create field " ^ name ^ " due to type mismatch"))
+			p
+		) :: err.err_sub })
+	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
-		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
+		{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) ->
+					(* TODO use sub error *)
+					display_error ctx.com "Only generic type parameters can be constructed" e.epos;
+					display_error ctx.com "While specializing this call" p;
+				| _ ->
+					Type.iter check e
 			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) ->
-						(* TODO use sub error *)
-						display_error ctx.com "Only generic type parameters can be constructed" e.epos;
-						display_error ctx.com "While specializing this call" p;
-					| _ ->
-						Type.iter check e
-				in
-				cf2.cf_expr <- (match cf.cf_expr with
-					| None ->
-						display_error ctx.com "Recursive @:generic function" p; None;
-					| Some e ->
-						let e = 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 = static_method_container gctx c cf p in
-					set_type_parameter_dependencies c.cl_module monos;
-					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
-					set_type_parameter_dependencies c.cl_module monos;
-					let cf2 = mk_cf2 name in
+			cf2.cf_expr <- (match cf.cf_expr with
+				| None ->
+					display_error ctx.com "Recursive @:generic function" p; None;
+				| Some e ->
+					let e = 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 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 = static_method_container gctx c cf p in
+				set_type_parameter_dependencies c.cl_module monos;
+				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;
-					{fa with fa_field = cf2}
-				end
+					cf2
+				in
+				{fa with fa_host = FHStatic c;fa_field = cf2;fa_on = Builder.make_static_this c p}
 			end else begin
 				set_type_parameter_dependencies c.cl_module monos;
 				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;
+				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
-		in
-		let dispatch = new CallUnification.call_dispatcher ctx (MCall []) with_type p in
-		dispatch#field_call fa el []
-	with Generic_Exception (msg,p) ->
-		raise_typing_error msg p)
+		end else begin
+			set_type_parameter_dependencies c.cl_module monos;
+			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 dispatch = new CallUnification.call_dispatcher ctx (MCall []) with_type p in
+	dispatch#field_call fa el []
 
 ;;
 Typecore.type_generic_function_ref := type_generic_function

+ 26 - 19
src/typing/instanceBuilder.ml

@@ -68,15 +68,14 @@ let build_macro_build ctx c pl cfl p =
 (* -------------------------------------------------------------------------- *)
 (* API EVENTS *)
 
-let build_instance ctx mtype p =
+let get_build_info ctx mtype p =
 	match mtype with
 	| TClassDecl c ->
 		if ctx.pass > PBuildClass then ignore(c.cl_build());
-		let build f s =
-			let r = exc_protect ctx (fun r ->
-				let t = spawn_monomorph ctx p in
-				r := lazy_processing (fun() -> t);
-				let tf = (f()) in
+		let build f s tl =
+			let t = spawn_monomorph ctx p in
+			let r = make_lazy ctx t (fun r ->
+				let tf = f tl in
 				unify_raise tf t p;
 				link_dynamic t tf;
 				(match tf with
@@ -88,21 +87,29 @@ let build_instance ctx mtype p =
 			) s in
 			TLazy r
 		in
-		let ft = (fun pl ->
-			match c.cl_kind with
+		let kind,f = match c.cl_kind with
 			| KGeneric ->
-				build (fun () -> Generic.build_generic_class ctx c p pl) "build_generic"
-			| KMacroType ->
-				build (fun () -> build_macro_type ctx pl p) "macro_type"
+				(BuildGeneric c),build (fun tl -> Generic.build_generic_class ctx c p tl) "build_generic"
 			| KGenericBuild cfl ->
-				build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
+				BuildGenericBuild,build (fun tl -> build_macro_build ctx c tl cfl p) "build_generic_build"
+			| KMacroType ->
+				BuildMacroType,build (fun tl -> build_macro_type ctx tl p) "build_macro_type"
 			| _ ->
-				TInst (c,pl)
-		) in
-		c.cl_params , c.cl_path , ft
+				BuildNormal,(fun tl -> TInst(c,tl))
+		in
+		make_build_info kind c.cl_path c.cl_params (has_class_flag c CExtern) f
 	| TEnumDecl e ->
-		e.e_params , e.e_path , (fun t -> TEnum (e,t))
-	| TTypeDecl t ->
-		t.t_params , t.t_path , (fun tl -> TType(t,tl))
+		make_build_info BuildNormal e.e_path e.e_params e.e_extern (fun t -> TEnum (e,t))
+	| TTypeDecl td ->
+		begin try
+			let msg = match Meta.get Meta.Deprecated td.t_meta with
+				| _,[EConst(String(s,_)),_],_ -> s
+				| _ -> "This typedef is deprecated in favor of " ^ (s_type (print_context()) td.t_type)
+			in
+			DeprecationCheck.warn_deprecation (create_deprecation_context ctx) msg p
+		with Not_found ->
+				()
+		end;
+		make_build_info BuildNormal td.t_path td.t_params false (fun tl -> TType(td,tl))
 	| TAbstractDecl a ->
-		a.a_params, a.a_path, (fun tl -> TAbstract(a,tl))
+		make_build_info BuildNormal a.a_path a.a_params false (fun tl -> TAbstract(a,tl))

+ 8 - 10
src/typing/macroContext.ml

@@ -94,7 +94,7 @@ let typing_timer ctx need_type f =
 
 	if need_type && ctx.pass < PTypeField then begin
 		ctx.pass <- PTypeField;
-		flush_pass ctx PBuildClass "typing_timer";
+		flush_pass ctx PBuildClass ("typing_timer",[] (* TODO: ? *));
 	end;
 	let exit() =
 		t();
@@ -340,7 +340,7 @@ let make_macro_api ctx mctx p =
 						mk_type_path path
 				in
 				try
-					let m = Some (Typeload.load_instance ctx (tp,p) true) in
+					let m = Some (Typeload.load_instance ctx (tp,p) ParamSpawnMonos) in
 					m
 				with Error { err_message = Module_not_found _; err_pos = p2 } when p == p2 ->
 					None
@@ -478,7 +478,7 @@ let make_macro_api ctx mctx p =
 		MacroApi.define_type = (fun v mdep ->
 			let cttype = mk_type_path ~sub:"TypeDefinition" (["haxe";"macro"],"Expr") in
 			let mctx = (match ctx.g.macros with None -> die "" __LOC__ | Some (_,mctx) -> mctx) in
-			let ttype = Typeload.load_instance mctx (cttype,p) false in
+			let ttype = Typeload.load_instance mctx (cttype,p) ParamNormal in
 			let f () = Interp.decode_type_def v in
 			let m, tdef, pos = safe_decode ctx.com v "TypeDefinition" ttype p f in
 			let has_native_meta = match tdef with
@@ -579,7 +579,7 @@ let make_macro_api ctx mctx p =
 				List.iter (fun path ->
 					ImportHandling.init_using ctx path null_pos
 				) usings;
-				flush_pass ctx PConnectField "with_imports";
+				flush_pass ctx PConnectField ("with_imports",[] (* TODO: ? *));
 				f()
 			in
 			let restore () =
@@ -806,12 +806,10 @@ let load_macro' ctx display cpath f p =
 	fst (load_macro'' ctx.com (get_macro_context ctx) display cpath f p)
 
 let do_call_macro com api cpath f args p =
-	if com.verbose then Common.log com ("Calling macro " ^ s_type_path cpath ^ "." ^ f ^ " (" ^ p.pfile ^ ":" ^ string_of_int (Lexer.get_error_line p) ^ ")");
 	let t = macro_timer com ["execution";s_type_path cpath ^ "." ^ f] in
 	incr stats.s_macros_called;
 	let r = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [snd cpath]) f args api in
 	t();
-	if com.verbose then Common.log com ("Exiting macro " ^ s_type_path cpath ^ "." ^ f);
 	r
 
 let load_macro ctx com mctx api display cpath f p =
@@ -846,7 +844,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	in
 	let mpos = mfield.cf_pos in
 	let ctexpr = mk_type_path (["haxe";"macro"],"Expr") in
-	let expr = Typeload.load_instance mctx (ctexpr,p) false in
+	let expr = Typeload.load_instance mctx (ctexpr,p) ParamNormal in
 	(match mode with
 	| MDisplay ->
 		raise Exit (* We don't have to actually call the macro. *)
@@ -855,18 +853,18 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	| MBuild ->
 		let params = [TPType (CTPath (mk_type_path ~sub:"Field" (["haxe";"macro"],"Expr")),null_pos)] in
 		let ctfields = mk_type_path ~params ([],"Array") in
-		let tfields = Typeload.load_instance mctx (ctfields,p) false in
+		let tfields = Typeload.load_instance mctx (ctfields,p) ParamNormal in
 		unify mctx mret tfields mpos
 	| MMacroType ->
 		let cttype = mk_type_path (["haxe";"macro"],"Type") in
-		let ttype = Typeload.load_instance mctx (cttype,p) false in
+		let ttype = Typeload.load_instance mctx (cttype,p) ParamNormal in
 		try
 			unify_raise mret ttype mpos;
 			(* TODO: enable this again in the future *)
 			(* warning ctx WDeprecated "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *)
 		with Error { err_message = Unify _ } ->
 			let cttype = mk_type_path ~sub:"ComplexType" (["haxe";"macro"],"Expr") in
-			let ttype = Typeload.load_instance mctx (cttype,p) false in
+			let ttype = Typeload.load_instance mctx (cttype,p) ParamNormal in
 			unify_raise mret ttype mpos;
 	);
 	(*

+ 0 - 101
src/typing/magicTypes.ml

@@ -1,101 +0,0 @@
-open Ast
-open Globals
-open Common
-open Type
-open Typecore
-open Typeload
-open TypeloadModule
-open Error
-
-(* -------------------------------------------------------------------------- *)
-(* REMOTING PROXYS *)
-
-let extend_remoting ctx c t p async prot =
-	if c.cl_super <> None then raise_typing_error "Cannot extend several classes" p;
-	(* remove forbidden packages *)
-	let rules = ctx.com.package_rules in
-	ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
-	(* parse module *)
-	let path = (t.tpackage,t.tname) in
-	let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
-	(* check if the proxy already exists *)
-	let t = (try
-		load_type_def ctx p (mk_type_path (fst path,new_name))
-	with
-		Error { err_message = Module_not_found _; err_pos = p2 } when p == p2 ->
-	(* build it *)
-	Common.log ctx.com ("Building proxy for " ^ s_type_path path);
-	let file, decls = (try
-		TypeloadParse.parse_module ctx path p
-	with
-		| Not_found -> ctx.com.package_rules <- rules; raise_typing_error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p
-		| e -> ctx.com.package_rules <- rules; raise e) in
-	ctx.com.package_rules <- rules;
-	let base_fields = [
-		{ cff_name = "__cnx",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath (mk_type_path (["haxe";"remoting"],if async then "AsyncConnection" else "Connection")),null_pos),None) };
-		{ cff_name = "new",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic,null_pos]; cff_kind = FFun { f_args = [("c",null_pos),false,[],None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } };
-	] in
-	let tvoid = CTPath (mk_type_path ([],"Void")) in
-	let build_field is_public acc f =
-		if fst f.cff_name = "new" then
-			acc
-		else match f.cff_kind with
-		| FFun fd when (is_public || List.mem_assoc APublic f.cff_access) && not (List.mem_assoc AStatic f.cff_access) ->
-			if List.exists (fun (_,_,_,t,_) -> t = None) fd.f_args then raise_typing_error ("Field " ^ fst f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p;
-			let eargs = [EArrayDecl (List.map (fun ((a,_),_,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
-			let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" },_) -> None | _ -> fd.f_type) in
-			let fargs, eargs = if async then match ftype with
-				| Some (tret,_) -> fd.f_args @ [("__callb",null_pos),true,[],Some (CTFunction ([tret,null_pos],(tvoid,null_pos)),null_pos),None], eargs @ [EConst (Ident "__callb"),p]
-				| _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
-			else
-				fd.f_args, eargs
-			in
-			let id = (EConst (String (fst f.cff_name,SDoubleQuotes)), p) in
-			let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
-			let expr = ECall (
-				(efield (
-					(ECall ((efield ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
-					"call")
-				,p),eargs),p
-			in
-			let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
-			let fd = {
-				f_params = fd.f_params;
-				f_args = fargs;
-				f_type = if async then None else ftype;
-				f_expr = Some (EBlock [expr],p);
-			} in
-			{ cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic,null_pos]; cff_kind = FFun fd } :: acc
-		| _ -> acc
-	in
-	let decls = List.map (fun d ->
-		match d with
-		| EClass c, p when fst c.d_name = t.tname ->
-			let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
-			let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
-			(EClass { c with d_flags = []; d_name = new_name,pos c.d_name; d_data = fields },p)
-		| _ -> d
-	) decls in
-	let m = type_module ctx (t.tpackage,new_name) file decls p in
-	add_dependency ctx.m.curmod m;
-	try
-		List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
-	with Not_found ->
-		raise_typing_error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
-	) in
-	match t with
-	| TClassDecl c2 when c2.cl_params = [] -> ignore(c2.cl_build()); c.cl_super <- Some (c2,[]);
-	| _ -> raise_typing_error "Remoting proxy must be a class without parameters" p
-
-let on_inherit ctx c p (is_extends,tp) =
-	if not is_extends then
-		true
-	else match fst tp with
-	| { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t,null_pos)] } ->
-		extend_remoting ctx c t p false true;
-		false
-	| { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t,null_pos)] } ->
-		extend_remoting ctx c t p true true;
-		false
-	| _ ->
-		true

+ 1 - 1
src/typing/matcher/exprToPattern.ml

@@ -58,7 +58,7 @@ let get_general_module_type ctx mt p =
 			end
 		| _ -> raise_typing_error "Cannot use this type as a value" p
 	in
-	Typeload.load_instance ctx ({tname=loop mt;tpackage=[];tsub=None;tparams=[]},p) true
+	Typeload.load_instance ctx ({tname=loop mt;tpackage=[];tsub=None;tparams=[]},p) ParamSpawnMonos
 
 let unify_type_pattern ctx mt t p =
 	let tcl = get_general_module_type ctx mt p in

+ 149 - 140
src/typing/operators.ml

@@ -392,7 +392,7 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
 		unify ctx e2.etype b p;
 		mk_op e1 e2 b
 	| OpInterval ->
-		let t = Typeload.load_instance ctx (mk_type_path (["std"],"IntIterator"),null_pos) false in
+		let t = Typeload.load_instance ctx (mk_type_path (["std"],"IntIterator"),null_pos) ParamNormal in
 		let e1 = AbstractCast.cast_or_unify_raise ctx tint e1 e1.epos in
 		let e2 = AbstractCast.cast_or_unify_raise ctx tint e2 e2.epos in
 		BinopSpecial (mk (TNew ((match t with TInst (c,[]) -> c | _ -> die "" __LOC__),[],[e1;e2])) t p,false)
@@ -575,7 +575,9 @@ let type_assign ctx e1 e2 with_type p =
 			if not (Common.ignore_error ctx.com) then
 				raise_typing_error "This expression cannot be accessed for writing" p
 			else check_acc acc
-		| AKUsingField _ | AKSafeNav _ ->
+		| AKSafeNav sn ->
+			safe_nav_branch ctx sn (fun () -> check_acc sn.sn_access)
+		| AKUsingField _ ->
 			raise_typing_error "Invalid operation" p
 		| AKExpr { eexpr = TLocal { v_kind = VUser TVOLocalFunction; v_name = name } } ->
 			raise_typing_error ("Cannot access function " ^ name ^ " for writing") p
@@ -668,79 +670,83 @@ let type_assign_op ctx op e1 e2 with_type p =
 		let e = BinopResult.to_texpr vr r_rhs assign in
 		vr#to_texpr e
 	in
-	(match !type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type with
-	| AKNo(_,p) ->
-		(* try abstract operator overloading *)
-		begin try
-			type_non_assign_op ctx op e1 e2 true true with_type p
-		with Not_found ->
-			raise_typing_error "This expression cannot be accessed for writing" p
-		end
-	| AKUsingField _ | AKSafeNav _ ->
-		raise_typing_error "Invalid operation" p
-	| AKExpr e ->
-		let e,vr = process_lhs_expr ctx "lhs" e in
-		let e_rhs = type_binop2 ctx op e e2 true WithType.value p in
-		assign vr e e_rhs
-	| AKField fa ->
-		let vr = new value_reference ctx in
-		let ef = vr#get_expr_part "fh" fa.fa_on in
-		let _,e_rhs = field_rhs op fa.fa_field ef in
-		let e_lhs = FieldAccess.get_field_expr {fa with fa_on = ef} FWrite in
-		assign vr e_lhs e_rhs
-	| AKAccessor fa ->
-		let vr = new value_reference ctx in
-		let ef = vr#get_expr_part "fh" fa.fa_on in
-		let t_lhs,e_rhs = field_rhs op fa.fa_field ef in
-		set vr {fa with fa_on = ef} t_lhs e_rhs []
-	| AKUsingAccessor sea ->
-		let fa = sea.se_access in
-		let ef,vr = process_lhs_expr ctx "fh" sea.se_this in
-		let t_lhs,e_rhs = field_rhs op fa.fa_field ef in
-		set vr sea.se_access t_lhs e_rhs [ef]
-	| AKAccess(a,tl,c,ebase,ekey) ->
-		let cf_get,tf_get,r_get,ekey = AbstractCast.find_array_read_access ctx a tl ekey p in
-		(* bind complex keys to a variable so they do not make it into the output twice *)
-		let save = save_locals ctx in
-		let vr = new value_reference ctx in
-		let maybe_bind_to_temp name e = match Optimizer.make_constant_expression ctx e with
-			| Some e -> e
-			| None -> vr#as_var name e
-		in
-		let ebase = maybe_bind_to_temp "base" ebase in
-		let ekey = maybe_bind_to_temp "key" ekey in
-		let eget = mk_array_get_call ctx (cf_get,tf_get,r_get,ekey) c ebase p in
-		let eget = type_binop2 ctx op eget e2 true WithType.value p in
-		let eget = BinopResult.to_texpr vr eget (fun e -> e) in
-		unify ctx eget.etype r_get p;
-		let cf_set,tf_set,r_set,ekey,eget = AbstractCast.find_array_write_access ctx a tl ekey eget p in
-		let et = type_module_type ctx (TClassDecl c) p in
-		let e = match cf_set.cf_expr,cf_get.cf_expr with
-			| None,None ->
-				let ea = mk (TArray(ebase,ekey)) r_get p in
-				mk (TBinop(OpAssignOp op,ea,type_expr ctx e2 (WithType.with_type r_get))) r_set p
-			| Some _,Some _ ->
-				let ef_set = mk (TField(et,(FStatic(c,cf_set)))) tf_set p in
-				let el = [make_call ctx ef_set [ebase;ekey;eget] r_set p] in
-				begin match el with
-					| [e] -> e
-					| el -> mk (TBlock el) r_set p
-				end
-			| _ ->
-				raise_typing_error "Invalid array access getter/setter combination" p
-		in
-		save();
-		vr#to_texpr	e
-	| AKResolve(sea,name) ->
-		let e,vr = process_lhs_expr ctx "fh" sea.se_this in
-		let t_lhs,r_rhs = field_rhs_by_name op name e WithType.value in
-		let assign e_rhs =
-			let e_name = Texpr.Builder.make_string ctx.t name null_pos in
-			(new call_dispatcher ctx (MCall [e2]) with_type p)#field_call sea.se_access [sea.se_this;e_name;e_rhs] []
-		in
-		let e = BinopResult.to_texpr vr r_rhs assign in
-		vr#to_texpr e
-	)
+	let rec loop acc = match acc with
+		| AKNo(_,p) ->
+			(* try abstract operator overloading *)
+			begin try
+				type_non_assign_op ctx op e1 e2 true true with_type p
+			with Not_found ->
+				raise_typing_error "This expression cannot be accessed for writing" p
+			end
+		| AKSafeNav sn ->
+			safe_nav_branch ctx sn (fun () -> loop sn.sn_access)
+		| AKUsingField _ ->
+			raise_typing_error "Invalid operation" p
+		| AKExpr e ->
+			let e,vr = process_lhs_expr ctx "lhs" e in
+			let e_rhs = type_binop2 ctx op e e2 true WithType.value p in
+			assign vr e e_rhs
+		| AKField fa ->
+			let vr = new value_reference ctx in
+			let ef = vr#get_expr_part "fh" fa.fa_on in
+			let _,e_rhs = field_rhs op fa.fa_field ef in
+			let e_lhs = FieldAccess.get_field_expr {fa with fa_on = ef} FWrite in
+			assign vr e_lhs e_rhs
+		| AKAccessor fa ->
+			let vr = new value_reference ctx in
+			let ef = vr#get_expr_part "fh" fa.fa_on in
+			let t_lhs,e_rhs = field_rhs op fa.fa_field ef in
+			set vr {fa with fa_on = ef} t_lhs e_rhs []
+		| AKUsingAccessor sea ->
+			let fa = sea.se_access in
+			let ef,vr = process_lhs_expr ctx "fh" sea.se_this in
+			let t_lhs,e_rhs = field_rhs op fa.fa_field ef in
+			set vr sea.se_access t_lhs e_rhs [ef]
+		| AKAccess(a,tl,c,ebase,ekey) ->
+			let cf_get,tf_get,r_get,ekey = AbstractCast.find_array_read_access ctx a tl ekey p in
+			(* bind complex keys to a variable so they do not make it into the output twice *)
+			let save = save_locals ctx in
+			let vr = new value_reference ctx in
+			let maybe_bind_to_temp name e = match Optimizer.make_constant_expression ctx e with
+				| Some e -> e
+				| None -> vr#as_var name e
+			in
+			let ebase = maybe_bind_to_temp "base" ebase in
+			let ekey = maybe_bind_to_temp "key" ekey in
+			let eget = mk_array_get_call ctx (cf_get,tf_get,r_get,ekey) c ebase p in
+			let eget = type_binop2 ctx op eget e2 true WithType.value p in
+			let eget = BinopResult.to_texpr vr eget (fun e -> e) in
+			unify ctx eget.etype r_get p;
+			let cf_set,tf_set,r_set,ekey,eget = AbstractCast.find_array_write_access ctx a tl ekey eget p in
+			let et = type_module_type ctx (TClassDecl c) p in
+			let e = match cf_set.cf_expr,cf_get.cf_expr with
+				| None,None ->
+					let ea = mk (TArray(ebase,ekey)) r_get p in
+					mk (TBinop(OpAssignOp op,ea,type_expr ctx e2 (WithType.with_type r_get))) r_set p
+				| Some _,Some _ ->
+					let ef_set = mk (TField(et,(FStatic(c,cf_set)))) tf_set p in
+					let el = [make_call ctx ef_set [ebase;ekey;eget] r_set p] in
+					begin match el with
+						| [e] -> e
+						| el -> mk (TBlock el) r_set p
+					end
+				| _ ->
+					raise_typing_error "Invalid array access getter/setter combination" p
+			in
+			save();
+			vr#to_texpr	e
+		| AKResolve(sea,name) ->
+			let e,vr = process_lhs_expr ctx "fh" sea.se_this in
+			let t_lhs,r_rhs = field_rhs_by_name op name e WithType.value in
+			let assign e_rhs =
+				let e_name = Texpr.Builder.make_string ctx.t name null_pos in
+				(new call_dispatcher ctx (MCall [e2]) with_type p)#field_call sea.se_access [sea.se_this;e_name;e_rhs] []
+			in
+			let e = BinopResult.to_texpr vr r_rhs assign in
+			vr#to_texpr e
+	in
+	loop (!type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type)
+
 
 let type_binop ctx op e1 e2 is_assign_op with_type p =
 	match op with
@@ -854,69 +860,72 @@ let type_unop ctx op flag e with_type p =
 			| None -> vr#to_texpr e
 			| Some e' -> vr#to_texpr_el [e] e'
 		in
-		let access_set = !type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *) in
-		match access_set with
-		| AKNo(acc,p) ->
-			begin try
-				try_abstract_unop_overloads (acc_get ctx acc)
-			with Not_found ->
-				raise_typing_error "This expression cannot be accessed for writing" p
-			end
-		| AKExpr e ->
-			find_overload_or_make e
-		| AKField fa ->
-			let vr = new value_reference ctx in
-			let ef = vr#get_expr_part "fh" fa.fa_on in
-			let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
-			let e,e_out = match access_get with
-			| AKField _ ->
-				let e = FieldAccess.get_field_expr {fa with fa_on = ef} FGet in
-				find_overload_or_make e,None
-			| _ ->
-				let e_set = FieldAccess.get_field_expr {fa with fa_on = ef} FWrite in
-				let e_lhs = acc_get ctx access_get in
-				let e_lhs,e_out = maybe_tempvar_postfix vr e_lhs in
-				let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
-				mk (TBinop(OpAssign,e_set,e_op)) e_set.etype p,e_out
-			in
-			generate vr e_out e
-		| AKAccessor fa ->
-			let vr = new value_reference ctx in
-			let ef = vr#get_expr_part "fh" fa.fa_on in
-			let fa = {fa with fa_on = ef} in
-			let e_lhs,e_out = read_on vr ef fa in
-			let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
-			let dispatcher = new call_dispatcher ctx (MSet None) WithType.value p in
-			let e = dispatcher#accessor_call fa [e_op] [] in
-			generate vr e_out e
-		| AKUsingAccessor sea ->
-			let ef,vr = process_lhs_expr ctx "fh" sea.se_this in
-			let e_lhs,e_out = read_on vr ef sea.se_access in
-			let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
-			let dispatcher = new call_dispatcher ctx (MSet None) WithType.value p in
-			let e = dispatcher#accessor_call sea.se_access [ef;e_op] [] in
-			generate vr e_out e
-		| AKAccess(a,tl,c,ebase,ekey) ->
-			begin try
-				(match op with Increment | Decrement -> () | _ -> raise Not_found);
-				let v_key = alloc_var VGenerated "tmp" ekey.etype ekey.epos in
-				let evar_key = mk (TVar(v_key,Some ekey)) ctx.com.basic.tvoid ekey.epos in
-				let ekey = mk (TLocal v_key) ekey.etype ekey.epos in
-				(* get *)
-				let e_get = mk_array_get_call ctx (AbstractCast.find_array_read_access_raise ctx a tl ekey p) c ebase p in
-				let v_get = alloc_var VGenerated "tmp" e_get.etype e_get.epos in
-				let ev_get = mk (TLocal v_get) v_get.v_type p in
-				let evar_get = mk (TVar(v_get,Some e_get)) ctx.com.basic.tvoid p in
-				(* op *)
-				let e_one = mk (TConst (TInt (Int32.of_int 1))) ctx.com.basic.tint p in
-				let e_op = mk (TBinop((if op = Increment then OpAdd else OpSub),ev_get,e_one)) ev_get.etype p in
-				(* set *)
-				let e_set = mk_array_set_call ctx (AbstractCast.find_array_write_access_raise ctx a tl ekey e_op p) c ebase p in
-				let el = evar_key :: evar_get :: e_set :: (if flag = Postfix then [ev_get] else []) in
-				mk (TBlock el) e_set.etype p
-			with Not_found ->
-				let e = mk_array_get_call ctx (AbstractCast.find_array_read_access ctx a tl ekey p) c ebase p in
+		let rec loop access_set = match access_set with
+			| AKNo(acc,p) ->
+				begin try
+					try_abstract_unop_overloads (acc_get ctx acc)
+				with Not_found ->
+					raise_typing_error "This expression cannot be accessed for writing" p
+				end
+			| AKExpr e ->
 				find_overload_or_make e
-			end
-		| AKUsingField _ | AKResolve _ | AKSafeNav _ ->
-			raise_typing_error "Invalid operation" p
+			| AKField fa ->
+				let vr = new value_reference ctx in
+				let ef = vr#get_expr_part "fh" fa.fa_on in
+				let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
+				let e,e_out = match access_get with
+				| AKField _ ->
+					let e = FieldAccess.get_field_expr {fa with fa_on = ef} FGet in
+					find_overload_or_make e,None
+				| _ ->
+					let e_set = FieldAccess.get_field_expr {fa with fa_on = ef} FWrite in
+					let e_lhs = acc_get ctx access_get in
+					let e_lhs,e_out = maybe_tempvar_postfix vr e_lhs in
+					let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
+					mk (TBinop(OpAssign,e_set,e_op)) e_set.etype p,e_out
+				in
+				generate vr e_out e
+			| AKAccessor fa ->
+				let vr = new value_reference ctx in
+				let ef = vr#get_expr_part "fh" fa.fa_on in
+				let fa = {fa with fa_on = ef} in
+				let e_lhs,e_out = read_on vr ef fa in
+				let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
+				let dispatcher = new call_dispatcher ctx (MSet None) WithType.value p in
+				let e = dispatcher#accessor_call fa [e_op] [] in
+				generate vr e_out e
+			| AKUsingAccessor sea ->
+				let ef,vr = process_lhs_expr ctx "fh" sea.se_this in
+				let e_lhs,e_out = read_on vr ef sea.se_access in
+				let e_op = mk (TBinop(binop,e_lhs,e_one)) e_lhs.etype p in
+				let dispatcher = new call_dispatcher ctx (MSet None) WithType.value p in
+				let e = dispatcher#accessor_call sea.se_access [ef;e_op] [] in
+				generate vr e_out e
+			| AKAccess(a,tl,c,ebase,ekey) ->
+				begin try
+					(match op with Increment | Decrement -> () | _ -> raise Not_found);
+					let v_key = alloc_var VGenerated "tmp" ekey.etype ekey.epos in
+					let evar_key = mk (TVar(v_key,Some ekey)) ctx.com.basic.tvoid ekey.epos in
+					let ekey = mk (TLocal v_key) ekey.etype ekey.epos in
+					(* get *)
+					let e_get = mk_array_get_call ctx (AbstractCast.find_array_read_access_raise ctx a tl ekey p) c ebase p in
+					let v_get = alloc_var VGenerated "tmp" e_get.etype e_get.epos in
+					let ev_get = mk (TLocal v_get) v_get.v_type p in
+					let evar_get = mk (TVar(v_get,Some e_get)) ctx.com.basic.tvoid p in
+					(* op *)
+					let e_one = mk (TConst (TInt (Int32.of_int 1))) ctx.com.basic.tint p in
+					let e_op = mk (TBinop((if op = Increment then OpAdd else OpSub),ev_get,e_one)) ev_get.etype p in
+					(* set *)
+					let e_set = mk_array_set_call ctx (AbstractCast.find_array_write_access_raise ctx a tl ekey e_op p) c ebase p in
+					let el = evar_key :: evar_get :: e_set :: (if flag = Postfix then [ev_get] else []) in
+					mk (TBlock el) e_set.etype p
+				with Not_found ->
+					let e = mk_array_get_call ctx (AbstractCast.find_array_read_access ctx a tl ekey p) c ebase p in
+					find_overload_or_make e
+				end
+			| AKSafeNav sn ->
+				safe_nav_branch ctx sn (fun () -> loop sn.sn_access)
+			| AKUsingField _ | AKResolve _ ->
+				raise_typing_error "Invalid operation" p
+		in
+		loop (!type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *))

+ 148 - 132
src/typing/typeload.ml

@@ -309,140 +309,160 @@ let check_param_constraints ctx t map c p =
 
 		) ctl
 
+type load_instance_param_mode =
+	| ParamNormal
+	| ParamSpawnMonos
+	| ParamCustom of (build_info -> Type.t list option -> Type.t list)
+
+let rec maybe_build_instance ctx t0 get_params p =
+	let rec loop t = match t with
+		| TInst({cl_kind = KGeneric} as c,tl) ->
+			let info = ctx.g.get_build_info ctx (TClassDecl c) p in
+			let tl = match get_params with
+				| ParamNormal | ParamSpawnMonos ->
+					tl
+				| ParamCustom f ->
+					f info (Some tl)
+			in
+			maybe_build_instance ctx (info.build_apply tl) get_params p
+		| TType(td,tl) ->
+			loop (apply_typedef td tl)
+		| TMono {tm_type = Some t} ->
+			loop t
+		| _ ->
+			t0
+	in
+	loop t0
+
+let rec load_params ctx info params p =
+	let is_rest = info.build_kind = BuildGenericBuild && (match info.build_params with [{ttp_name="Rest"}] -> true | _ -> false) in
+	let is_java_rest = ctx.com.platform = Jvm && info.build_extern in
+	let is_rest = is_rest || is_java_rest in
+	let load_param t =
+		match t with
+		| TPExpr e ->
+			let name = (match fst e with
+				| EConst (String(s,_)) -> "S" ^ s
+				| EConst (Int (_,_) as c) -> "I" ^ s_constant c
+				| EConst (Float (_,_) as c) -> "F" ^ s_constant c
+				| EDisplay _ ->
+					ignore(type_expr ctx e WithType.value);
+					"Expr"
+				| _ -> "Expr"
+			) in
+			let c = mk_class ctx.m.curmod ([],name) p (pos e) in
+			c.cl_kind <- KExpr e;
+			TInst (c,[]),pos e
+		| TPType t -> load_complex_type ctx true t,pos t
+	in
+	let checks = DynArray.create () in
+	let rec loop tl1 tl2 is_rest = match tl1,tl2 with
+		| t :: tl1,({ttp_name=name;ttp_type=t2}) :: tl2 ->
+			let t,pt = load_param t in
+			let check_const c =
+				let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in
+				let expects_expression = name = "Const" || Meta.has Meta.Const c.cl_meta in
+				let accepts_expression = name = "Rest" in
+				if is_expression then begin
+					if not expects_expression && not accepts_expression then
+						raise_typing_error "Constant value unexpected here" p
+				end else if expects_expression then
+					raise_typing_error "Type parameter is expected to be a constant value" p
+			in
+			let is_rest = is_rest || name = "Rest" && info.build_kind = BuildGenericBuild in
+			let t = match follow t2 with
+				| TInst ({ cl_kind = KTypeParameter [] } as c, []) when (match info.build_kind with BuildGeneric _ -> false | _ -> true) ->
+					check_const c;
+					t
+				| TInst (c,[]) ->
+					check_const c;
+					DynArray.add checks (t,c,pt);
+					t
+				| _ -> die "" __LOC__
+			in
+			t :: loop tl1 tl2 is_rest
+		| [],[] ->
+			[]
+		| [],[{ttp_name="Rest"}] when info.build_kind = BuildGenericBuild ->
+			[]
+		| [],({ttp_type=t;ttp_default=def}) :: tl ->
+			if is_java_rest then
+				t_dynamic :: loop [] tl is_rest
+			else begin match def with
+				| None ->
+					if ignore_error ctx.com then
+						t :: loop [] tl is_rest
+					else
+						raise_typing_error ("Not enough type parameters for " ^ s_type_path info.build_path) p
+				| Some t ->
+					t :: loop [] tl is_rest
+			end
+		| t :: tl,[] ->
+			let t,pt = load_param t in
+			if is_rest then
+				t :: loop tl [] true
+			else if ignore_error ctx.com then
+				[]
+			else
+				raise_typing_error ("Too many type parameters for " ^ s_type_path info.build_path) pt
+	in
+	let params = loop params info.build_params false in
+	if not is_rest then begin
+		let map t =
+			let t = apply_params info.build_params params t in
+			maybe_build_instance ctx t ParamNormal p;
+		in
+		delay ctx PCheckConstraint (fun () ->
+			DynArray.iter (fun (t,c,p) ->
+				check_param_constraints ctx t map c p
+			) checks
+		);
+	end;
+	params
+
 (* build an instance from a full type *)
-let rec load_instance' ctx (t,p) allow_no_params =
-	let t = try
+and load_instance' ctx (t,p) get_params =
+	try
 		if t.tpackage <> [] || t.tsub <> None then raise Not_found;
 		let pt = lookup_param t.tname ctx.type_params in
 		if t.tparams <> [] then raise_typing_error ("Class type parameter " ^ t.tname ^ " can't have parameters") p;
 		pt
 	with Not_found ->
 		let mt = load_type_def ctx p t in
-		let is_generic,is_generic_build,is_extern = match mt with
-			| TClassDecl {cl_kind = KGeneric} -> true,false,false
-			| TClassDecl {cl_kind = KGenericBuild _} -> false,true,false
-			| TClassDecl c when (has_class_flag c CExtern) -> false,false,true
-			| TTypeDecl td ->
-				begin try
-					let msg = match Meta.get Meta.Deprecated td.t_meta with
-						| _,[EConst(String(s,_)),_],_ -> s
-						| _ -> "This typedef is deprecated in favor of " ^ (s_type (print_context()) td.t_type)
-					in
-					DeprecationCheck.warn_deprecation (create_deprecation_context ctx) msg p
-				with Not_found ->
-						()
-				end;
-				false,false,false
-			| _ -> false,false,false
-		in
-		let types , path , f = ctx.g.do_build_instance ctx mt p in
-		let is_rest = is_generic_build && (match types with [{ttp_name="Rest"}] -> true | _ -> false) in
-		if allow_no_params && t.tparams = [] && not is_rest then begin
-			let monos = Monomorph.spawn_constrained_monos (fun t -> t) types in
-			f (monos)
-		end else if path = ([],"Dynamic") then
-			match t.tparams with
+		let info = ctx.g.get_build_info ctx mt p in
+		if info.build_path = ([],"Dynamic") then match t.tparams with
 			| [] -> t_dynamic
 			| [TPType t] -> TDynamic (Some (load_complex_type ctx true t))
 			| _ -> raise_typing_error "Too many parameters for Dynamic" p
-		else begin
-			let is_java_rest = ctx.com.platform = Jvm && is_extern in
-			let is_rest = is_rest || is_java_rest in
-			let load_param t =
-				match t with
-				| TPExpr e ->
-					let name = (match fst e with
-						| EConst (String(s,_)) -> "S" ^ s
-						| EConst (Int (_,_) as c) -> "I" ^ s_constant c
-						| EConst (Float (_,_) as c) -> "F" ^ s_constant c
-						| EDisplay _ ->
-							ignore(type_expr ctx e WithType.value);
-							"Expr"
-						| _ -> "Expr"
-					) in
-					let c = mk_class ctx.m.curmod ([],name) p (pos e) in
-					c.cl_kind <- KExpr e;
-					TInst (c,[]),pos e
-				| TPType t -> load_complex_type ctx true t,pos t
-			in
-			let checks = DynArray.create () in
-			let rec loop tl1 tl2 is_rest = match tl1,tl2 with
-				| t :: tl1,({ttp_name=name;ttp_type=t2}) :: tl2 ->
-					let t,pt = load_param t in
-					let check_const c =
-						let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in
-						let expects_expression = name = "Const" || Meta.has Meta.Const c.cl_meta in
-						let accepts_expression = name = "Rest" in
-						if is_expression then begin
-							if not expects_expression && not accepts_expression then
-								raise_typing_error "Constant value unexpected here" p
-						end else if expects_expression then
-							raise_typing_error "Type parameter is expected to be a constant value" p
-					in
-					let is_rest = is_rest || name = "Rest" && is_generic_build in
-					let t = match follow t2 with
-						| TInst ({ cl_kind = KTypeParameter [] } as c, []) when not is_generic ->
-							check_const c;
-							t
-						| TInst (c,[]) ->
-							check_const c;
-							DynArray.add checks (t,c,pt);
-							t
-						| _ -> die "" __LOC__
-					in
-					t :: loop tl1 tl2 is_rest
-				| [],[] ->
-					[]
-				| [],[{ttp_name="Rest"}] when is_generic_build ->
-					[]
-				| [],({ttp_type=t;ttp_default=def}) :: tl ->
-					if is_java_rest then
-						t_dynamic :: loop [] tl is_rest
-					else begin match def with
-						| None ->
-							if ignore_error ctx.com then
-								t :: loop [] tl is_rest
-							else
-								raise_typing_error ("Not enough type parameters for " ^ s_type_path path) p
-						| Some t ->
-							t :: loop [] tl is_rest
-					end
-				| t :: tl,[] ->
-					let t,pt = load_param t in
-					if is_rest then
-						t :: loop tl [] true
-					else if ignore_error ctx.com then
-						[]
-					else
-						raise_typing_error ("Too many type parameters for " ^ s_type_path path) pt
-			in
-			let params = loop t.tparams types false in
-			if not is_rest then begin
-				let map t =
-					let t = apply_params types params t in
-					let t = (match follow t with
-						| TInst ({ cl_kind = KGeneric } as c,pl) ->
-							(* if we solve a generic contraint, let's substitute with the actual generic instance before unifying *)
-							let _,_, f = ctx.g.do_build_instance ctx (TClassDecl c) p in
-							f pl
-						| _ -> t
-					) in
-					t
+		else if info.build_params = [] then begin match t.tparams with
+			| [] ->
+				info.build_apply []
+			|  tp :: _ ->
+				let pt = match tp with
+					| TPType(_,p) | TPExpr(_,p) -> p
 				in
-				delay ctx PCheckConstraint (fun () ->
-					DynArray.iter (fun (t,c,p) ->
-						check_param_constraints ctx t map c p
-					) checks
-				);
-			end;
-			f params
+				display_error ctx.com ("Too many type parameters for " ^ s_type_path info.build_path) pt;
+				info.build_apply []
+		end else begin
+			(* TODO: this is currently duplicated, but it seems suspcious anyway... *)
+			let is_rest = info.build_kind = BuildGenericBuild && (match info.build_params with [{ttp_name="Rest"}] -> true | _ -> false) in
+			let tl = if t.tparams = [] && not is_rest then begin match get_params with
+				| ParamNormal ->
+					load_params ctx info t.tparams p
+				| ParamSpawnMonos ->
+					Monomorph.spawn_constrained_monos (fun t -> t) info.build_params
+				| ParamCustom f ->
+					f info None
+			end else
+				load_params ctx info t.tparams p
+			in
+			let t = info.build_apply tl in
+			maybe_build_instance ctx t get_params p
 		end
-	in
-	t
 
-and load_instance ctx ?(allow_display=false) ((_,pn) as tp) allow_no_params =
+and load_instance ctx ?(allow_display=false) ((_,pn) as tp) get_params =
 	try
-		let t = load_instance' ctx tp allow_no_params in
+		let t = load_instance' ctx tp get_params in
 		if allow_display then DisplayEmitter.check_display_type ctx t tp;
 		t
 	with Error { err_message = Module_not_found path } when ctx.macro_depth <= 0 && (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn ->
@@ -456,7 +476,7 @@ and load_complex_type' ctx allow_display (t,p) =
 	match t with
 	| CTParent t -> load_complex_type ctx allow_display t
 	| CTPath { tpackage = ["$"]; tname = "_hx_mono" } -> spawn_monomorph ctx p
-	| CTPath t -> load_instance ~allow_display ctx (t,p) false
+	| CTPath t -> load_instance ~allow_display ctx (t,p) ParamNormal
 	| CTOptional _ -> raise_typing_error "Optional type not allowed here" p
 	| CTNamed _ -> raise_typing_error "Named type not allowed here" p
 	| CTIntersection tl ->
@@ -472,8 +492,7 @@ and load_complex_type' ctx allow_display (t,p) =
 		) tl in
 		let tr = Monomorph.create() in
 		let t = TMono tr in
-		let r = exc_protect ctx (fun r ->
-			r := lazy_processing (fun() -> t);
+		let r = make_lazy ctx t (fun r ->
 			let ta = make_extension_type ctx tl in
 			Monomorph.bind tr ta;
 			ta
@@ -504,7 +523,7 @@ and load_complex_type' ctx allow_display (t,p) =
 			in
 			let il = List.map (fun (t,pn) ->
 				try
-					(load_instance ctx ~allow_display (t,pn) false,pn)
+					(load_instance ctx ~allow_display (t,pn) ParamNormal,pn)
 				with DisplayException(DisplayFields ({fkind = CRTypeHint} as r)) ->
 					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Struct},_) -> true
@@ -514,8 +533,7 @@ and load_complex_type' ctx allow_display (t,p) =
 			) tl in
 			let tr = Monomorph.create() in
 			let t = TMono tr in
-			let r = exc_protect ctx (fun r ->
-				r := lazy_processing (fun() -> t);
+			let r = make_lazy ctx t (fun r ->
 				Monomorph.bind tr (match il with
 					| [i] ->
 						mk_extension i
@@ -767,8 +785,7 @@ let rec type_type_param ctx host path get_params p tp =
 		| None ->
 			None
 		| Some ct ->
-			let r = exc_protect ctx (fun r ->
-				r := lazy_processing (fun() -> t);
+			let r = make_lazy ctx t (fun r ->
 				let t = load_complex_type ctx true ct in
 				begin match host with
 				| TPHType ->
@@ -786,8 +803,7 @@ let rec type_type_param ctx host path get_params p tp =
 	| None ->
 		mk_type_param n t default
 	| Some th ->
-		let r = exc_protect ctx (fun r ->
-			r := lazy_processing (fun() -> t);
+		let r = make_lazy ctx t (fun r ->
 			let ctx = { ctx with type_params = ctx.type_params @ get_params() } in
 			let rec loop th = match fst th with
 				| CTIntersection tl -> List.map (load_complex_type ctx true) tl
@@ -840,8 +856,8 @@ let load_core_class ctx c =
 		| KAbstractImpl a -> mk_type_path a.a_path
 		| _ -> mk_type_path c.cl_path
 	in
-	let t = load_instance ctx2 (tpath,c.cl_pos) true in
-	flush_pass ctx2 PFinal "core_final";
+	let t = load_instance ctx2 (tpath,c.cl_pos) ParamSpawnMonos in
+	flush_pass ctx2 PFinal ("core_final",(fst c.cl_path @ [snd c.cl_path]));
 	match t with
 	| TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) ->
 		ccore

+ 1 - 2
src/typing/typeloadCheck.ml

@@ -530,7 +530,6 @@ module Inheritance = struct
 			| HImplements t -> Some(false,t)
 			| t -> None
 		) herits in
-		let herits = List.filter (ctx.g.do_inherit ctx c p) herits in
 		(* Pass 1: Check and set relations *)
 		let check_herit t is_extends p =
 			let rec check_interfaces_or_delay () =
@@ -594,7 +593,7 @@ module Inheritance = struct
 		let fl = ExtList.List.filter_map (fun (is_extends,(ct,p)) ->
 			try
 				let t = try
-					Typeload.load_instance ~allow_display:true ctx (ct,p) false
+					Typeload.load_instance ~allow_display:true ctx (ct,p) ParamNormal
 				with DisplayException(DisplayFields ({fkind = CRTypeHint} as r)) ->
 					(* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *)
 					if not is_extends && (has_class_flag c CInterface) then raise_fields [] CRImplements r.fsubject;

+ 11 - 28
src/typing/typeloadFields.ml

@@ -360,15 +360,7 @@ let patch_class ctx c fields =
 		List.rev fields
 
 let lazy_display_type ctx f =
-	(* if ctx.is_display_file then begin
-		let r = exc_protect ctx (fun r ->
-			let t = f () in
-			r := lazy_processing (fun () -> t);
-			t
-		) "" in
-		TLazy r
-	end else *)
-		f ()
+	f ()
 
 type enum_abstract_mode =
 	| EAString
@@ -459,14 +451,9 @@ let build_enum_abstract ctx c a fields p =
 
 let resolve_type_import ctx p i =
 	try
-		let res = ctx.m.import_resolution#resolve' i in
-		begin match res.r_kind with
-		| RTypeImport(_,mt) ->
-			let path = t_path mt in
-			snd path :: (List.rev (fst path))
-		| _ ->
-			raise_typing_error "Type path expected" p
-		end
+		let mt,_ = ctx.m.import_resolution#find_type_import i in
+		let path = t_path mt in
+		snd path :: (List.rev (fst path))
 	with Not_found ->
 		[i]
 
@@ -863,11 +850,10 @@ module TypeBinding = struct
 					mk_cast e cf.cf_type e.epos
 			end
 		in
-		let r = exc_protect ~force:false ctx (fun r ->
+		let r = make_lazy ~force:false ctx t (fun r ->
 			(* type constant init fields (issue #1956) *)
 			if not !return_partial_type || (match fst e with EConst _ -> true | _ -> false) then begin
-				r := lazy_processing (fun() -> t);
-				if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.com.is_macro_context then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
+				if (Meta.has (Meta.Custom ":debug.typing") (c.cl_meta @ cf.cf_meta)) then ctx.com.print (Printf.sprintf "Typing field %s.%s\n" (s_type_path c.cl_path) cf.cf_name);
 				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
@@ -942,9 +928,8 @@ module TypeBinding = struct
 	let bind_method ctx cctx fctx cf t args ret e p =
 		let c = cctx.tclass in
 		let bind r =
-			r := lazy_processing (fun() -> t);
 			incr stats.s_methods_typed;
-			if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.com.is_macro_context then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
+			if (Meta.has (Meta.Custom ":debug.typing") (c.cl_meta @ cf.cf_meta)) then ctx.com.print (Printf.sprintf "Typing method %s.%s\n" (s_type_path c.cl_path) cf.cf_name);
 			let fmode = (match cctx.abstract with
 				| Some _ ->
 					if fctx.is_abstract_member then FunMemberAbstract else FunStatic
@@ -986,7 +971,7 @@ module TypeBinding = struct
 			if not !return_partial_type then bind r;
 			t
 		in
-		let r = exc_protect ~force:false ctx maybe_bind "type_fun" in
+		let r = make_lazy ~force:false ctx t maybe_bind "type_fun" in
 		bind_type ctx cctx fctx cf r p
 end
 
@@ -1050,8 +1035,7 @@ let check_abstract (ctx,cctx,fctx) a c cf fd t ret p =
 		fctx.expr_presence_matters <- true;
 	end in
 	let handle_from () =
-		let r = exc_protect ctx (fun r ->
-			r := lazy_processing (fun () -> t);
+		let r = make_lazy ctx t (fun r ->
 			(* the return type of a from-function must be the abstract, not the underlying type *)
 			if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> raise_typing_error_ext (make_error (Unify l) p));
 			match t with
@@ -1091,8 +1075,7 @@ let check_abstract (ctx,cctx,fctx) a c cf fd t ret p =
 		let is_multitype_cast = Meta.has Meta.MultiType a.a_meta && not fctx.is_abstract_member in
 		if is_multitype_cast && not (Meta.has Meta.MultiType cf.cf_meta) then
 			cf.cf_meta <- (Meta.MultiType,[],null_pos) :: cf.cf_meta;
-		let r = exc_protect ctx (fun r ->
-			r := lazy_processing (fun () -> t);
+		let r = make_lazy ctx t (fun r ->
 			let args = if is_multitype_cast then begin
 				let ctor = try
 					PMap.find "_new" c.cl_statics
@@ -1349,7 +1332,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 				| None -> ()
 				| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
 					if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
-						ignore(load_instance ~allow_display:true ctx (tp,p) false);
+						ignore(load_instance ~allow_display:true ctx (tp,p) ParamNormal);
 				| _ -> raise_typing_error "A class constructor can't have a return type" p;
 			end
 		| false,_ ->

+ 2 - 3
src/typing/typeloadFunction.ml

@@ -187,9 +187,8 @@ let add_constructor ctx c force_constructor p =
 		cf.cf_kind <- cfsup.cf_kind;
 		cf.cf_params <- cfsup.cf_params;
 		cf.cf_meta <- List.filter (fun (m,_,_) -> m = Meta.CompilerGenerated) cfsup.cf_meta;
-		let r = exc_protect ctx (fun r ->
-			let t = mk_mono() in
-			r := lazy_processing (fun() -> t);
+		let t = spawn_monomorph ctx p in
+		let r = make_lazy ctx t (fun r ->
 			let ctx = { ctx with
 				curfield = cf;
 				pass = PTypeField;

+ 4 - 6
src/typing/typeloadModule.ml

@@ -583,8 +583,7 @@ module TypeLevel = struct
 					| _ ->
 						()
 				in
-				let r = exc_protect ctx (fun r ->
-					r := lazy_processing (fun() -> tt);
+				let r = make_lazy ctx tt (fun r ->
 					check_rec tt;
 					tt
 				) "typedef_rec_check" in
@@ -610,8 +609,7 @@ module TypeLevel = struct
 			let t = load_complex_type ctx true t in
 			let t = if not (Meta.has Meta.CoreType a.a_meta) then begin
 				if !is_type then begin
-					let r = exc_protect ctx (fun r ->
-						r := lazy_processing (fun() -> t);
+					let r = make_lazy ctx t (fun r ->
 						(try (if from then Type.unify t a.a_this else Type.unify a.a_this t) with Unify_error _ -> raise_typing_error "You can only declare from/to with compatible types" pos);
 						t
 					) "constraint" in
@@ -766,7 +764,7 @@ let type_types_into_module ctx m tdecls p =
 	if ctx.g.std != null_module then begin
 		add_dependency m ctx.g.std;
 		(* this will ensure both String and (indirectly) Array which are basic types which might be referenced *)
-		ignore(load_instance ctx (mk_type_path (["std"],"String"),null_pos) false)
+		ignore(load_instance ctx (mk_type_path (["std"],"String"),null_pos) ParamNormal)
 	end;
 	ModuleLevel.init_type_params ctx decls;
 	(* setup module types *)
@@ -832,7 +830,7 @@ let load_module' ctx g m p =
 let load_module ctx m p =
 	let m2 = load_module' ctx ctx.g m p in
 	add_dependency ~skip_postprocess:true ctx.m.curmod m2;
-	if ctx.pass = PTypeField then flush_pass ctx PConnectField "load_module";
+	if ctx.pass = PTypeField then flush_pass ctx PConnectField ("load_module",fst m @ [snd m]);
 	m2
 
 (* let load_module ctx m p =

+ 0 - 1
src/typing/typeloadParse.ml

@@ -53,7 +53,6 @@ let parse_file_from_lexbuf com file p lexbuf =
 			()
 	end;
 	t();
-	Common.log com ("Parsed " ^ file);
 	parse_result
 
 let parse_file_from_string com file p string =

+ 59 - 55
src/typing/typer.ml

@@ -879,6 +879,7 @@ and type_object_decl ctx fl with_type p =
 		let t, fl = type_fields a.a_fields in
 		mk (TObjectDecl fl) t p
 	| ODKWithClass (c,tl) ->
+		no_abstract_constructor c p;
 		let fa = FieldAccess.get_constructor_access c tl p in
 		let ctor = fa.fa_field in
 		let args = match follow (FieldAccess.get_map_function fa ctor.cf_type) with
@@ -939,10 +940,10 @@ and type_object_decl ctx fl with_type p =
 		mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos
 	)
 
-and type_new ctx path el with_type force_inline p =
-	let path =
-		if snd path <> null_pos then
-			path
+and type_new ctx (path,p_path) el with_type force_inline p =
+	let p_path =
+		if p_path <> null_pos then
+			p_path
 		(*
 			Since macros don't have placed_type_path structure on Haxe side any ENew will have null_pos in `path`.
 			Try to calculate a better pos.
@@ -953,13 +954,16 @@ and type_new ctx path el with_type force_inline p =
 				let pmin = p.pmin + (String.length "new ")
 				and pmax = p1.pmin - 2 (* Additional "1" for an opening bracket *)
 				in
-				fst path, { p with
+				{ p with
 					pmin = if pmin < pmax then pmin else p.pmin;
 					pmax = pmax;
 				}
-			| _ -> fst path, p
+			| _ -> p
 		end
 	in
+	let display_position_in_el () =
+		List.exists (fun e -> DisplayPosition.display_position#enclosed_in (pos e)) el
+	in
 	let unify_constructor_call c fa =
 		try
 			let fcc = unify_field_call ctx fa [] el p fa.fa_inline in
@@ -968,57 +972,58 @@ and type_new ctx path el with_type force_inline p =
 		with Error err ->
 			raise_typing_error_ext err
 	in
-	let display_position_in_el () =
-		List.exists (fun e -> DisplayPosition.display_position#enclosed_in (pos e)) el
-	in
-	let t = if (fst path).tparams <> [] then begin
-		try
-			Typeload.load_instance ctx path false
-		with Error _ as exc when display_position_in_el() ->
-			(* If we fail for some reason, process the arguments in case we want to display them (#7650). *)
-			List.iter (fun e -> ignore(type_expr ctx e WithType.value)) el;
-			raise exc
-	end else try
-		ctx.call_argument_stack <- el :: ctx.call_argument_stack;
-		let t = Typeload.load_instance ctx path true in
-		let t_follow = follow t in
-		ctx.call_argument_stack <- List.tl ctx.call_argument_stack;
-		(* Try to properly build @:generic classes here (issue #2016) *)
-		begin match t_follow with
-			| TInst({cl_kind = KGeneric } as c,tl) -> follow (Generic.build_generic_class ctx c p tl)
-			| _ -> t
-		end
-	with
-	| Generic.Generic_Exception _ ->
-		(* Try to infer generic parameters from the argument list (issue #2044) *)
-		begin match resolve_typedef (Typeload.load_type_def ctx p (fst path)) with
-		| TClassDecl ({cl_constructor = Some cf} as c) ->
-			let monos = Monomorph.spawn_constrained_monos (fun t -> t) c.cl_params in
-			let fa = FieldAccess.get_constructor_access c monos p in
-			no_abstract_constructor c p;
+	let get_params info tl =
+		let tl_or_monos params = match tl with
+			| Some tl ->
+				tl
+			| None ->
+				Monomorph.spawn_constrained_monos (fun t -> t) params
+		in
+		let def c =
+			let tl = tl_or_monos c.cl_params in
+			let fa = FieldAccess.get_constructor_access c tl p in
 			ignore (unify_constructor_call c fa);
-			begin try
-				Generic.build_generic_class ctx c p monos
-			with Generic.Generic_Exception _ as exc ->
-				(* If we have an expected type, just use that (issue #3804) *)
-				begin match with_type with
-					| WithType.WithType(t,_) ->
-						begin match follow t with
-							| TMono _ -> raise exc
-							| t -> t
-						end
+			tl
+		in
+		match info.build_kind with
+		| BuildGeneric c ->
+			let tl = match with_type with
+			| WithType.WithType(t,_) ->
+				(* If we have a matching expected type, use its type parameters. *)
+				begin match follow t with
+					| TInst(c,tl) when c.cl_path = info.build_path ->
+						tl
+					| TInst({cl_kind = KGenericInstance(c,tl)},_) when c.cl_path = info.build_path ->
+						tl
+					| TAbstract(a,tl) when a.a_path = info.build_path ->
+						tl
 					| _ ->
-						raise exc
+						def c
 				end
-			end
-		| mt ->
-			raise_typing_error ((s_type_path (t_infos mt).mt_path) ^ " cannot be constructed") p
-		end
-	| Error _ as exc when display_position_in_el() ->
-		List.iter (fun e -> ignore(type_expr ctx e WithType.value)) el;
+			| _ ->
+				def c
+			in
+			tl
+		| _ ->
+			tl_or_monos info.build_params
+	in
+	let restore =
+		ctx.call_argument_stack <- el :: ctx.call_argument_stack;
+		ctx.with_type_stack <- with_type :: ctx.with_type_stack;
+		(fun () ->
+			ctx.with_type_stack <- List.tl ctx.with_type_stack;
+			ctx.call_argument_stack <- List.tl ctx.call_argument_stack
+		)
+	in
+	let t = try
+		Typeload.load_instance ctx (path,p_path) (ParamCustom get_params)
+	with exc ->
+		restore();
+		(* If we fail for some reason, process the arguments in case we want to display them (#7650). *)
+		if display_position_in_el () then List.iter (fun e -> ignore(type_expr ctx e WithType.value)) el;
 		raise exc
 	in
-	DisplayEmitter.check_display_type ctx t path;
+	DisplayEmitter.check_display_type ctx t (path,p_path);
 	let t = follow t in
 	let build_constructor_call ao c tl =
 		let fa = FieldAccess.get_constructor_access c tl p in
@@ -1796,7 +1801,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 	| EConst (Regexp (r,opt)) ->
 		let str = mk (TConst (TString r)) ctx.t.tstring p in
 		let opt = mk (TConst (TString opt)) ctx.t.tstring p in
-		let t = Typeload.load_instance ctx (mk_type_path (["std"],"EReg"),null_pos) false in
+		let t = Typeload.load_instance ctx (mk_type_path (["std"],"EReg"),null_pos) ParamNormal in
 		mk (TNew ((match t with TInst (c,[]) -> c | _ -> die "" __LOC__),[],[str;opt])) t p
 	| EConst (String(s,SSingleQuotes)) when s <> "" ->
 		type_expr ctx (format_string ctx s p) with_type
@@ -2040,12 +2045,11 @@ let create com macros =
 			type_hints = [];
 			load_only_cached_modules = false;
 			functional_interface_lut = new pmap_lookup;
-			do_inherit = MagicTypes.on_inherit;
 			do_macro = MacroContext.type_macro;
 			do_load_macro = MacroContext.load_macro';
 			do_load_module = TypeloadModule.load_module;
 			do_load_type_def = Typeload.load_type_def;
-			do_build_instance = InstanceBuilder.build_instance;
+			get_build_info = InstanceBuilder.get_build_info;
 			do_format_string = format_string;
 			do_load_core_class = Typeload.load_core_class;
 		};

+ 20 - 2
src/typing/typerBase.ml

@@ -195,8 +195,8 @@ let type_module_type ctx t p =
 	let rec loop t tparams =
 		match t with
 		| TClassDecl {cl_kind = KGenericBuild _} ->
-			let _,_,f = InstanceBuilder.build_instance ctx t p in
-			let t = f (match tparams with None -> [] | Some tl -> tl) in
+			let info = InstanceBuilder.get_build_info ctx t p in
+			let t = info.build_apply (match tparams with None -> [] | Some tl -> tl) in
 			let mt = try
 				module_type_of_type t
 			with Exit ->
@@ -351,3 +351,21 @@ let get_abstract_froms ctx a pl =
 		| _ ->
 			acc
 	) l a.a_from_field
+
+let safe_nav_branch ctx sn f_then =
+	(* generate null-check branching for the safe navigation chain *)
+	let eobj = sn.sn_base in
+	let enull = Builder.make_null eobj.etype sn.sn_pos in
+	let eneq = Builder.binop OpNotEq eobj enull ctx.t.tbool sn.sn_pos in
+	let ethen = f_then () in
+	let tnull = ctx.t.tnull ethen.etype in
+	let ethen = if not (is_nullable ethen.etype) then
+		mk (TCast(ethen,None)) tnull ethen.epos
+	else
+		ethen
+	in
+	let eelse = Builder.make_null tnull sn.sn_pos in
+	let eif = mk (TIf(eneq,ethen,Some eelse)) tnull sn.sn_pos in
+	(match sn.sn_temp_var with
+	| None -> eif
+	| Some evar -> { eif with eexpr = TBlock [evar; eif] })

+ 1 - 1
src/typing/typerDisplay.ml

@@ -310,7 +310,7 @@ let rec handle_signature_display ctx e_ast with_type =
 			in
 			handle_call tl el e1.epos
 		| ENew(tpath,el) ->
-			let t = Abstract.follow_with_forward_ctor (Typeload.load_instance ctx tpath true) in
+			let t = Abstract.follow_with_forward_ctor (Typeload.load_instance ctx tpath ParamSpawnMonos) in
 			handle_call (find_constructor_types t) el (pos tpath)
 		| EArray(e1,e2) ->
 			let e1 = type_expr ctx e1 WithType.value in

+ 3 - 0
std/hl/_std/haxe/NativeStackTrace.hx

@@ -29,6 +29,9 @@ class NativeStackTrace {
 		var count = callStackRaw(null);
 		var arr = new NativeArray(count);
 		callStackRaw(arr);
+		// This will avoid errors when compiling hl/c on unix
+		// See https://github.com/HaxeFoundation/haxe/pull/11382 for long term fix
+		if (arr.length == 0) return arr;
 		return arr.sub(1, arr.length - 1);
 	}
 

+ 0 - 1
tests/misc/eventLoop/build-hl.hxml

@@ -1,3 +1,2 @@
 --main Main
 --dce full
--hl eventLoop.hl

+ 37 - 0
tests/misc/hl/reservedKeywords/Macro.macro.hx

@@ -0,0 +1,37 @@
+import haxe.macro.Context;
+
+using haxe.macro.Tools;
+
+class Macro {
+	public static function build() {
+		var fields = Context.getBuildFields();
+		var keywords = [
+			"auto", "bool", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto",
+			"if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned",
+			"void", "volatile", "while",
+			// Values
+			"NULL", "true", "false",
+			// MS specific
+			"asm", "dllimport2", "dllexport2", "naked2", "thread2",
+			// reserved by HLC
+			"t",
+			// GCC
+			"typeof",
+			// C11
+			"_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local", "_Pragma",
+			"inline", "restrict"
+		];
+
+		var pos = Context.currentPos();
+
+		for (k in keywords)
+			fields.push({
+				pos: pos,
+				name: "_test_" + k,
+				meta: [{pos: pos, name: ":native", params: [macro $v{k}]}],
+				kind: FVar(macro :String, null)
+			});
+
+		return fields;
+	}
+}

+ 4 - 0
tests/misc/hl/reservedKeywords/Main.hx

@@ -0,0 +1,4 @@
+@:build(Macro.build())
+class Main {
+	public static function main() {}
+}

+ 1 - 0
tests/misc/hl/reservedKeywords/compile.hxml

@@ -0,0 +1 @@
+-main Main

+ 6 - 0
tests/misc/projects/Issue11152/Generic.hx

@@ -0,0 +1,6 @@
+@:generic
+class Generic<T> {
+	public function new() {
+		trace(NotMain.notMain);
+	}
+}

+ 3 - 0
tests/misc/projects/Issue11152/Main.hx

@@ -0,0 +1,3 @@
+import Generic;
+
+function main() {}

+ 5 - 0
tests/misc/projects/Issue11152/NotMain.hx

@@ -0,0 +1,5 @@
+class NotMain {
+	static public function notMain() {
+		new Generic<Int>();
+	}
+}

+ 2 - 0
tests/misc/projects/Issue11152/compile.hxml

@@ -0,0 +1,2 @@
+--main Main
+--interp

+ 8 - 0
tests/misc/projects/Issue11342/Main.hx

@@ -0,0 +1,8 @@
+@:structInit
+abstract class Foo {
+	public function new(a:Int, b:Int) {}
+}
+
+function main() {
+	var x:Foo = {a: 1, b: 2};
+}

+ 1 - 0
tests/misc/projects/Issue11342/compile-fail.hxml

@@ -0,0 +1 @@
+--main Main

+ 1 - 0
tests/misc/projects/Issue11342/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+Main.hx:7: characters 14-26 : Foo is abstract and cannot be constructed

+ 7 - 0
tests/misc/projects/Issue11372/Macro.hx

@@ -0,0 +1,7 @@
+@RuntimeMeta([42,0])
+class Macro {
+	public static function init() {
+		var m = haxe.rtti.Meta.getType(Macro);
+		if (m.RuntimeMeta[0][0] != 42) throw "runtime meta failure";
+	}
+}

+ 3 - 0
tests/misc/projects/Issue11372/MainBad.hx

@@ -0,0 +1,3 @@
+function main() {
+	ValuePrinter.printValue(ON);
+}

+ 3 - 0
tests/misc/projects/Issue11372/MainGood.hx

@@ -0,0 +1,3 @@
+function main() {
+	ValuePrinter.printValue(ONE);
+}

+ 11 - 0
tests/misc/projects/Issue11372/MyEnumAbstract.hx

@@ -0,0 +1,11 @@
+enum abstract MyEnumAbstract(Int) {
+	var ONE = 1;
+
+	@:to
+	private function toValue():String {
+		return switch (abstract) {
+			case ONE:
+				"One";
+		}
+	}
+}

+ 16 - 0
tests/misc/projects/Issue11372/ValuePrinter.hx

@@ -0,0 +1,16 @@
+overload extern inline function printValue(input:MyEnumAbstract) {
+	var value:String = input;
+	printValue(value);
+}
+
+overload extern inline function printValue(input:Int) {
+	// Do something.
+}
+
+overload extern inline function printValue(input:String) {
+	// Do something.
+}
+
+overload extern inline function printValue(input:Bool) {
+	// Do something.
+}

+ 2 - 0
tests/misc/projects/Issue11372/compile-bad-fail.hxml

@@ -0,0 +1,2 @@
+--main MainBad
+--interp

+ 2 - 0
tests/misc/projects/Issue11372/compile-bad-fail.hxml.stderr

@@ -0,0 +1,2 @@
+MainBad.hx:2: characters 26-28 : Unknown identifier : ON
+MainBad.hx:2: characters 26-28 : ... For function argument 'input'

+ 2 - 0
tests/misc/projects/Issue11372/compile-good.hxml

@@ -0,0 +1,2 @@
+--main MainGood
+--interp

+ 10 - 0
tests/misc/projects/Issue3864/Base.hx

@@ -0,0 +1,10 @@
+abstract class Base<T = Bool> {
+	var id:String;
+	function new(id:String) {
+		this.id = id;
+	}
+
+	public function getValue() {
+		return id;
+	}
+}

+ 28 - 0
tests/misc/projects/Issue3864/Macro.hx

@@ -0,0 +1,28 @@
+import haxe.macro.Context;
+import haxe.macro.Expr;
+
+using haxe.macro.Tools;
+
+class Macro {
+	static var counter = 0;
+
+	static public function apply() {
+		var local = Context.getLocalType();
+		var expected = Context.getExpectedType();
+		var superClass = switch (expected) {
+			case TInst(c, [t]):
+				var c = c.get();
+				{ pack: c.pack, name: c.name, params: [TPType(t.toComplexType())] };
+			case _:
+				throw false;
+		}
+		var name = 'Test${counter++}';
+		var cls = macro class $name extends $superClass {
+			public function new() {
+				super($v{name} + " extends " + $v{expected.toString()});
+			}
+		}
+		Context.defineType(cls);
+		return TPath({pack: [], name: name});
+	}
+}

+ 14 - 0
tests/misc/projects/Issue3864/Main.hx

@@ -0,0 +1,14 @@
+class Main {
+	public static function main() {
+		var t:Base<String> = new Test();
+		trace(t.getValue());
+		var t:Base<Int> = new Test();
+		trace(t.getValue());
+
+		var t:Base = new Test();
+		trace(t.getValue());
+	}
+}
+
+@:genericBuild(Macro.apply())
+class Test {}

+ 2 - 0
tests/misc/projects/Issue3864/compile.hxml

@@ -0,0 +1,2 @@
+--no-inline
+--run Main

+ 3 - 0
tests/misc/projects/Issue3864/compile.hxml.stdout

@@ -0,0 +1,3 @@
+Main.hx:4: Test0 extends Base<String>
+Main.hx:6: Test1 extends Base<Int>
+Main.hx:9: Test2 extends Base<Bool>

+ 1 - 1
tests/misc/projects/Issue7227/compile-fail.hxml.stderr

@@ -1,3 +1,3 @@
 Main.hx:4: characters 9-81 : error: Struct should be String
 Main.hx:4: characters 9-81 : ... have: Generic<{ url: Struct }>
-Main.hx:4: characters 9-81 : ... want: Generic<{ url: String }>
+Main.hx:4: characters 9-81 : ... want: Generic<{ url: String }>

+ 9 - 0
tests/runci/System.hx

@@ -133,6 +133,15 @@ class System {
 		}
 	}
 
+	static public function addToLIBPATH(path:String):Void {
+		infoMsg('Prepending $path to LD_LIBRARY_PATH.');
+		switch (systemName) {
+			case "Windows": // pass
+			case "Mac", "Linux":
+				Sys.putEnv("LD_LIBRARY_PATH", path + ":" + Sys.getEnv("LD_LIBRARY_PATH"));
+		}
+	}
+
 	static function isLibraryInstalled(library:String):Bool {
 		return new Process("haxelib", ["path", library]).exitCode() == 0;
 	}

+ 46 - 8
tests/runci/targets/Hl.hx

@@ -65,29 +65,67 @@ class Hl {
 
 		runCommand(hlBinary, ["--version"]);
 		addToPATH(hlBuildBinDir);
+		addToLIBPATH(hlBuildBinDir);
 
 		haxelibDev("hashlink", '$hlSrc/other/haxelib/');
 	}
 
+	static function buildAndRunHlc(dir:String, filename:String, ?run) {
+		if (run == null) run = runCommand;
+
+		switch (systemName) {
+			case "Linux" if (isCi()):
+				runCommand("gcc", [
+					"-o", '$dir/$filename.exe',
+					'$dir/$filename.c',
+					'-I$dir',
+					'-I$hlSrc/src',
+					'$hlBuildBinDir/fmt.hdll',
+					'$hlBuildBinDir/ssl.hdll',
+					'$hlBuildBinDir/sqlite.hdll',
+					"-lm",
+					'-L$hlBuildBinDir', "-lhl"
+				]);
+
+				run('$dir/$filename.exe', []);
+
+			case _: // TODO hl/c for mac/windows
+		}
+	}
+
+	static function buildAndRun(hxml:String, target:String, ?args:Array<String>) {
+		if (args == null) args = [];
+
+		runCommand("haxe", [hxml, "-hl", '$target/hl-jit.hl'].concat(args));
+		runCommand(hlBinary, ['$target/hl-jit.hl']);
+
+		runCommand("haxe", [hxml, "-hl", '$target/hlc.c'].concat(args));
+		buildAndRunHlc(target, "hlc");
+	}
+
 	static public function run(args:Array<String>) {
 		getHlDependencies();
 
-		runCommand("haxe", ["compile-hl.hxml"].concat(args));
-		runCommand("haxe", ["compile-hlc.hxml"].concat(args));
-		runCommand(hlBinary, ["bin/unit.hl"]);
+		buildAndRun("compile-hl.hxml", "bin/unit", args);
 
 		changeDirectory(threadsDir);
-		runCommand("haxe", ["build.hxml", "-hl", "export/threads.hl"]);
-		runCommand(hlBinary, ["export/threads.hl"]);
+		buildAndRun("build.hxml", "export/threads");
 
 		changeDirectory(sysDir);
 		runCommand("haxe", ["compile-hl.hxml"].concat(args));
 		runSysTest(hlBinary, ["bin/hl/sys.hl"]);
+		runCommand("haxe", ["compile-hlc.hxml"].concat(args));
+		function dontRun(cmd,?args) {}
+		buildAndRunHlc("bin/hlc/testArguments", "TestArguments", dontRun);
+		buildAndRunHlc("bin/hlc/exitCode", "ExitCode", dontRun);
+		buildAndRunHlc("bin/hlc/utilityProcess", "UtilityProcess", dontRun);
+		buildAndRunHlc("bin/hlc/sys", "sys", (cmd, ?args) -> runSysTest(FileSystem.fullPath(cmd), args));
 
 		changeDirectory(getMiscSubDir("eventLoop"));
-		runCommand("haxe", ["build-hl.hxml"]);
-		// TODO: check output like misc tests do
-		runCommand(hlBinary, ["eventLoop.hl"]);
+		buildAndRun("build-hl.hxml", "bin/eventLoop");
+
+		changeDirectory(getMiscSubDir("hl/reservedKeywords"));
+		buildAndRun("compile.hxml", "bin/reservedKeywords");
 
 		changeDirectory(miscHlDir);
 		runCommand("haxe", ["run.hxml"]);

+ 13 - 0
tests/server/src/cases/issues/Issue9358.hx

@@ -0,0 +1,13 @@
+package cases.issues;
+
+class Issue9358 extends TestCase {
+	function test(_) {
+		vfs.putContent("Main.hx", getTemplate("issues/Issue9358/Main.hx"));
+		vfs.putContent("StateHandler.hx", getTemplate("issues/Issue9358/StateHandler.hx"));
+		var args = ["-cp", "src", "-m", "Main", "-hl", "hl.hl"];
+		runHaxe(args);
+		vfs.touchFile("Main.hx");
+		runHaxe(args);
+		assertSuccess();
+	}
+}

+ 16 - 0
tests/server/test/templates/issues/Issue9358/Main.hx

@@ -0,0 +1,16 @@
+enum StateEnum {
+	State1;
+	State2;
+}
+
+class Main {
+	var stateHandler = new StateHandler<StateEnum>();
+
+	public function new() {
+		stateHandler.state = State1;
+	}
+
+	public static function main() {
+		new Main();
+	}
+}

+ 12 - 0
tests/server/test/templates/issues/Issue9358/StateHandler.hx

@@ -0,0 +1,12 @@
+@:generic
+class StateHandler<S> {
+	public var state(default, set):S;
+
+	public function new() {}
+
+	inline function set_state(state) {
+		trace("State changed in the handler!");
+
+		return this.state = state;
+	}
+}

+ 18 - 0
tests/sys/compile-hlc.hxml

@@ -0,0 +1,18 @@
+compile-each.hxml
+--main Main
+-hl bin/hlc/sys/sys.c
+
+--next
+compile-each.hxml
+--main TestArguments
+-hl bin/hlc/testArguments/TestArguments.c
+
+--next
+compile-each.hxml
+--main ExitCode
+-hl bin/hlc/exitCode/ExitCode.c
+
+--next
+compile-each.hxml
+--main UtilityProcess
+-hl bin/hlc/utilityProcess/UtilityProcess.c

+ 1 - 0
tests/sys/gen_test_res.py

@@ -82,6 +82,7 @@ for data in all_filenames:
         ("../../bin/cs/bin/UtilityProcess-Debug.exe", "bin-cs-debug"),
         ("../../bin/cs/bin/UtilityProcess.exe", "bin-cs"),
         ("../../bin/hl/UtilityProcess.hl", "bin-hl"),
+        ("../../bin/hlc/utilityProcess/UtilityProcess.exe", "bin-hlc"),
         ("../../bin/lua/UtilityProcess.lua", "bin-lua"),
         ("../../bin/java/UtilityProcess-Debug.jar", "bin-java-debug"),
         ("../../bin/java/UtilityProcess.jar", "bin-java"),

+ 5 - 1
tests/sys/src/ExitCode.hx

@@ -12,7 +12,11 @@ class ExitCode {
 	#elseif neko
 		"bin/neko/ExitCode.n";
 	#elseif hl
-		"bin/hl/ExitCode.hl";
+		#if hlc
+			"bin/hlc/exitCode/ExitCode.exe";
+		#else
+			"bin/hl/ExitCode.hl";
+		#end
 	#elseif cpp
 		#if debug
 			"bin/cpp/ExitCode-debug";

+ 5 - 1
tests/sys/src/TestArguments.hx

@@ -72,7 +72,11 @@ class TestArguments extends utest.Test {
 	#elseif neko
 		"bin/neko/TestArguments.n";
 	#elseif hl
-		"bin/hl/TestArguments.hl";
+		#if hlc
+			"bin/hlc/testArguments/TestArguments.exe";
+		#else
+			"bin/hl/TestArguments.hl";
+		#end
 	#elseif cpp
 		#if debug
 			"bin/cpp/TestArguments-debug";

+ 8 - 0
tests/sys/src/TestCommandBase.hx

@@ -37,7 +37,11 @@ class TestCommandBase extends utest.Test {
 			#elseif neko
 				run("neko", [bin].concat(args));
 			#elseif hl
+				#if hlc
+				run(bin, args);
+				#else
 				run("hl", [bin].concat(args));
+				#end
 			#elseif php
 				run(php.Global.defined('PHP_BINARY') ? php.Const.PHP_BINARY : 'php', [bin].concat(args));
 			#elseif lua
@@ -130,7 +134,11 @@ class TestCommandBase extends utest.Test {
 				#elseif neko
 					run("neko", [bin].concat(args));
 				#elseif hl
+					#if hlc
+					run(bin, args);
+					#else
 					run("hl", [bin].concat(args));
+					#end
 				#elseif php
 					run(php.Global.defined('PHP_BINARY') ? php.Const.PHP_BINARY : 'php', [bin].concat(args));
 				#elseif lua

+ 5 - 1
tests/sys/src/TestUnicode.hx

@@ -23,7 +23,11 @@ class TestUnicode extends utest.Test {
 			"bin-cs";
 		#end
 #elseif hl
-		"bin-hl";
+		#if hlc
+			"bin-hlc";
+		#else
+			"bin-hl";
+		#end
 #elseif lua
 		"bin-lua";
 #elseif jvm

+ 13 - 1
tests/sys/src/UtilityProcess.hx

@@ -13,7 +13,11 @@ class UtilityProcess {
 #elseif cs
 		Path.join(["bin", "cs", "bin"]);
 #elseif hl
+	#if hlc
+		Path.join(["bin", "hlc/utilityProcess"]);
+	#else
 		Path.join(["bin", "hl"]);
+	#end
 #elseif lua
 		Path.join(["bin", "lua"]);
 #elseif jvm
@@ -47,7 +51,11 @@ class UtilityProcess {
 			"UtilityProcess.exe";
 		#end
 #elseif hl
+	#if hlc
+		"UtilityProcess.exe";
+	#else
 		"UtilityProcess.hl";
+	#end
 #elseif lua
 		"UtilityProcess.lua";
 #elseif jvm
@@ -100,7 +108,11 @@ class UtilityProcess {
 		#elseif neko
 		new Process("neko", [execFull].concat(args));
 		#elseif hl
-		new Process("hl", [execFull].concat(args));
+			#if hlc
+			new Process(execFull, args);
+			#else
+			new Process("hl", [execFull].concat(args));
+			#end
 		#elseif php
 		new Process(php.Global.defined('PHP_BINARY') ? php.Const.PHP_BINARY : 'php', [execFull].concat(args));
 		#elseif lua

+ 1 - 2
tests/unit/compile-hl.hxml

@@ -1,6 +1,5 @@
 compile-each.hxml
 --main unit.TestMain
--hl bin/unit.hl
 #-D interp
 -D hl-check
--D hl-ver=1.13.0
+-D hl-ver=1.13.0

+ 0 - 5
tests/unit/compile-hlc.hxml

@@ -1,5 +0,0 @@
-compile-each.hxml
---main unit.TestMain
--hl bin/hlc/main.c
--D hl-check
--D hl-ver=1.13.0

+ 102 - 59
tests/unit/src/unit/TestDCE.hx

@@ -1,57 +1,85 @@
 package unit;
 
 private typedef Foo = {
-	var bar(get, null): Bar;
+	var bar(get, null):Bar;
 }
 
 private typedef Bar = {
-	var data: Int;
+	var data:Int;
 }
 
 private class AdrianV {
-	public var bar(get, null): Bar = {data: 100};
+	public var bar(get, null):Bar = {data: 100};
+
 	function get_bar() {
 		return bar;
 	}
 
 	public function new() {}
 
-	static public function testFoo(foo: Foo) {
+	static public function testFoo(foo:Foo) {
 		return foo.bar.data;
 	}
 }
 
+@:generic @:keepSub @:keep
+class GenericKeepSub<T> {}
+
+class ChildOfGenericKeepSub extends GenericKeepSub<String> {}
+
 @:analyzer(no_local_dce)
 class DCEClass {
 	// used statics
-	static function staticUsed() { }
-	@:keep static function staticKeep() { }
+	static function staticUsed() {}
+
+	@:keep static function staticKeep() {}
+
 	static var staticVarUsed = "foo";
 	@:isVar static var staticPropUsed(get, set):Int = 1;
-	static function get_staticPropUsed() return staticPropUsed;
-	static function set_staticPropUsed(i:Int) return 0;
+
+	static function get_staticPropUsed()
+		return staticPropUsed;
+
+	static function set_staticPropUsed(i:Int)
+		return 0;
 
 	// used members
-	function memberUsed() { }
-	@:keep function memberKeep() { }
+	function memberUsed() {}
+
+	@:keep function memberKeep() {}
+
 	var memberVarUsed = 0;
 	@:isVar var memberPropUsed(get, set):Int = 1;
-	function get_memberPropUsed() return memberPropUsed;
-	function set_memberPropUsed(i:Int) return 0;
+
+	function get_memberPropUsed()
+		return memberPropUsed;
+
+	function set_memberPropUsed(i:Int)
+		return 0;
 
 	// unused statics
-	static function staticUnused() { }
+	static function staticUnused() {}
+
 	static var staticVarUnused = "bar";
 	static var staticPropUnused(get, set):Int;
-	static function get_staticPropUnused() return 0;
-	static function set_staticPropUnused(i:Int) return 0;
+
+	static function get_staticPropUnused()
+		return 0;
+
+	static function set_staticPropUnused(i:Int)
+		return 0;
 
 	// unused members
-	function memberUnused() { }
+	function memberUnused() {}
+
 	var memberVarUnused = 1;
 	var memberPropUnused(get, set):Int;
-	function get_memberPropUnused() return 0;
-	function set_memberPropUnused(i:Int) return 0;
+
+	function get_memberPropUnused()
+		return 0;
+
+	function set_memberPropUnused(i:Int)
+		return 0;
 
 	static var c:Array<Dynamic> = [null, unit.UsedReferenced2];
 
@@ -68,7 +96,9 @@ class DCEClass {
 
 		new UsedConstructed();
 
-		try cast (null, UsedReferenced) catch(e:Dynamic) { }
+		try
+			cast(null, UsedReferenced)
+		catch (e:Dynamic) {}
 
 		new UsedAsBaseChild();
 		c.push(null);
@@ -77,7 +107,6 @@ class DCEClass {
 
 @:analyzer(no_local_dce)
 class TestDCE extends Test {
-
 	public function testFields() {
 		var dce = new DCEClass();
 		var c = Type.getClass(dce);
@@ -177,13 +206,17 @@ class TestDCE extends Test {
 		var c = new ThrownWithToString();
 		try {
 			throw c;
-		} catch (_:Dynamic) { }
+		} catch (_:Dynamic) {}
 		#if js
 		if (!js.Browser.supported || js.Browser.navigator.userAgent.indexOf('MSIE 8') == -1)
 		#end
 		hf(ThrownWithToString, "toString");
 	}
 
+	function testIssue6500() {
+		t(Type.resolveClass("unit.ChildOfGenericKeepSub") != null);
+	}
+
 	public function testIssue7259() {
 		var me = new AdrianV();
 		AdrianV.testFoo(me);
@@ -194,28 +227,24 @@ class TestDCE extends Test {
 	public function testIssue10162() {
 		eq('bar', foo(ClassWithBar));
 	}
-	static function foo<T:Class<Dynamic> & { function bar():String; }>(cls:T)
+
+	static function foo<T:Class<Dynamic> & {function bar():String;}>(cls:T)
 		return cls.bar();
 }
 
 class ClassWithBar {
-	static public function bar() return 'bar';
+	static public function bar()
+		return 'bar';
 }
 
 class UsedConstructed {
-	public function new() { }
-}
-
-class UsedReferenced { }
-class UsedReferenced2 { }
-
-class UsedConstructedChild extends UsedConstructed {
-
+	public function new() {}
 }
 
-class UsedReferencedChild extends UsedReferenced {
-
-}
+class UsedReferenced {}
+class UsedReferenced2 {}
+class UsedConstructedChild extends UsedConstructed {}
+class UsedReferencedChild extends UsedReferenced {}
 
 interface UsedInterface {
 	public function usedInterfaceFunc():Void;
@@ -223,26 +252,28 @@ interface UsedInterface {
 }
 
 class UsedThroughInterface implements UsedInterface {
-	public function new() { }
-	public function usedInterfaceFunc():Void { }
-	public function unusedInterfaceFunc():Void { }
-	public function otherFunc() { }
-}
+	public function new() {}
 
-class UsedAsBase { }
-class UsedAsBaseChild extends UsedAsBase {
-	public function new() { }
+	public function usedInterfaceFunc():Void {}
+
+	public function unusedInterfaceFunc():Void {}
+
+	public function otherFunc() {}
 }
 
-class Unused {
+class UsedAsBase {}
 
+class UsedAsBaseChild extends UsedAsBase {
+	public function new() {}
 }
 
-class UnusedChild extends Unused { }
+class Unused {}
+class UnusedChild extends Unused {}
 
 class UnusedImplements implements UsedInterface {
-	public function usedInterfaceFunc():Void { }
-	public function unusedInterfaceFunc():Void { }
+	public function usedInterfaceFunc():Void {}
+
+	public function unusedInterfaceFunc():Void {}
 }
 
 interface PropertyInterface {
@@ -250,37 +281,49 @@ interface PropertyInterface {
 }
 
 class PropertyAccessorsFromBaseClass {
-	public function get_x() return throw "must not set";
-	public function set_x(x:String) return "ok";
+	public function get_x()
+		return throw "must not set";
+
+	public function set_x(x:String)
+		return "ok";
 }
 
 class PropertyAccessorsFromBaseClassChild extends PropertyAccessorsFromBaseClass implements PropertyInterface {
 	public var x(get, set):String;
-	public function new() { }
+
+	public function new() {}
 }
 
 class InterfaceMethodFromBaseClass {
-	public function usedInterfaceFunc():Void { }
-	public function unusedInterfaceFunc():Void { }
+	public function usedInterfaceFunc():Void {}
+
+	public function unusedInterfaceFunc():Void {}
 }
 
 class InterfaceMethodFromBaseClassChild extends InterfaceMethodFromBaseClass implements UsedInterface {
-	public function new() { }
+	public function new() {}
 }
 
 class ThrownWithToString {
-	public function new() { }
-	public function toString() { return "I was thrown today"; }
-}
+	public function new() {}
 
+	public function toString() {
+		return "I was thrown today";
+	}
+}
 
-class RemovePropertyKeepAccessors
-{
+class RemovePropertyKeepAccessors {
 	public function new() {}
 
 	var _test:Float;
+
 	public var test(get, set):Float;
 
-	public function get_test():Float return _test;
-	public function set_test(a:Float):Float { _test = a; return _test; }
+	public function get_test():Float
+		return _test;
+
+	public function set_test(a:Float):Float {
+		_test = a;
+		return _test;
+	}
 }

+ 4 - 0
tests/unit/src/unit/TestExceptions.hx

@@ -253,6 +253,10 @@ class TestExceptions extends Test {
 			var expected = null;
 			var lineShift = 0;
 			for(s in stacks) {
+				// This will avoid errors when compiling hl/c on unix
+				// See https://github.com/HaxeFoundation/haxe/pull/11382 for long term fix
+				#if hlc if (s.length == 0) continue; #end
+
 				if(expected == null) {
 					expected = stackItemData(s[0]);
 				} else {

+ 2 - 1
tests/unit/src/unit/issues/Issue10109.hx

@@ -1,7 +1,8 @@
 package unit.issues;
 
 class Issue10109 extends Test {
-#if hl
+// Disabled for hl/c until https://github.com/HaxeFoundation/haxe/pull/11382 is implemented
+#if (hl && !hlc)
 	@:pure(false)
 	static function foo( o : String ) {
 		return o.length;

+ 24 - 0
tests/unit/src/unit/issues/Issue10528.hx

@@ -0,0 +1,24 @@
+package unit.issues;
+
+@:using(unit.issues.Issue10528.ExtensionA)
+@:generic
+private class Data<T> {
+	public var data:T;
+
+	public function new(data)
+		this.data = data;
+}
+
+private class ExtensionA {
+	public static function defaultUsing<D>(d:D) {
+		return null;
+	}
+}
+
+class Issue10528 extends unit.Test {
+	private function test() {
+		var p = new Data("foo");
+		p.defaultUsing();
+		utest.Assert.pass();
+	}
+}

+ 43 - 0
tests/unit/src/unit/issues/Issue11010.hx

@@ -0,0 +1,43 @@
+package unit.issues;
+
+abstract class ExampleAbstract<T> {
+	public function new(v:T) {
+		this.value = v;
+	}
+
+	public var value(get, set):T;
+
+	abstract public function get_value():T;
+
+	abstract public function set_value(value:T):T;
+}
+
+@:generic
+class ExampleGeneric<T> extends ExampleAbstract<Array<T>> {
+	public function new(v:Array<T>) {
+		super(v);
+	}
+
+	final wrapped:Array<{value:T}> = [];
+
+	public function get_value():Array<T> {
+		return [for (w in wrapped) w.value];
+	}
+
+	public function set_value(value:Array<T>):Array<T> {
+		wrapped.resize(0);
+		for (v in value) {
+			wrapped.push({value: v});
+		}
+		return value;
+	}
+}
+
+class Issue11010 extends Test {
+	#if (!cs && !cppia)
+	function test() {
+		var test = new ExampleGeneric<Int>([1, 2, 3, 4]);
+		utest.Assert.same([1, 2, 3, 4], test.value);
+	}
+	#end
+}

+ 24 - 0
tests/unit/src/unit/issues/Issue11379.hx

@@ -0,0 +1,24 @@
+package unit.issues;
+
+private class SafeNavThing {
+	static public function doSafeNavThings(test:SafeNavThing) {
+		test?.int = 0;
+		test?.int += 1;
+		test?.int++;
+		++test?.int;
+	}
+
+	public var int:Int;
+
+	public function new() {}
+}
+
+class Issue11379 extends Test {
+	function test() {
+		final test = new SafeNavThing();
+		SafeNavThing.doSafeNavThings(test);
+		eq(3, test.int);
+
+		SafeNavThing.doSafeNavThings(null);
+	}
+}

+ 9 - 0
tests/unit/src/unit/issues/Issue11385.hx

@@ -0,0 +1,9 @@
+package unit.issues;
+
+import unit.issues.misc.Issue11385LibraryData;
+
+class Issue11385 extends Test {
+	function test() {
+		eq("Hello World", Issue11385LibraryData.isCommitHash());
+	}
+}

+ 5 - 3
tests/unit/src/unit/issues/Issue2016.hx

@@ -2,7 +2,7 @@ package unit.issues;
 
 @:generic
 private class Gen<T> {
-	public function new(a:T) { }
+	public function new(a:T) {}
 }
 
 private typedef TGen<T> = Gen<T>;
@@ -11,8 +11,10 @@ class Issue2016 extends Test {
 	function test() {
 		var t = new TGen("a");
 		eq("unit.issues._Issue2016.Gen_String", Type.getClassName(Type.getClass(t)));
-
 		var t = new TGen(1);
 		eq("unit.issues._Issue2016.Gen_Int", Type.getClassName(Type.getClass(t)));
+
+		var t = new TGen<String>("a");
+		eq("unit.issues._Issue2016.Gen_String", Type.getClassName(Type.getClass(t)));
 	}
-}
+}

+ 32 - 0
tests/unit/src/unit/issues/Issue5482.hx

@@ -0,0 +1,32 @@
+package unit.issues;
+
+import utest.Assert;
+
+@:generic
+private class Temp<T> {
+	var t:T;
+
+	public function new(t:T) {
+		this.t = t;
+	}
+}
+
+class Issue5482 extends Test {
+	@:generic
+	static function makeTemp<T>(c:T):Temp<T>
+		return new Temp<T>(c);
+
+	@:generic
+	static function makeTempArray<T>(c:T):Array<Temp<T>>
+		return [new Temp<T>(c)];
+
+	function test() {
+		var tt:Temp<Int> = makeTemp(10);
+		var tt1 = makeTemp(10);
+
+		var tt:Array<Temp<Int>> = makeTempArray(10);
+		var tt1 = makeTempArray(10);
+
+		Assert.pass();
+	}
+}

+ 17 - 0
tests/unit/src/unit/issues/Issue5536.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+@:autoBuild(unit.issues.misc.Issue5536Macro.build())
+private class Builder {
+	public function new() {}
+}
+
+@:generic // without @:generic all is correct
+private class A<T> extends Builder {}
+
+private class B extends A<String> {}
+
+class Issue5536 extends Test {
+	function test() {
+		eq("unit.issues._Issue5536.A, unit.issues._Issue5536.B", unit.issues.misc.Issue5536Macro.getBuilt());
+	}
+}

+ 43 - 0
tests/unit/src/unit/issues/Issue6761.hx

@@ -0,0 +1,43 @@
+package unit.issues;
+
+import haxe.Constraints.Constructible;
+import unit.Test;
+
+private class Base<T> {
+	public var value:T;
+}
+
+@:generic
+private class InnerGeneric<T:Constructible<Void->Void>> {
+	public var innerValue:T;
+
+	public function new() {
+		this.innerValue = new T();
+	}
+}
+
+@:generic
+private class OuterGeneric<T:Constructible<Void->Void>> extends Base<InnerGeneric<T>> {
+	public function new() {
+		this.value = new InnerGeneric();
+	}
+}
+
+private class Foo {
+	public function new() {}
+
+	public function getValue() {
+		return "value";
+	}
+}
+
+class Issue6761 extends Test {
+	function test() {
+		var a = new OuterGeneric<Foo>();
+		var b:Base<InnerGeneric<Foo>> = null;
+		b = a;
+		if (a.value != null) {
+			eq("value", a.value.innerValue.getValue());
+		}
+	}
+}

+ 19 - 0
tests/unit/src/unit/issues/Issue7574.hx

@@ -0,0 +1,19 @@
+package unit.issues;
+
+@:generic
+private class Foo<@:const FOO:Dynamic> {
+	var foo = cast(FOO, String);
+
+	public function new() {}
+
+	public function test() {
+		return foo;
+	}
+}
+
+class Issue7574 extends unit.Test {
+	function test() {
+		eq("X", new Foo<"X">().test());
+		eq("Y", new Foo<"Y">().test());
+	}
+}

+ 21 - 0
tests/unit/src/unit/issues/Issue9395.hx

@@ -0,0 +1,21 @@
+package unit.issues;
+
+private class DisposeThing {
+	@:generic
+	static public function d<T:{function dispose():String;}>(o:T):() -> String {
+		return o.dispose;
+	}
+
+	public function new() {}
+
+	public function dispose() {
+		return "Disposing";
+	}
+}
+
+class Issue9395 extends Test {
+	function test() {
+		var dispose = DisposeThing.d(new DisposeThing());
+		eq("Disposing", dispose());
+	}
+}

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

@@ -1,7 +1,7 @@
 package unit.issues;
 
 class Issue9678 extends unit.Test {
-	#if !cpp
+	#if (!cpp && !hlc)
 	function test() {
 		var called = 0;
 		function returnVoid() {

+ 7 - 0
tests/unit/src/unit/issues/misc/Issue11385LibraryData.hx

@@ -0,0 +1,7 @@
+package unit.issues.misc;
+
+class Issue11385LibraryData {}
+
+function isCommitHash() {
+	return "Hello World";
+}

+ 17 - 0
tests/unit/src/unit/issues/misc/Issue5536Macro.hx

@@ -0,0 +1,17 @@
+package unit.issues.misc;
+
+import haxe.macro.Expr;
+
+class Issue5536Macro {
+	static var built = [];
+
+	static macro function build():Array<Field> {
+		built.push(haxe.macro.Context.getLocalClass().toString());
+		return null;
+	}
+
+	static public macro function getBuilt() {
+		built.sort(Reflect.compare);
+		return macro $v{built.join(", ")};
+	}
+}