Browse Source

Instance builder cleanup (#11376)

* change return of build_instance to record

* also rename

* also seperate

* also bring back typedef deprecation check

* alsp keep special cases in the right place

* mess around

* avoid some work if we need no params anyway

* make @:generic inference work again

* remove Generic_Exception

* push expected type before loading instance

closes #3864

* expand generic types on field call candidate when expanding generic function

closes #5482

* build generic parents as well

closes #6761

* inherit `@:autoBuild` to generic instance

closes #5536

* also inherit @:keepSub while we're at it

closes #6500

* deal with KExpr in generic classes properly

closes #7574

* don't inherit cf_expr_unoptimized to generic instances

closes #9358

* reroute FClosure in map_expr_type

closes #9395

* inherit cl_using to generic instances

closes #10528

* set inherited flags on generic instance fields at the right time

closes #11010

* I really don't care

* wild guess

* avoid the follow change
Simon Krajewski 1 year ago
parent
commit
128261aafd
40 changed files with 867 additions and 404 deletions
  1. 0 2
      src/compiler/compiler.ml
  2. 1 1
      src/context/display/displayTexpr.ml
  3. 23 1
      src/context/typecore.ml
  4. 5 5
      src/core/inheritDoc.ml
  5. 4 1
      src/core/tFunctions.ml
  6. 1 1
      src/core/tType.ml
  7. 13 0
      src/core/texpr.ml
  8. 6 6
      src/filters/exceptions.ml
  9. 1 1
      src/optimization/inline.ml
  10. 152 116
      src/typing/generic.ml
  11. 24 16
      src/typing/instanceBuilder.ml
  12. 6 6
      src/typing/macroContext.ml
  13. 1 1
      src/typing/matcher/exprToPattern.ml
  14. 1 1
      src/typing/operators.ml
  15. 143 123
      src/typing/typeload.ml
  16. 1 1
      src/typing/typeloadCheck.ml
  17. 1 1
      src/typing/typeloadFields.ml
  18. 1 1
      src/typing/typeloadModule.ml
  19. 58 54
      src/typing/typer.ml
  20. 2 2
      src/typing/typerBase.ml
  21. 1 1
      src/typing/typerDisplay.ml
  22. 10 0
      tests/misc/projects/Issue3864/Base.hx
  23. 28 0
      tests/misc/projects/Issue3864/Macro.hx
  24. 14 0
      tests/misc/projects/Issue3864/Main.hx
  25. 2 0
      tests/misc/projects/Issue3864/compile.hxml
  26. 3 0
      tests/misc/projects/Issue3864/compile.hxml.stdout
  27. 1 1
      tests/misc/projects/Issue7227/compile-fail.hxml.stderr
  28. 13 0
      tests/server/src/cases/issues/Issue9358.hx
  29. 16 0
      tests/server/test/templates/issues/Issue9358/Main.hx
  30. 12 0
      tests/server/test/templates/issues/Issue9358/StateHandler.hx
  31. 102 59
      tests/unit/src/unit/TestDCE.hx
  32. 24 0
      tests/unit/src/unit/issues/Issue10528.hx
  33. 43 0
      tests/unit/src/unit/issues/Issue11010.hx
  34. 5 3
      tests/unit/src/unit/issues/Issue2016.hx
  35. 32 0
      tests/unit/src/unit/issues/Issue5482.hx
  36. 17 0
      tests/unit/src/unit/issues/Issue5536.hx
  37. 43 0
      tests/unit/src/unit/issues/Issue6761.hx
  38. 19 0
      tests/unit/src/unit/issues/Issue7574.hx
  39. 21 0
      tests/unit/src/unit/issues/Issue9395.hx
  40. 17 0
      tests/unit/src/unit/issues/misc/Issue5536Macro.hx

+ 0 - 2
src/compiler/compiler.ml

@@ -407,8 +407,6 @@ with
 		end
 		end
 	| Error.Error err ->
 	| Error.Error err ->
 		error_ext ctx err
 		error_ext ctx err
-	| Generic.Generic_Exception(m,p) ->
-		error ctx m p
 	| Arg.Bad msg ->
 	| Arg.Bad msg ->
 		error ctx ("Error: " ^ msg) null_pos
 		error ctx ("Error: " ^ msg) null_pos
 	| Failure msg when not Helper.is_debug_run ->
 	| Failure msg when not Helper.is_debug_run ->

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

@@ -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);
 		ignore(Typeload.type_type_params ctx TPHType c.cl_path (fun() -> c.cl_params) null_pos sc.d_params);
 		List.iter (function
 		List.iter (function
 			| (HExtends(ct,p) | HImplements(ct,p)) when display_position#enclosed_in p ->
 			| (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;
 		) sc.d_flags;

+ 23 - 1
src/context/typecore.ml

@@ -72,6 +72,20 @@ type delay = {
 	delay_functions : (unit -> unit) list;
 	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 = {
 type typer_globals = {
 	mutable delayed : delay list;
 	mutable delayed : delay list;
 	mutable debug_delayed : (typer_pass * ((unit -> unit) * (string * string list) * typer) list) list;
 	mutable debug_delayed : (typer_pass * ((unit -> unit) * (string * string list) * typer) list) list;
@@ -94,7 +108,7 @@ type typer_globals = {
 	do_load_macro : typer -> bool -> path -> string -> pos -> ((string * bool * t) list * t * tclass * Type.tclass_field);
 	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_module : typer -> path -> pos -> module_def;
 	do_load_type_def : typer -> pos -> type_path -> module_type;
 	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_format_string : typer -> string -> pos -> Ast.expr;
 	do_load_core_class : typer -> tclass -> tclass;
 	do_load_core_class : typer -> tclass -> tclass;
 }
 }
@@ -200,6 +214,14 @@ type dot_path_part = {
 	pos : pos
 	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 Forbid_package of (string * path * pos) * pos list * string
 
 
 exception WithTypeError of error
 exception WithTypeError of error

+ 5 - 5
src/core/inheritDoc.ml

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

+ 4 - 1
src/core/tFunctions.ml

@@ -506,7 +506,10 @@ let rec follow t =
 		| Some t -> follow t
 		| Some t -> follow t
 		| _ -> t)
 		| _ -> t)
 	| TLazy f ->
 	| TLazy f ->
-		follow (lazy_type f)
+		(match !f with
+		| LAvailable t -> follow t
+		| _ -> follow (lazy_type f)
+		)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		follow (apply_typedef t tl)
 		follow (apply_typedef t tl)
 	| TAbstract({a_path = [],"Null"},[t]) ->
 	| TAbstract({a_path = [],"Null"},[t]) ->

+ 1 - 1
src/core/tType.ml

@@ -461,7 +461,7 @@ type flag_tclass_field =
 
 
 (* Order has to match declaration for printing*)
 (* Order has to match declaration for printing*)
 let flag_tclass_field_names = [
 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 =
 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 }
 		{ e with eexpr = TEnumParameter (f e1,ef,i); etype = ft e.etype }
 	| TEnumIndex e1 ->
 	| TEnumIndex e1 ->
 		{ e with eexpr = TEnumIndex (f e1); etype = ft e.etype }
 		{ 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) ->
 	| TField (e1,v) ->
 		let e1 = f e1 in
 		let e1 = f e1 in
 		let v = try
 		let v = try

+ 6 - 6
src/filters/exceptions.ml

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

+ 1 - 1
src/optimization/inline.ml

@@ -866,7 +866,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 tl = arg_types params f.tf_args in
 	let e = state#finalize e tl tret has_params map_type p in
 	let e = state#finalize e tl tret has_params map_type p in
 	if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin
 	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"
 		print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s"
 			cf.cf_name
 			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))
 			(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))

