浏览代码

do not allow transitive unification of abstracts that have implementations (fixed issue #1406)

Simon Krajewski 12 年之前
父节点
当前提交
d51d0d01c4
共有 2 个文件被更改,包括 12 次插入6 次删除
  1. 5 2
      std/haxe/Vector.hx
  2. 7 4
      type.ml

+ 5 - 2
std/haxe/Vector.hx

@@ -25,13 +25,16 @@ package haxe;
 	A Vector is a storage of fixed size. It can be faster than Array on some
 	A Vector is a storage of fixed size. It can be faster than Array on some
 	targets, and is never slower.
 	targets, and is never slower.
 **/
 **/
-abstract Vector(#if flash9
+	
+typedef VImpl<T> = #if flash9
 	flash.Vector<T>
 	flash.Vector<T>
 #elseif neko
 #elseif neko
 	neko.NativeArray<T>
 	neko.NativeArray<T>
 #else
 #else
 	Array<T>
 	Array<T>
-#end)<T> {
+#end
+
+abstract Vector(VImpl<T>)<T> {
 	/**
 	/**
 		Creates a new Vector of length [length].
 		Creates a new Vector of length [length].
 		
 		

+ 7 - 4
type.ml

@@ -993,14 +993,15 @@ let rec unify a b =
 	| _ , TAbstract ({a_path=[],"Void"},_) ->
 	| _ , TAbstract ({a_path=[],"Void"},_) ->
 		error [cannot_unify a b]
 		error [cannot_unify a b]
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
+		let has_impl = a1.a_impl <> None || a2.a_impl <> None in
 		if not (List.exists (fun (t,cfo) ->
 		if not (List.exists (fun (t,cfo) ->
 			let t = apply_params a1.a_types tl1 t in
 			let t = apply_params a1.a_types tl1 t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
-			try unify t b; true with Unify_error _ -> false
+			try if has_impl then type_eq EqStrict t b else unify t b; true with Unify_error _ -> false
 		) a1.a_to) && not (List.exists (fun (t,cfo) ->
 		) a1.a_to) && not (List.exists (fun (t,cfo) ->
 			let t = apply_params a2.a_types tl2 t in
 			let t = apply_params a2.a_types tl2 t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
-			try unify a t; true with Unify_error _ -> false
+			try if has_impl then type_eq EqStrict a t else unify a t; true with Unify_error _ -> false
 		) a2.a_from) then error [cannot_unify a b]
 		) a2.a_from) then error [cannot_unify a b]
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 		let rec loop c tl =
 		let rec loop c tl =
@@ -1145,10 +1146,11 @@ let rec unify a b =
 		| _ ->
 		| _ ->
 			error [cannot_unify a b])
 			error [cannot_unify a b])
 	| TAbstract (aa,tl), _  ->
 	| TAbstract (aa,tl), _  ->
+		let has_impl = aa.a_impl <> None in
 		if not (List.exists (fun (t,cfo) ->
 		if not (List.exists (fun (t,cfo) ->
 			let t = apply_params aa.a_types tl t in
 			let t = apply_params aa.a_types tl t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
-			try unify t b; true with Unify_error _ -> false
+			try if has_impl then type_eq EqStrict t b else unify t b; true with Unify_error _ -> false
 		) aa.a_to) then error [cannot_unify a b];
 		) aa.a_to) then error [cannot_unify a b];
 	| TInst ({ cl_kind = KTypeParameter ctl } as c,pl), TAbstract _ ->
 	| TInst ({ cl_kind = KTypeParameter ctl } as c,pl), TAbstract _ ->
 		(* one of the constraints must satisfy the abstract *)
 		(* one of the constraints must satisfy the abstract *)
@@ -1157,10 +1159,11 @@ let rec unify a b =
 			try unify t b; true with Unify_error _ -> false
 			try unify t b; true with Unify_error _ -> false
 		) ctl) then error [cannot_unify a b];
 		) ctl) then error [cannot_unify a b];
 	| _, TAbstract (bb,tl) ->
 	| _, TAbstract (bb,tl) ->
+		let has_impl = bb.a_impl <> None in
 		if not (List.exists (fun (t,cfo) ->
 		if not (List.exists (fun (t,cfo) ->
 			let t = apply_params bb.a_types tl t in
 			let t = apply_params bb.a_types tl t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
 			let t = match cfo with None -> t | Some cf -> monomorphs cf.cf_params t in
-			try unify a t; true with Unify_error _ -> false
+			try if has_impl then type_eq EqStrict a t else unify a t; true with Unify_error _ -> false
 		) bb.a_from) then error [cannot_unify a b];
 		) bb.a_from) then error [cannot_unify a b];
 	| _ , _ ->
 	| _ , _ ->
 		error [cannot_unify a b]
 		error [cannot_unify a b]