Ver código fonte

check abstract from/to even if the base abstract is the same (see #3494)

Simon Krajewski 10 anos atrás
pai
commit
1763b97ed6
2 arquivos alterados com 36 adições e 10 exclusões
  1. 14 0
      tests/unit/src/unit/issues/Issue3494.hx
  2. 22 10
      type.ml

+ 14 - 0
tests/unit/src/unit/issues/Issue3494.hx

@@ -0,0 +1,14 @@
+package unit.issues;
+
+private abstract E2<T1,T2>(Dynamic)
+	from T1 from T2 from E2<T2,T1>
+	to T1 to T2 to E2<T2,T1>
+{}
+
+class Issue3494 extends Test {
+	function test() {
+        var v1:E2<Int,String> = 1;
+        var v2:E2<String,Int> = 2;
+        v1 = v2;
+	}
+}

+ 22 - 10
type.ml

@@ -1329,20 +1329,21 @@ let rec unify a b =
 		if ea != eb then error [cannot_unify a b];
 		unify_type_params a b tl1 tl2
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) when a1 == a2 ->
-		unify_type_params a b tl1 tl2
+		begin try
+			unify_type_params a b tl1 tl2
+		with Unify_error _ as err ->
+			(* the type could still have a from/to relation to itself (issue #3494) *)
+			begin try
+				unify_abstracts a b a1 tl1 a2 tl2
+			with Unify_error _ ->
+				raise err
+			end
+		end
 	| TAbstract ({a_path=[],"Void"},_) , _
 	| _ , TAbstract ({a_path=[],"Void"},_) ->
 		error [cannot_unify a b]
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
-		let f1 = unify_to a1 tl1 b in
-		let f2 = unify_from a2 tl2 a b in
-		if (List.exists (f1 ~allow_transitive_cast:false) a1.a_to)
-		|| (List.exists (f2 ~allow_transitive_cast:false) a2.a_from)
-		|| (((Meta.has Meta.CoreType a1.a_meta) || (Meta.has Meta.CoreType a2.a_meta))
-			&& ((List.exists f1 a1.a_to) || (List.exists f2 a2.a_from))) then
-			()
-		else
-			error [cannot_unify a b]
+		unify_abstracts a b a1 tl1 a2 tl2
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 		let rec loop c tl =
 			if c == c2 then begin
@@ -1478,6 +1479,17 @@ let rec unify a b =
 	| _ , _ ->
 		error [cannot_unify a b]
 
+and unify_abstracts a b a1 tl1 a2 tl2 =
+	let f1 = unify_to a1 tl1 b in
+		let f2 = unify_from a2 tl2 a b in
+		if (List.exists (f1 ~allow_transitive_cast:false) a1.a_to)
+		|| (List.exists (f2 ~allow_transitive_cast:false) a2.a_from)
+		|| (((Meta.has Meta.CoreType a1.a_meta) || (Meta.has Meta.CoreType a2.a_meta))
+			&& ((List.exists f1 a1.a_to) || (List.exists f2 a2.a_from))) then
+			()
+		else
+			error [cannot_unify a b]
+
 and unify_anons a b a1 a2 =
 	(try
 		PMap.iter (fun n f2 ->