+ 152 - 116
src/typing/generic.ml

@@ -6,17 +6,16 @@ open Type
 open Typecore
 open Typecore
 open Error
 open Error
 
 
-exception Generic_Exception of string * pos
-
 type generic_context = {
 type generic_context = {
 	ctx : typer;
 	ctx : typer;
 	subst : (t * (t * texpr option)) list;
 	subst : (t * (t * texpr option)) list;
 	name : string;
 	name : string;
 	p : pos;
 	p : pos;
 	mutable mg : module_def option;
 	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 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 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
 	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 ->
 					| KExpr e ->
 						let name = ident_safe (Ast.Printer.s_expr e) in
 						let name = ident_safe (Ast.Printer.s_expr e) in
 						let e = type_expr {ctx with locals = PMap.empty} e WithType.value 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))
 						((ident_safe (s_type_path_underscore c.cl_path)) ^ (loop_tl top tl),(t,None))
 				end
 				end
@@ -62,7 +61,7 @@ let make_generic ctx ps pt p =
 	in
 	in
 	let rec loop acc_name acc_subst ttpl tl = match ttpl,tl with
 	let rec loop acc_name acc_subst ttpl tl = match ttpl,tl with
 		| ttp :: ttpl,t :: tl ->
 		| 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
 			loop (name :: acc_name) ((follow ttp.ttp_type,t) :: acc_subst) ttpl tl
 		| [],[] ->
 		| [],[] ->
 			let name = String.concat "_" (List.rev acc_name) in
 			let name = String.concat "_" (List.rev acc_name) in
