2
0
Эх сурвалжийг харах

detect recursive abstracts on type_field (fixes #7614, closes #8609)

Aleksandr Kuzmenko 6 жил өмнө
parent
commit
73a85bf947

+ 12 - 2
src/core/abstract.ml

@@ -49,7 +49,7 @@ let find_from ab pl a b =
 
 
 let underlying_type_stack = new_rec_stack()
 let underlying_type_stack = new_rec_stack()
 
 
-let rec get_underlying_type a pl =
+let rec get_underlying_type ?(return_first=false) a pl =
 	let maybe_recurse t =
 	let maybe_recurse t =
 		let rec loop t = match t with
 		let rec loop t = match t with
 			| TMono r ->
 			| TMono r ->
@@ -68,7 +68,13 @@ let rec get_underlying_type a pl =
 					let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in
 					let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in
 					error ("Abstract chain detected: " ^ s) a.a_pos
 					error ("Abstract chain detected: " ^ s) a.a_pos
 				end;
 				end;
-				get_underlying_type a tl
+				(*
+					Even if only the first underlying type was requested
+					keep traversing to detect mutually recursive abstracts
+				*)
+				let result = get_underlying_type a tl in
+				if return_first then t
+				else result
 			| _ ->
 			| _ ->
 				t
 				t
 		in
 		in
@@ -76,6 +82,10 @@ let rec get_underlying_type a pl =
 	in
 	in
 	try
 	try
 		if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
 		if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
+		(* TODO:
+			Look into replacing `mk_mono` & `find_to` with `build_abstract a` & `TAbstract(a, pl)`.
+			`find_to` is probably needed for `@:multiType`
+		*)
 		let m = mk_mono() in
 		let m = mk_mono() in
 		let _ = find_to a pl m in
 		let _ = find_to a pl m in
 		maybe_recurse (follow m)
 		maybe_recurse (follow m)

+ 2 - 1
src/typing/fields.ml

@@ -561,7 +561,8 @@ let rec type_field cfg ctx e i p mode =
 				error "This operation is unsupported" p)
 				error "This operation is unsupported" p)
 		with Not_found -> try
 		with Not_found -> try
 			if does_forward a false then
 			if does_forward a false then
-				type_field (TypeFieldConfig.with_resume cfg) ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode
+				let underlying_type = Abstract.get_underlying_type ~return_first:true a pl in
+				type_field (TypeFieldConfig.with_resume cfg) ctx {e with etype = underlying_type} i p mode
 			else
 			else
 				raise Not_found
 				raise Not_found
 		with Not_found -> try
 		with Not_found -> try

+ 13 - 0
tests/misc/projects/Issue7614/Main.hx

@@ -0,0 +1,13 @@
+class Main {
+	static function main() { }
+}
+
+@:forward
+abstract Test(Test2) {
+	public inline function new() {
+		this.prop;
+	}
+}
+
+@:forward
+abstract Test2(Test) {}

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

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

+ 3 - 0
tests/misc/projects/Issue7614/compile-fail.hxml.stderr

@@ -0,0 +1,3 @@
+Main.hx:13: characters 1-24 : Abstract chain detected: Test2 -> Test -> Test2
+Main.hx:6: lines 6-10 : Defined in this class
+Main.hx:6: lines 6-10 : Abstract underlying type cannot be recursive