Browse Source

[typer] don't top-down-infer through the @:from we're currently typing

closes #10604
Simon Krajewski 3 years ago
parent
commit
ab1d6c8489

+ 1 - 1
src/typing/matcher.ml

@@ -422,7 +422,7 @@ module Pattern = struct
 						) el in
 						) el in
 						PatConstructor(con_array (List.length patterns) (pos e),patterns)
 						PatConstructor(con_array (List.length patterns) (pos e),patterns)
 					| TAbstract(a,tl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
 					| TAbstract(a,tl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
-						begin match TyperBase.get_abstract_froms a tl with
+						begin match TyperBase.get_abstract_froms ctx a tl with
 							| [t2] -> pattern (t :: seen) t2
 							| [t2] -> pattern (t :: seen) t2
 							| _ -> fail()
 							| _ -> fail()
 						end
 						end

+ 4 - 4
src/typing/typer.ml

@@ -75,7 +75,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
 					) c.cl_ordered_statics in
 					) c.cl_ordered_statics in
 					false,a.a_path,fields,TAbstractDecl a
 					false,a.a_path,fields,TAbstractDecl a
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-					begin match get_abstract_froms a pl with
+					begin match get_abstract_froms ctx a pl with
 						| [t2] ->
 						| [t2] ->
 							if (List.exists (shallow_eq t) stack) then raise Exit;
 							if (List.exists (shallow_eq t) stack) then raise Exit;
 							loop (t :: stack) t2
 							loop (t :: stack) t2
@@ -783,7 +783,7 @@ and type_object_decl ctx fl with_type p =
 			| TAbstract (a,pl) as t
 			| TAbstract (a,pl) as t
 				when not (Meta.has Meta.CoreType a.a_meta)
 				when not (Meta.has Meta.CoreType a.a_meta)
 					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
 					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
-				let froms = get_abstract_froms a pl
+				let froms = get_abstract_froms ctx a pl
 				and fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
 				and fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
 				(match List.fold_left fold [] froms with
 				(match List.fold_left fold [] froms with
 				| [t] -> t
 				| [t] -> t
@@ -1255,7 +1255,7 @@ and type_local_function ctx kind f with_type p =
 				(* unify for top-down inference unless we are expecting Void *)
 				(* unify for top-down inference unless we are expecting Void *)
 				maybe_unify_ret tr
 				maybe_unify_ret tr
 			| TAbstract(a,tl) ->
 			| TAbstract(a,tl) ->
-				begin match get_abstract_froms a tl with
+				begin match get_abstract_froms ctx a tl with
 					| [t2] ->
 					| [t2] ->
 						if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
 						if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
 					| l ->
 					| l ->
@@ -1351,7 +1351,7 @@ and type_array_decl ctx el with_type p =
 							| Some t -> t :: acc
 							| Some t -> t :: acc
 						)
 						)
 						[]
 						[]
-						(get_abstract_froms a pl)
+						(get_abstract_froms ctx a pl)
 				in
 				in
 				(match types with
 				(match types with
 				| [t] -> Some t
 				| [t] -> Some t

+ 5 - 2
src/typing/typerBase.ml

@@ -247,10 +247,13 @@ let unify_static_extension ctx e t p =
 		e
 		e
 	end
 	end
 
 
-let get_abstract_froms a pl =
+let get_abstract_froms ctx a pl =
 	let l = List.map (apply_params a.a_params pl) a.a_from in
 	let l = List.map (apply_params a.a_params pl) a.a_from in
 	List.fold_left (fun acc (t,f) ->
 	List.fold_left (fun acc (t,f) ->
-		match follow (Type.field_type f) with
+		(* We never want to use the @:from we're currently in because that's recursive (see #10604) *)
+		if f == ctx.curfield then
+			acc
+		else match follow (Type.field_type f) with
 		| TFun ([_,_,v],t) ->
 		| TFun ([_,_,v],t) ->
 			(try
 			(try
 				ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *)
 				ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *)

+ 18 - 0
tests/unit/src/unit/issues/Issue10604.hx

@@ -0,0 +1,18 @@
+package unit.issues;
+
+private abstract Promise<T>(Dynamic) {
+	@:from static inline function ofData<T>(d:T):Promise<T>
+		throw 0;
+}
+
+@:callable
+private abstract Next<In, Out>(In->Promise<Out>) from In->Promise<Out> to In->Promise<Out> {
+	@:from static function ofSafeSync<In, Out>(f:In->Out):Next<In, Out>
+		return x -> f(x); // error: Recursive implicit cast
+}
+
+class Issue10604 extends Test {
+	function test() {
+		utest.Assert.pass();
+	}
+}