Kaynağa Gözat

[server] detect recursive dependencies, which cause inifinite loops (#8179)

* [server] detect recursive dependencies, which cause inifinite loops

* the?

* moved `complete` from typer context to typer globals

* forgotten line
Alexander Kuzmenko 6 yıl önce
ebeveyn
işleme
9a9ac37f5e
3 değiştirilmiş dosya ile 15 ekleme ve 0 silme
  1. 11 0
      src/compiler/server.ml
  2. 2 0
      src/context/typecore.ml
  3. 2 0
      src/typing/typer.ml

+ 11 - 0
src/compiler/server.ml

@@ -10,6 +10,7 @@ open DisplayOutput
 open Json
 open Json
 
 
 exception Dirty of module_def
 exception Dirty of module_def
+exception ServerError of string
 
 
 let measure_times = ref false
 let measure_times = ref false
 let prompt = ref false
 let prompt = ref false
@@ -300,6 +301,16 @@ let rec wait_loop process_params verbose accept =
 				| MCode -> check_module_shadowing com2 directories m
 				| MCode -> check_module_shadowing com2 directories m
 				| MMacro when ctx.Typecore.in_macro -> check_module_shadowing com2 directories m
 				| MMacro when ctx.Typecore.in_macro -> check_module_shadowing com2 directories m
 				| MMacro ->
 				| MMacro ->
+					(*
+						Creating another context while the previous one is incomplete means we have an infinite loop in the compiler.
+						Most likely because of circular dependencies in base modules (e.g. `StdTypes` or `String`)
+						Prevents spending another 5 hours for debugging.
+						@see https://github.com/HaxeFoundation/haxe/issues/8174
+					*)
+					if not ctx.g.complete then
+						raise (ServerError ("Infinite loop in Haxe server detected. "
+							^ "Probably caused by shadowing a module of the standard library. "
+							^ "Make sure shadowed module does not pull macro context."));
 					let _, mctx = MacroContext.get_macro_context ctx p in
 					let _, mctx = MacroContext.get_macro_context ctx p in
 					check_module_shadowing mctx.Typecore.com (get_changed_directories mctx) m
 					check_module_shadowing mctx.Typecore.com (get_changed_directories mctx) m
 			in
 			in

+ 2 - 0
src/context/typecore.ml

@@ -75,6 +75,8 @@ type typer_globals = {
 	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	mutable module_check_policies : (string list * module_check_policy list * bool) list;
 	mutable module_check_policies : (string list * module_check_policy list * bool) list;
 	mutable global_using : (tclass * pos) list;
 	mutable global_using : (tclass * pos) list;
+	(* Indicates that Typer.create() finished building this instance *)
+	mutable complete : bool;
 	(* api *)
 	(* api *)
 	do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool;
 	do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool;
 	do_create : Common.context -> typer;
 	do_create : Common.context -> typer;

+ 2 - 0
src/typing/typer.ml

@@ -2498,6 +2498,7 @@ let rec create com =
 			hook_generate = [];
 			hook_generate = [];
 			std = null_module;
 			std = null_module;
 			global_using = [];
 			global_using = [];
+			complete = false;
 			do_inherit = MagicTypes.on_inherit;
 			do_inherit = MagicTypes.on_inherit;
 			do_create = create;
 			do_create = create;
 			do_macro = MacroContext.type_macro;
 			do_macro = MacroContext.type_macro;
@@ -2607,6 +2608,7 @@ let rec create com =
 		| [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
 		| [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
 		| _ -> assert false);
 		| _ -> assert false);
 	| _ -> assert false);
 	| _ -> assert false);
+	ctx.g.complete <- true;
 	ctx
 	ctx
 
 
 ;;
 ;;