Jelajahi Sumber

[typer] delay interface checking somehow

closes #10847
Simon Krajewski 2 tahun lalu
induk
melakukan
66c86baf82

+ 13 - 2
src/typing/typeloadCheck.ml

@@ -549,6 +549,17 @@ module Inheritance = struct
 		let herits = List.filter (ctx.g.do_inherit ctx c p) herits in
 		(* Pass 1: Check and set relations *)
 		let check_herit t is_extends p =
+			let rec check_interfaces_or_delay () =
+				match c.cl_build() with
+				| BuildMacro pending ->
+					(* Ok listen... we're still building this class, which means we can't check its interfaces yet. However,
+					   we do want to check them at SOME point. So we use this pending list which was maybe designed for this
+					   purpose. However, we STILL have to delay the check because at the time pending is handled, the class
+					   is not built yet. See issue #10847. *)
+					pending := (fun () -> delay ctx PConnectField check_interfaces_or_delay) :: !pending
+				| _ ->
+					check_interfaces ctx c
+			in
 			if is_extends then begin
 				if c.cl_super <> None then typing_error "Cannot extend several classes" p;
 				let csup,params = check_extends ctx c t p in
@@ -556,7 +567,7 @@ module Inheritance = struct
 					if not (has_class_flag csup CInterface) then typing_error "Cannot extend by using a class" p;
 					c.cl_implements <- (csup,params) :: c.cl_implements;
 					if not !has_interf then begin
-						if not is_lib then delay ctx PConnectField (fun() -> check_interfaces ctx c);
+						if not is_lib then delay ctx PConnectField check_interfaces_or_delay;
 						has_interf := true;
 					end
 				end else begin
@@ -578,7 +589,7 @@ module Inheritance = struct
 					if not (has_class_flag intf CInterface) then typing_error "You can only implement an interface" p;
 					c.cl_implements <- (intf, params) :: c.cl_implements;
 					if not !has_interf && not is_lib && not (Meta.has (Meta.Custom "$do_not_check_interf") c.cl_meta) then begin
-						delay ctx PConnectField (fun() -> check_interfaces ctx c);
+						delay ctx PConnectField check_interfaces_or_delay;
 						has_interf := true;
 					end;
 					(fun () ->

+ 9 - 0
tests/misc/projects/Issue10847/bad/Macro.hx

@@ -0,0 +1,9 @@
+import haxe.macro.Context;
+import haxe.macro.Expr.Field;
+
+class Macro {
+	public static macro function build():Array<Field> {
+		Context.typeof(macro(null : String));
+		return [];
+	}
+}

+ 10 - 0
tests/misc/projects/Issue10847/bad/Main.hx

@@ -0,0 +1,10 @@
+interface Foo {
+	function foo():Void;
+}
+
+@:build(Macro.build())
+class Main implements Foo {
+	public function foo():Void {}
+}
+
+function main() {}

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

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

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

@@ -0,0 +1 @@
+Main.hx:6: characters 7-11 : Field foo needed by Foo is missing

+ 9 - 0
tests/misc/projects/Issue10847/good/Macro.hx

@@ -0,0 +1,9 @@
+import haxe.macro.Context;
+import haxe.macro.Expr.Field;
+
+class Macro {
+	public static macro function build():Array<Field> {
+		Context.typeof(macro(null : String));
+		return null;
+	}
+}

+ 10 - 0
tests/misc/projects/Issue10847/good/Main.hx

@@ -0,0 +1,10 @@
+interface Foo {
+	function foo():Void;
+}
+
+@:build(Macro.build())
+class Main implements Foo {
+	public function foo():Void {}
+}
+
+function main() {}

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

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