@@ -77,22 +76,33 @@ let make_generic ctx ps pt p =
 		name = name;
 		name = name;
 		p = p;
 		p = p;
 		mg = None;
 		mg = None;
+		generic_debug = debug;
 	}
 	}
 
 
-let rec generic_substitute_type gctx t =
+let rec generic_substitute_type' gctx allow_expr t =
 	match t with
 	match t with
 	| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
 	| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
 		(* maybe loop, or generate cascading generics *)
 		(* 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 | _ -> ());
 		(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
 		t
 		t
 	| _ ->
 	| _ ->
 		try
 		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 ->
 		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 generic_substitute_expr gctx e =
 	let vars = Hashtbl.create 0 in
 	let vars = Hashtbl.create 0 in
@@ -108,8 +118,8 @@ let generic_substitute_expr gctx e =
 	let rec build_expr e =
 	let rec build_expr e =
 		let e = match e.eexpr with
 		let e = match e.eexpr with
 		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
 		| 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
 			begin match follow t with
 			| TInst(c',_) when c == c' ->
 			| TInst(c',_) when c == c' ->
 				(* The @:generic class wasn't expanded, let's not recurse to avoid infinite loop (#6430) *)
 				(* 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 pack = fst c.cl_path in
 	let name = (snd c.cl_path) ^ "_" ^ cf.cf_name ^ "_" ^ gctx.name in
 	let name = (snd c.cl_path) ^ "_" ^ cf.cf_name ^ "_" ^ gctx.name in
 	try
 	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
 		match t with
 		| TInst(cg,_) -> cg
 		| TInst(cg,_) -> cg
 		| _ -> raise_typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
 		| _ -> raise_typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
@@ -213,6 +223,14 @@ let set_type_parameter_dependencies mg tl =
 	in
 	in
 	List.iter loop tl
 	List.iter loop 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 rec build_generic_class ctx c p tl =
 let rec build_generic_class ctx c p tl =
 	let pack = fst c.cl_path in
 	let pack = fst c.cl_path in
 	let recurse = ref false in
 	let recurse = ref false in
@@ -233,15 +251,29 @@ let rec build_generic_class ctx c p tl =
 	if !recurse || not (ctx.com.display.dms_full_typing) then begin
 	if !recurse || not (ctx.com.display.dms_full_typing) then begin
 		TInst (c,tl) (* build a normal instance *)
 		TInst (c,tl) (* build a normal instance *)
 	end else begin
 	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
 	let name = (snd c.cl_path) ^ "_" ^ gctx.name in
 	try
 	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
 		match t with
 		| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
 		| 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
 		| _ -> 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) ->
 	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
 		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 *)
 		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		let mg = {
 		let mg = {
 			m_id = alloc_mid();
 			m_id = alloc_mid();
@@ -257,11 +289,12 @@ let rec build_generic_class ctx c p tl =
 			| Final
 			| Final
 			| Hack
 			| Hack
 			| Internal
 			| Internal
-			| Keep
+			| Keep | KeepSub
 			| NoClosure | NullSafety
 			| NoClosure | NullSafety
 			| Pure
 			| Pure
 			| Struct | StructInit
 			| Struct | StructInit
-			| Using ->
+			| Using
+			| AutoBuild ->
 				true
 				true
 			| _ ->
 			| _ ->
 				false
 				false
@@ -282,8 +315,7 @@ let rec build_generic_class ctx c p tl =
 				| _ -> die "" __LOC__
 				| _ -> die "" __LOC__
 			) ([],[]) cf_old.cf_params in
 			) ([],[]) cf_old.cf_params in
 			let gctx = {gctx with subst = param_subst @ gctx.subst} 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. *)
 			(* Type parameter constraints are substituted here. *)
 			cf_new.cf_params <- List.rev_map (fun tp -> match follow tp.ttp_type with
 			cf_new.cf_params <- List.rev_map (fun tp -> match follow tp.ttp_type with
 				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
 				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
@@ -293,8 +325,13 @@ let rec build_generic_class ctx c p tl =
 				| _ -> die "" __LOC__
 				| _ -> die "" __LOC__
 			) params;
 			) params;
 			let f () =
 			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
 				let t = generic_substitute_type gctx cf_old.cf_type in
-				ignore (follow t);
 				begin try (match cf_old.cf_expr with
 				begin try (match cf_old.cf_expr with
 					| None ->
 					| None ->
 						begin match cf_old.cf_kind with
 						begin match cf_old.cf_kind with
@@ -310,6 +347,7 @@ let rec build_generic_class ctx c p tl =
 				) with Unify_error l ->
 				) with Unify_error l ->
 					raise_typing_error (error_msg (Unify l)) cf_new.cf_pos
 					raise_typing_error (error_msg (Unify l)) cf_new.cf_pos
 				end;
 				end;
+				if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass_field "  " cf_new));
 				t
 				t
 			in
 			in
 			let r = exc_protect ctx (fun r ->
 			let r = exc_protect ctx (fun r ->
@@ -331,14 +369,9 @@ let rec build_generic_class ctx c p tl =
 		cg.cl_super <- (match c.cl_super with
 		cg.cl_super <- (match c.cl_super with
 			| None -> None
 			| None -> None
 			| Some (cs,pl) ->
 			| 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;
 		TypeloadFunction.add_constructor ctx cg false p;
 		cg.cl_kind <- KGenericInstance (c,tl);
 		cg.cl_kind <- KGenericInstance (c,tl);
@@ -365,6 +398,8 @@ let rec build_generic_class ctx c p tl =
 			let n = get_short_name () in
 			let n = get_short_name () in
 			cg.cl_meta <- (Meta.Native,[EConst(String (n,SDoubleQuotes)),p],null_pos) :: cg.cl_meta;
 			cg.cl_meta <- (Meta.Native,[EConst(String (n,SDoubleQuotes)),p],null_pos) :: cg.cl_meta;
 		end;
 		end;
+		cg.cl_using <- c.cl_using;
+		if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass "  " cg));
 		TInst (cg,[])
 		TInst (cg,[])
 	end
 	end
 
 
@@ -378,8 +413,11 @@ let type_generic_function ctx fa fcc with_type p =
 	let cf = fcc.fc_field in
 	let cf = fcc.fc_field in
 	if cf.cf_params = [] then raise_typing_error "Function has no type parameters and cannot be generic" p;
 	if cf.cf_params = [] then raise_typing_error "Function has no type parameters and cannot be generic" p;
 	begin match with_type with
 	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;
 	end;
 	let monos = fcc.fc_monos in
 	let monos = fcc.fc_monos in
 	List.iter (fun t -> match follow t with
 	List.iter (fun t -> match follow t with
@@ -387,102 +425,100 @@ let type_generic_function ctx fa fcc with_type p =
 		| _ -> ()
 		| _ -> ()
 	) monos;
 	) monos;
 	let el = fcc.fc_args in
 	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
 		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
 			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_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
 					c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
 					c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
 					finalize_field c cf2;
 					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
 			end else begin
 				set_type_parameter_dependencies c.cl_module monos;
 				set_type_parameter_dependencies c.cl_module monos;
 				let cf2 = mk_cf2 name in
 				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;
 				finalize_field c cf2;
 				{fa with fa_field = cf2}
 				{fa with fa_field = cf2}
 			end
 			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
 Typecore.type_generic_function_ref := type_generic_function

+ 24 - 16
src/typing/instanceBuilder.ml

@@ -68,15 +68,15 @@ let build_macro_build ctx c pl cfl p =
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* API EVENTS *)
 (* API EVENTS *)
 
 
-let build_instance ctx mtype p =
+let get_build_info ctx mtype p =
 	match mtype with
 	match mtype with
 	| TClassDecl c ->
 	| TClassDecl c ->
 		if ctx.pass > PBuildClass then ignore(c.cl_build());
 		if ctx.pass > PBuildClass then ignore(c.cl_build());
-		let build f s =
+		let build f s tl =
 			let r = exc_protect ctx (fun r ->
 			let r = exc_protect ctx (fun r ->
 				let t = spawn_monomorph ctx p in
 				let t = spawn_monomorph ctx p in
 				r := lazy_processing (fun() -> t);
 				r := lazy_processing (fun() -> t);
-				let tf = (f()) in
+				let tf = f tl in
 				unify_raise tf t p;
 				unify_raise tf t p;
 				link_dynamic t tf;
 				link_dynamic t tf;
 				(match tf with
 				(match tf with
@@ -88,21 +88,29 @@ let build_instance ctx mtype p =
 			) s in
 			) s in
 			TLazy r
 			TLazy r
 		in
 		in
-		let ft = (fun pl ->
-			match c.cl_kind with
+		let kind,f = match c.cl_kind with
 			| KGeneric ->
 			| 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 ->
 			| 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 ->
 	| 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 ->
 	| 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))

+ 6 - 6
src/typing/macroContext.ml

@@ -340,7 +340,7 @@ let make_macro_api ctx mctx p =
 						mk_type_path path
 						mk_type_path path
 				in
 				in
 				try
 				try
-					let m = Some (Typeload.load_instance ctx (tp,p) true) in
+					let m = Some (Typeload.load_instance ctx (tp,p) ParamSpawnMonos) in
 					m
 					m
 				with Error { err_message = Module_not_found _; err_pos = p2 } when p == p2 ->
 				with Error { err_message = Module_not_found _; err_pos = p2 } when p == p2 ->
 					None
 					None
@@ -478,7 +478,7 @@ let make_macro_api ctx mctx p =
 		MacroApi.define_type = (fun v mdep ->
 		MacroApi.define_type = (fun v mdep ->
 			let cttype = mk_type_path ~sub:"TypeDefinition" (["haxe";"macro"],"Expr") in
 			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 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 f () = Interp.decode_type_def v in
 			let m, tdef, pos = safe_decode ctx.com v "TypeDefinition" ttype p f in
 			let m, tdef, pos = safe_decode ctx.com v "TypeDefinition" ttype p f in
 			let has_native_meta = match tdef with
 			let has_native_meta = match tdef with
@@ -846,7 +846,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	in
 	in
 	let mpos = mfield.cf_pos in
 	let mpos = mfield.cf_pos in
 	let ctexpr = mk_type_path (["haxe";"macro"],"Expr") 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
 	(match mode with
 	| MDisplay ->
 	| MDisplay ->
 		raise Exit (* We don't have to actually call the macro. *)
 		raise Exit (* We don't have to actually call the macro. *)
@@ -855,18 +855,18 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	| MBuild ->
 	| MBuild ->
 		let params = [TPType (CTPath (mk_type_path ~sub:"Field" (["haxe";"macro"],"Expr")),null_pos)] in
 		let params = [TPType (CTPath (mk_type_path ~sub:"Field" (["haxe";"macro"],"Expr")),null_pos)] in
 		let ctfields = mk_type_path ~params ([],"Array") 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
 		unify mctx mret tfields mpos
 	| MMacroType ->
 	| MMacroType ->
 		let cttype = mk_type_path (["haxe";"macro"],"Type") in
 		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
 		try
 			unify_raise mret ttype mpos;
 			unify_raise mret ttype mpos;
 			(* TODO: enable this again in the future *)
 			(* TODO: enable this again in the future *)
 			(* warning ctx WDeprecated "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *)
 			(* warning ctx WDeprecated "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *)
 		with Error { err_message = Unify _ } ->
 		with Error { err_message = Unify _ } ->
 			let cttype = mk_type_path ~sub:"ComplexType" (["haxe";"macro"],"Expr") in
 			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;
 			unify_raise mret ttype mpos;
 	);
 	);
 	(*
 	(*

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

@@ -58,7 +58,7 @@ let get_general_module_type ctx mt p =
 			end
 			end
 		| _ -> raise_typing_error "Cannot use this type as a value" p
 		| _ -> raise_typing_error "Cannot use this type as a value" p
 	in
 	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 unify_type_pattern ctx mt t p =
 	let tcl = get_general_module_type ctx mt p in
 	let tcl = get_general_module_type ctx mt p in

+ 1 - 1
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;
 		unify ctx e2.etype b p;
 		mk_op e1 e2 b
 		mk_op e1 e2 b
 	| OpInterval ->
 	| 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 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
 		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)
 		BinopSpecial (mk (TNew ((match t with TInst (c,[]) -> c | _ -> die "" __LOC__),[],[e1;e2])) t p,false)

+ 143 - 123
src/typing/typeload.ml

@@ -309,140 +309,160 @@ let check_param_constraints ctx t map c p =
 
 
 		) ctl
 		) 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 = Java && 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 *)
 (* 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;
 		if t.tpackage <> [] || t.tsub <> None then raise Not_found;
 		let pt = lookup_param t.tname ctx.type_params in
 		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;
 		if t.tparams <> [] then raise_typing_error ("Class type parameter " ^ t.tname ^ " can't have parameters") p;
 		pt
 		pt
 	with Not_found ->
 	with Not_found ->
 		let mt = load_type_def ctx p t in
 		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
 			| [] -> t_dynamic
 			| [TPType t] -> TDynamic (Some (load_complex_type ctx true t))
 			| [TPType t] -> TDynamic (Some (load_complex_type ctx true t))
 			| _ -> raise_typing_error "Too many parameters for Dynamic" p
 			| _ -> raise_typing_error "Too many parameters for Dynamic" p
-		else begin
-			let is_java_rest = ctx.com.platform = Java && 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
 				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
 		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
 	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;
 		if allow_display then DisplayEmitter.check_display_type ctx t tp;
 		t
 		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 ->
 	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
 	match t with
 	| CTParent t -> load_complex_type ctx allow_display t
 	| CTParent t -> load_complex_type ctx allow_display t
 	| CTPath { tpackage = ["$"]; tname = "_hx_mono" } -> spawn_monomorph ctx p
 	| 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
 	| CTOptional _ -> raise_typing_error "Optional type not allowed here" p
 	| CTNamed _ -> raise_typing_error "Named type not allowed here" p
 	| CTNamed _ -> raise_typing_error "Named type not allowed here" p
 	| CTIntersection tl ->
 	| CTIntersection tl ->
@@ -504,7 +524,7 @@ and load_complex_type' ctx allow_display (t,p) =
 			in
 			in
 			let il = List.map (fun (t,pn) ->
 			let il = List.map (fun (t,pn) ->
 				try
 				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)) ->
 				with DisplayException(DisplayFields ({fkind = CRTypeHint} as r)) ->
 					let l = List.filter (fun item -> match item.ci_kind with
 					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Struct},_) -> true
 						| ITType({kind = Struct},_) -> true
@@ -840,7 +860,7 @@ let load_core_class ctx c =
 		| KAbstractImpl a -> mk_type_path a.a_path
 		| KAbstractImpl a -> mk_type_path a.a_path
 		| _ -> mk_type_path c.cl_path
 		| _ -> mk_type_path c.cl_path
 	in
 	in
-	let t = load_instance ctx2 (tpath,c.cl_pos) true in
+	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]));
 	flush_pass ctx2 PFinal ("core_final",(fst c.cl_path @ [snd c.cl_path]));
 	match t with
 	match t with
 	| TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) ->
 	| TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) ->

+ 1 - 1
src/typing/typeloadCheck.ml

@@ -596,7 +596,7 @@ module Inheritance = struct
 		let fl = ExtList.List.filter_map (fun (is_extends,(ct,p)) ->
 		let fl = ExtList.List.filter_map (fun (is_extends,(ct,p)) ->
 			try
 			try
 				let t = 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)) ->
 				with DisplayException(DisplayFields ({fkind = CRTypeHint} as r)) ->
 					(* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *)
 					(* 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;
 					if not is_extends && (has_class_flag c CInterface) then raise_fields [] CRImplements r.fsubject;

+ 1 - 1
src/typing/typeloadFields.ml

@@ -1351,7 +1351,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 				| None -> ()
 				| None -> ()
 				| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
 				| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
 					if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
 					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;
 				| _ -> raise_typing_error "A class constructor can't have a return type" p;
 			end
 			end
 		| false,_ ->
 		| false,_ ->

+ 1 - 1
src/typing/typeloadModule.ml

@@ -771,7 +771,7 @@ let type_types_into_module ctx m tdecls p =
 	if ctx.g.std != null_module then begin
 	if ctx.g.std != null_module then begin
 		add_dependency m ctx.g.std;
 		add_dependency m ctx.g.std;
 		(* this will ensure both String and (indirectly) Array which are basic types which might be referenced *)
 		(* 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;
 	end;
 	ModuleLevel.init_type_params ctx decls;
 	ModuleLevel.init_type_params ctx decls;
 	(* setup module types *)
 	(* setup module types *)

+ 58 - 54
src/typing/typer.ml

@@ -944,10 +944,10 @@ and type_object_decl ctx fl with_type p =
 		mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos
 		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`.
 			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.
 			Try to calculate a better pos.
@@ -958,13 +958,16 @@ and type_new ctx path el with_type force_inline p =
 				let pmin = p.pmin + (String.length "new ")
 				let pmin = p.pmin + (String.length "new ")
 				and pmax = p1.pmin - 2 (* Additional "1" for an opening bracket *)
 				and pmax = p1.pmin - 2 (* Additional "1" for an opening bracket *)
 				in
 				in
-				fst path, { p with
+				{ p with
 					pmin = if pmin < pmax then pmin else p.pmin;
 					pmin = if pmin < pmax then pmin else p.pmin;
 					pmax = pmax;
 					pmax = pmax;
 				}
 				}
-			| _ -> fst path, p
+			| _ -> p
 		end
 		end
 	in
 	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 =
 	let unify_constructor_call c fa =
 		try
 		try
 			let fcc = unify_field_call ctx fa [] el p fa.fa_inline in
 			let fcc = unify_field_call ctx fa [] el p fa.fa_inline in
@@ -973,57 +976,58 @@ and type_new ctx path el with_type force_inline p =
 		with Error err ->
 		with Error err ->
 			raise_typing_error_ext err
 			raise_typing_error_ext err
 	in
 	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);
 			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
-			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
 		raise exc
 	in
 	in
-	DisplayEmitter.check_display_type ctx t path;
+	DisplayEmitter.check_display_type ctx t (path,p_path);
 	let t = follow t in
 	let t = follow t in
 	let build_constructor_call ao c tl =
 	let build_constructor_call ao c tl =
 		let fa = FieldAccess.get_constructor_access c tl p in
 		let fa = FieldAccess.get_constructor_access c tl p in
@@ -1801,7 +1805,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 	| EConst (Regexp (r,opt)) ->
 	| EConst (Regexp (r,opt)) ->
 		let str = mk (TConst (TString r)) ctx.t.tstring p in
 		let str = mk (TConst (TString r)) ctx.t.tstring p in
 		let opt = mk (TConst (TString opt)) 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
 		mk (TNew ((match t with TInst (c,[]) -> c | _ -> die "" __LOC__),[],[str;opt])) t p
 	| EConst (String(s,SSingleQuotes)) when s <> "" ->
 	| EConst (String(s,SSingleQuotes)) when s <> "" ->
 		type_expr ctx (format_string ctx s p) with_type
 		type_expr ctx (format_string ctx s p) with_type
@@ -2050,7 +2054,7 @@ let create com macros =
 			do_load_macro = MacroContext.load_macro';
 			do_load_macro = MacroContext.load_macro';
 			do_load_module = TypeloadModule.load_module;
 			do_load_module = TypeloadModule.load_module;
 			do_load_type_def = Typeload.load_type_def;
 			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_format_string = format_string;
 			do_load_core_class = Typeload.load_core_class;
 			do_load_core_class = Typeload.load_core_class;
 		};
 		};

+ 2 - 2
src/typing/typerBase.ml

@@ -195,8 +195,8 @@ let type_module_type ctx t p =
 	let rec loop t tparams =
 	let rec loop t tparams =
 		match t with
 		match t with
 		| TClassDecl {cl_kind = KGenericBuild _} ->
 		| 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
 			let mt = try
 				module_type_of_type t
 				module_type_of_type t
 			with Exit ->
 			with Exit ->

+ 1 - 1
src/typing/typerDisplay.ml

@@ -310,7 +310,7 @@ let rec handle_signature_display ctx e_ast with_type =
 			in
 			in
 			handle_call tl el e1.epos
 			handle_call tl el e1.epos
 		| ENew(tpath,el) ->
 		| 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)
 			handle_call (find_constructor_types t) el (pos tpath)
 		| EArray(e1,e2) ->
 		| EArray(e1,e2) ->
 			let e1 = type_expr ctx e1 WithType.value in
 			let e1 = type_expr ctx e1 WithType.value in

+ 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 : error: Struct should be String
 Main.hx:4: characters 9-81 : ... have: Generic<{ url: Struct }>
 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 }>

+ 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;
+	}
+}

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

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

+ 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
+}

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

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

+ 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(", ")};
+	}
+}