瀏覽代碼

Make ctx.pass immutable (#11538)

* remove @:enumConstructorParam

* remove init_class_done

see if this breaks anything

* clone for expr

* make ctx.pass immutable

* ctx.e can be immutable too

* add failing test to show everyone that it's broken

* fix it

* inherit allow_inline and allow_transform to contexts within the same module
Simon Krajewski 1 年之前
父節點
當前提交
3f13b750ba

+ 0 - 7
src-json/meta.json

@@ -295,13 +295,6 @@
 		"targets": ["TAbstract"],
 		"links": ["https://haxe.org/manual/types-abstract-enum.html"]
 	},
-	{
-		"name": "EnumConstructorParam",
-		"metadata": ":enumConstructorParam",
-		"doc": "Used internally to annotate GADT type parameters.",
-		"targets": ["TClass"],
-		"internal": true
-	},
 	{
 		"name": "Event",
 		"metadata": ":event",

+ 1 - 1
src/codegen/gencommon/normalize.ml

@@ -31,7 +31,7 @@ open Gencommon
 
 let rec filter_param (stack:t list) t =
 	match t with
-	| TInst({ cl_kind = KTypeParameter _ } as c,_) when Meta.has Meta.EnumConstructorParam c.cl_meta ->
+	| TInst({ cl_kind = KTypeParameter ttp },_) when ttp.ttp_host = TPHEnumConstructor ->
 		t_dynamic
 	| TMono r ->
 		(match r.tm_type with

+ 17 - 22
src/context/typecore.ml

@@ -169,8 +169,8 @@ and typer = {
 	mutable m : typer_module;
 	c : typer_class;
 	f : typer_field;
-	mutable e : typer_expr;
-	mutable pass : typer_pass;
+	e : typer_expr;
+	pass : typer_pass;
 	mutable type_params : type_params;
 	mutable allow_inline : bool;
 	mutable allow_transform : bool;
@@ -183,7 +183,7 @@ and monomorphs = {
 }
 
 module TyperManager = struct
-	let create com g m c f e pass params = {
+	let create com g m c f e pass params allow_inline allow_transform = {
 		com = com;
 		g = g;
 		t = com.basic;
@@ -192,8 +192,8 @@ module TyperManager = struct
 		f = f;
 		e = e;
 		pass = pass;
-		allow_inline = true;
-		allow_transform = true;
+		allow_inline;
+		allow_transform;
 		type_params = params;
 		memory_marker = memory_marker;
 	}
@@ -244,42 +244,46 @@ module TyperManager = struct
 		let c = create_ctx_c null_class in
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
-		create com g m c f e PBuildModule []
+		create com g m c f e PBuildModule [] true true
 
 	let clone_for_class ctx c =
 		let c = create_ctx_c c in
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
 		let params = match c.curclass.cl_kind with KAbstractImpl a -> a.a_params | _ -> c.curclass.cl_params in
-		create ctx.com ctx.g ctx.m c f e PBuildClass params
+		create ctx.com ctx.g ctx.m c f e PBuildClass params ctx.allow_inline ctx.allow_transform
 
 	let clone_for_enum ctx en =
 		let c = create_ctx_c null_class in
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
-		create ctx.com ctx.g ctx.m c f e PBuildModule en.e_params
+		create ctx.com ctx.g ctx.m c f e PBuildModule en.e_params ctx.allow_inline ctx.allow_transform
 
 	let clone_for_typedef ctx td =
 		let c = create_ctx_c null_class in
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
-		create ctx.com ctx.g ctx.m c f e PBuildModule td.t_params
+		create ctx.com ctx.g ctx.m c f e PBuildModule td.t_params ctx.allow_inline ctx.allow_transform
 
 	let clone_for_abstract ctx a =
 		let c = create_ctx_c null_class in
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
-		create ctx.com ctx.g ctx.m c f e PBuildModule a.a_params
+		create ctx.com ctx.g ctx.m c f e PBuildModule a.a_params ctx.allow_inline ctx.allow_transform
 
 	let clone_for_field ctx cf params =
 		let f = create_ctx_f cf in
 		let e = create_ctx_e () in
-		create ctx.com ctx.g ctx.m ctx.c f e PBuildClass params
+		create ctx.com ctx.g ctx.m ctx.c f e PBuildClass params ctx.allow_inline ctx.allow_transform
 
 	let clone_for_enum_field ctx params =
 		let f = create_ctx_f null_field in
 		let e = create_ctx_e () in
-		create ctx.com ctx.g ctx.m ctx.c f e PBuildClass params
+		create ctx.com ctx.g ctx.m ctx.c f e PBuildClass params ctx.allow_inline ctx.allow_transform
+
+	let clone_for_expr ctx =
+		let e = create_ctx_e () in
+		create ctx.com ctx.g ctx.m ctx.c ctx.f e PTypeField ctx.type_params ctx.allow_inline ctx.allow_transform
 end
 
 type field_host =
@@ -559,12 +563,8 @@ let rec flush_pass ctx p where =
 
 let make_pass ctx f = f
 
-let init_class_done ctx =
-	ctx.pass <- PConnectField
-
 let enter_field_typing_pass ctx info =
-	flush_pass ctx PConnectField info;
-	ctx.pass <- PTypeField
+	flush_pass ctx PConnectField info
 
 let make_lazy ?(force=true) ctx t_proc f where =
 	let r = ref (lazy_available t_dynamic) in
@@ -909,11 +909,6 @@ let debug com (path : string list) str =
 			if List.exists (Ast.match_path false path) debug_paths then emit();
 	end
 
-let init_class_done ctx =
-	let path = fst ctx.c.curclass.cl_path @ [snd ctx.c.curclass.cl_path] in
-	debug ctx.com path ("init_class_done " ^ s_type_path ctx.c.curclass.cl_path);
-	init_class_done ctx
-
 let ctx_pos ctx =
 	let inf = fst ctx.m.curmod.m_path @ [snd ctx.m.curmod.m_path]in
 	let inf = (match snd ctx.c.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf @ [n]) in

+ 8 - 8
src/typing/functionArguments.ml

@@ -4,7 +4,7 @@ open Type
 open Typecore
 open Error
 
-let type_function_arg ctx t e opt p =
+let type_function_arg com t e opt p =
 	(* TODO https://github.com/HaxeFoundation/haxe/issues/8461 *)
 	(* delay ctx PTypeField (fun() ->
 		if ExtType.is_void (follow t) then
@@ -12,9 +12,9 @@ let type_function_arg ctx t e opt p =
 	); *)
 	if opt then
 		let e = (match e with None -> Some (EConst (Ident "null"),null_pos) | _ -> e) in
-		ctx.t.tnull t, e
+		com.Common.basic.tnull t, e
 	else
-		let t = match e with Some (EConst (Ident "null"),null_pos) -> ctx.t.tnull t | _ -> t in
+		let t = match e with Some (EConst (Ident "null"),null_pos) -> com.basic.tnull t | _ -> t in
 		t, e
 
 let type_function_arg_value ctx t c do_display =
@@ -38,7 +38,7 @@ let type_function_arg_value ctx t c do_display =
 			loop e
 
 class function_arguments
-	(ctx : typer)
+	(com : Common.context)
 	(type_arg : int -> bool -> type_hint option -> pos -> Type.t)
 	(is_extern : bool)
 	(do_display : bool)
@@ -48,7 +48,7 @@ class function_arguments
 	let with_default =
 		let l = List.mapi (fun i ((name,pn),opt,_,t,eo) ->
 			let t = type_arg i opt t pn in
-			let t,eo = type_function_arg ctx t eo opt pn in
+			let t,eo = type_function_arg com t eo opt pn in
 			(name,eo,t)
 		) syntax in
 		let l = match abstract_this with
@@ -83,7 +83,7 @@ object(self)
 
 	(* Returns the `(tvar * texpr option) list` for `tf_args`. Also checks the validity of argument names and whether or not
 	   an argument should be displayed. *)
-	method for_expr = match expr_repr with
+	method for_expr ctx = match expr_repr with
 		| Some l ->
 			l
 		| None ->
@@ -116,7 +116,7 @@ object(self)
 			l
 
 	(* Verifies the validity of any argument typed as `haxe.extern.Rest` and checks default values. *)
-	method verify_extern =
+	method verify_extern ctx =
 		let rec loop is_abstract_this syntax typed = match syntax,typed with
 			| syntax,(name,_,t) :: typed when is_abstract_this ->
 				loop false syntax typed
@@ -135,5 +135,5 @@ object(self)
 	method bring_into_context ctx =
 		List.iter (fun (v,_) ->
 			ctx.f.locals <- PMap.add v.v_name v ctx.f.locals
-		) self#for_expr
+		) (self#for_expr ctx)
 end

+ 15 - 13
src/typing/macroContext.ml

@@ -57,7 +57,7 @@ let macro_timer com l =
 
 let typing_timer ctx need_type f =
 	let t = Timer.timer ["typing"] in
-	let old = ctx.com.error_ext and oldp = ctx.pass and oldlocals = ctx.f.locals in
+	let old = ctx.com.error_ext and oldlocals = ctx.f.locals in
 	let restore_report_mode = disable_report_mode ctx.com in
 	(*
 		disable resumable errors... unless we are in display mode (we want to reach point of completion)
@@ -65,18 +65,20 @@ let typing_timer ctx need_type f =
 	(* if ctx.com.display.dms_kind = DMNone then ctx.com.error <- (fun e -> raise_error e); *) (* TODO: review this... *)
 	ctx.com.error_ext <- (fun err -> raise_error { err with err_from_macro = true });
 
-	if need_type && ctx.pass < PTypeField then begin
+	let ctx = if need_type && ctx.pass < PTypeField then begin
 		enter_field_typing_pass ctx ("typing_timer",[] (* TODO: ? *));
-	end;
+		TyperManager.clone_for_expr ctx
+	end else
+		ctx
+	in
 	let exit() =
 		t();
 		ctx.com.error_ext <- old;
-		ctx.pass <- oldp;
 		ctx.f.locals <- oldlocals;
 		restore_report_mode ();
 	in
 	try
-		let r = f() in
+		let r = f ctx in
 		exit();
 		r
 	with Error err ->
@@ -322,7 +324,7 @@ let make_macro_api ctx mctx p =
 	{
 		com_api with
 		MacroApi.get_type = (fun s ->
-			typing_timer ctx false (fun() ->
+			typing_timer ctx false (fun ctx ->
 				let path = parse_path s in
 				let tp = match List.rev (fst path) with
 					| s :: sl when String.length s > 0 && (match s.[0] with 'A'..'Z' -> true | _ -> false) ->
@@ -338,10 +340,10 @@ let make_macro_api ctx mctx p =
 			)
 		);
 		MacroApi.resolve_type = (fun t p ->
-			typing_timer ctx false (fun() -> Typeload.load_complex_type ctx false (t,p))
+			typing_timer ctx false (fun ctx -> Typeload.load_complex_type ctx false (t,p))
 		);
 		MacroApi.resolve_complex_type = (fun t ->
-			typing_timer ctx false (fun() ->
+			typing_timer ctx false (fun ctx ->
 				let rec load (t,_) =
 					((match t with
 					| CTPath ptp ->
@@ -394,17 +396,17 @@ let make_macro_api ctx mctx p =
 			)
 		);
 		MacroApi.get_module = (fun s ->
-			typing_timer ctx false (fun() ->
+			typing_timer ctx false (fun ctx ->
 				let path = parse_path s in
 				let m = List.map type_of_module_type (TypeloadModule.load_module ctx path p).m_types in
 				m
 			)
 		);
 		MacroApi.type_expr = (fun e ->
-			typing_timer ctx true (fun() -> type_expr ctx e WithType.value)
+			typing_timer ctx true (fun ctx -> type_expr ctx e WithType.value)
 		);
 		MacroApi.flush_context = (fun f ->
-			typing_timer ctx true f
+			typing_timer ctx true (fun _ -> f ())
 		);
 		MacroApi.get_local_type = (fun() ->
 			match ctx.c.get_build_infos() with
@@ -500,7 +502,7 @@ let make_macro_api ctx mctx p =
 			end
 		);
 		MacroApi.module_dependency = (fun mpath file ->
-			let m = typing_timer ctx false (fun() ->
+			let m = typing_timer ctx false (fun ctx ->
 				let old_deps = ctx.m.curmod.m_extra.m_deps in
 				let m = TypeloadModule.load_module ctx (parse_path mpath) p in
 				ctx.m.curmod.m_extra.m_deps <- old_deps;
@@ -512,7 +514,7 @@ let make_macro_api ctx mctx p =
 			ctx.m.curmod
 		);
 		MacroApi.cast_or_unify = (fun t e p ->
-			typing_timer ctx true (fun () ->
+			typing_timer ctx true (fun ctx ->
 				try
 					ignore(AbstractCast.cast_or_unify_raise ctx t e p);
 					true

+ 0 - 1
src/typing/typeload.ml

@@ -726,7 +726,6 @@ let rec type_type_param ctx host path p tp =
 	let c = mk_class ctx.m.curmod (fst path @ [snd path],n) (pos tp.tp_name) (pos tp.tp_name) in
 	c.cl_params <- type_type_params ctx host c.cl_path p tp.tp_params;
 	c.cl_meta <- tp.Ast.tp_meta;
-	if host = TPHEnumConstructor then c.cl_meta <- (Meta.EnumConstructorParam,[],null_pos) :: c.cl_meta;
 	let ttp = mk_type_param c host None None in
 	if ctx.m.is_display_file && DisplayPosition.display_position#enclosed_in (pos tp.tp_name) then
 		DisplayEmitter.display_type ctx ttp.ttp_type (pos tp.tp_name);

+ 12 - 7
src/typing/typeloadFields.ml

@@ -740,10 +740,11 @@ module TypeBinding = struct
 						display_error ctx.com ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed. Previously declared at " ^ (s_type_path csup.cl_path) ) cf.cf_name_pos
 		end
 
-	let bind_var_expression ctx cctx fctx cf e =
+	let bind_var_expression ctx_f cctx fctx cf e =
 		let c = cctx.tclass in
 		let t = cf.cf_type in
 		let p = cf.cf_pos in
+		let ctx = TyperManager.clone_for_expr ctx_f in
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta);
 		let check_cast e =
@@ -834,8 +835,9 @@ module TypeBinding = struct
 		| Some e ->
 			bind_var_expression ctx cctx fctx cf e
 
-	let bind_method ctx cctx fctx cf t args ret e p =
+	let bind_method ctx_f cctx fctx cf t args ret e p =
 		let c = cctx.tclass in
+		let ctx = TyperManager.clone_for_expr ctx_f in
 		let bind r =
 			incr stats.s_methods_typed;
 			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);
@@ -875,7 +877,7 @@ module TypeBinding = struct
 						if v.v_name <> "_" && has_mono v.v_type then warning ctx WTemp "Uninferred function argument, please add a type-hint" v.v_pos;
 					) fargs; *)
 					let tf = {
-						tf_args = args#for_expr;
+						tf_args = args#for_expr ctx;
 						tf_type = ret;
 						tf_expr = e;
 					} in
@@ -1192,7 +1194,7 @@ let setup_args_ret ctx cctx fctx name fd p =
 		in
 		if i = 0 then maybe_use_property_type cto (fun () -> match Lazy.force mk with MKSetter -> true | _ -> false) def else def()
 	in
-	let args = new FunctionArguments.function_arguments ctx type_arg is_extern fctx.is_display_field abstract_this fd.f_args in
+	let args = new FunctionArguments.function_arguments ctx.com type_arg is_extern fctx.is_display_field abstract_this fd.f_args in
 	args,ret
 
 let create_method (ctx,cctx,fctx) c f fd p =
@@ -1346,11 +1348,15 @@ let create_method (ctx,cctx,fctx) c f fd p =
 		if fctx.is_display_field then begin
 			delay ctx PTypeField (fun () ->
 				(* We never enter type_function so we're missing out on the argument processing there. Let's do it here. *)
-				ignore(args#for_expr)
+				let ctx = TyperManager.clone_for_expr ctx in
+				ignore(args#for_expr ctx)
 			);
 			check_field_display ctx fctx c cf;
 		end else
-			delay ctx PTypeField (fun () -> args#verify_extern);
+			delay ctx PTypeField (fun () ->
+				let ctx = TyperManager.clone_for_expr ctx in
+				args#verify_extern ctx
+			);
 		if fd.f_expr <> None then begin
 			if fctx.is_abstract then unexpected_expression ctx.com fctx "Abstract methods may not have an expression" p
 			else if not (fctx.is_inline || fctx.is_macro) then warning ctx WExternWithExpr "Extern non-inline function may not have an expression" p;
@@ -1608,7 +1614,6 @@ let check_overloads ctx c =
 let finalize_class cctx =
 	(* push delays in reverse order so they will be run in correct order *)
 	List.iter (fun (ctx,r) ->
-		init_class_done ctx;
 		(match r with
 		| None -> ()
 		| Some r -> delay ctx PTypeField (fun() -> ignore(lazy_type r)))

+ 0 - 3
src/typing/typeloadFunction.ml

@@ -28,12 +28,9 @@ open Error
 open FunctionArguments
 
 let save_field_state ctx =
-	let old_e = ctx.e in
-	ctx.e <- TyperManager.create_ctx_e ();
 	let locals = ctx.f.locals in
 	(fun () ->
 		ctx.f.locals <- locals;
-		ctx.e <- old_e;
 	)
 
 let type_function_params ctx fd host fname p =

+ 13 - 13
src/typing/typer.ml

@@ -1217,23 +1217,30 @@ and type_map_declaration ctx e1 el with_type p =
 	let el = (mk (TVar (v,Some enew)) t_dynamic p) :: (List.rev el) in
 	mk (TBlock el) tmap p
 
-and type_local_function ctx kind f with_type p =
+and type_local_function ctx_from kind f with_type p =
 	let name,inline = match kind with FKNamed (name,inline) -> Some name,inline | _ -> None,false in
-	let params = TypeloadFunction.type_function_params ctx f TPHLocal (match name with None -> "localfun" | Some (n,_) -> n) p in
+	let params = TypeloadFunction.type_function_params ctx_from f TPHLocal (match name with None -> "localfun" | Some (n,_) -> n) p in
 	if params <> [] then begin
-		if name = None then display_error ctx.com "Type parameters not supported in unnamed local functions" p;
+		if name = None then display_error ctx_from.com "Type parameters not supported in unnamed local functions" p;
 		if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p
 	end;
 	let v,pname = (match name with
 		| None -> None,p
 		| Some (v,pn) -> Some v,pn
 	) in
-	let old_tp,old_in_loop = ctx.type_params,ctx.e.in_loop in
+	let curfun = match ctx_from.e.curfun with
+		| FunStatic -> FunStatic
+		| FunMemberAbstract
+		| FunMemberAbstractLocal -> FunMemberAbstractLocal
+		| _ -> FunMemberClassLocal
+	in
+	let ctx = TyperManager.clone_for_expr ctx_from in
+	let old_tp = ctx.type_params in
 	ctx.type_params <- params @ ctx.type_params;
 	if not inline then ctx.e.in_loop <- false;
 	let rt = Typeload.load_type_hint ctx p f.f_type in
 	let type_arg _ opt t p = Typeload.load_type_hint ~opt ctx p t in
-	let args = new FunctionArguments.function_arguments ctx type_arg false ctx.f.in_display None f.f_args in
+	let args = new FunctionArguments.function_arguments ctx.com type_arg false ctx.f.in_display None f.f_args in
 	let targs = args#for_type in
 	let maybe_unify_arg t1 t2 =
 		match follow t1 with
@@ -1331,17 +1338,10 @@ and type_local_function ctx kind f with_type p =
 			if params <> [] then v.v_extra <- Some (var_extra params None);
 			Some v
 	) in
-	let curfun = match ctx.e.curfun with
-		| FunStatic -> FunStatic
-		| FunMemberAbstract
-		| FunMemberAbstractLocal -> FunMemberAbstractLocal
-		| _ -> FunMemberClassLocal
-	in
 	let e = TypeloadFunction.type_function ctx args rt curfun f.f_expr ctx.f.in_display p in
 	ctx.type_params <- old_tp;
-	ctx.e.in_loop <- old_in_loop;
 	let tf = {
-		tf_args = args#for_expr;
+		tf_args = args#for_expr ctx;
 		tf_type = rt;
 		tf_expr = e;
 	} in

+ 0 - 1
src/typing/typerDisplay.ml

@@ -583,7 +583,6 @@ let handle_display ctx e_ast dk mode with_type =
 			raise_toplevel ctx dk with_type (s_type_path path,p)
 	| DisplayException(DisplayFields ({fkind = CRTypeHint} as r)) when (match fst e_ast with ENew _ -> true | _ -> false) ->
 		let timer = Timer.timer ["display";"toplevel";"filter ctors"] in
-		ctx.pass <- PBuildClass;
 		let l = List.filter (fun item ->
 			let is_private_to_current_module mt =
 				(* Remove the _Module nonsense from the package *)

+ 3 - 0
tests/misc/projects/Issue11538/M.hx

@@ -0,0 +1,3 @@
+class M {
+	static public var x:Float;
+}

+ 25 - 0
tests/misc/projects/Issue11538/Main.hx

@@ -0,0 +1,25 @@
+import haxe.macro.Context;
+import haxe.macro.Expr;
+
+using haxe.macro.Tools;
+
+#if !macro
+@:build(Main.build())
+#end
+class Main {
+	#if macro
+	static function build():Array<Field> {
+		var t = Context.typeof(macro M.x);
+		var field = (macro class X {
+			static public var type = $v{t.toString()};
+		}).fields[0];
+		return [field];
+	}
+	#end
+}
+
+function main() {
+	#if !macro
+	trace(Main.type);
+	#end
+}

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

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

+ 1 - 0
tests/misc/projects/Issue11538/compile.hxml.stdout

@@ -0,0 +1 @@
+Main.hx:23: Float