浏览代码

attempts to retain current casting behavior

Simon Krajewski 11 年之前
父节点
当前提交
77211ee13e
共有 2 个文件被更改,包括 73 次插入14 次删除
  1. 31 14
      codegen.ml
  2. 42 0
      tests/unit/issues/Issue1845.hx

+ 31 - 14
codegen.ml

@@ -657,20 +657,37 @@ module AbstractCast = struct
 		in
 		in
 		if type_iseq tleft eright.etype then
 		if type_iseq tleft eright.etype then
 			eright
 			eright
-		else try
-			begin match follow eright.etype with
-				| TAbstract(a,tl) ->
-					find a tl (fun () -> Abstract.find_to a tl tleft)
-				| _ ->
-					raise Not_found
-			end
-		with Not_found ->
-			begin match follow tleft with
-				| TAbstract(a,tl) ->
-					find a tl (fun () -> Abstract.find_from a tl eright.etype tleft)
-				| _ ->
-					raise Not_found
-			end
+		else begin
+			let rec loop tleft tright = match follow tleft,follow tright with
+			| TAbstract(a1,tl1),TAbstract(a2,tl2) ->
+				begin try find a2 tl2 (fun () -> Abstract.find_to a2 tl2 tleft)
+				with Not_found -> try find a1 tl1 (fun () -> Abstract.find_from a1 tl1 eright.etype tleft)
+				with Not_found -> raise Not_found
+				end
+			| TAbstract(a,tl),_ ->
+				begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft)
+				with Not_found ->
+					let rec loop2 tcl = match tcl with
+						| tc :: tcl -> loop (apply_params a.a_params tl tc) tright
+						| [] -> raise Not_found
+					in
+					loop2 a.a_from
+				end
+			| _,TAbstract(a,tl) ->
+				begin try find a tl (fun () -> Abstract.find_to a tl tleft)
+				with Not_found ->
+					let rec loop2 tcl = match tcl with
+						| tc :: tcl -> loop tleft (apply_params a.a_params tl tc)
+						| [] -> raise Not_found
+					in
+					loop2 a.a_to
+				end
+			| _ ->
+				unify_raise ctx eright.etype tleft p;
+				eright
+			in
+			loop tleft eright.etype
+		end
 
 
 	let cast_or_unify_raise ctx tleft eright p =
 	let cast_or_unify_raise ctx tleft eright p =
 		try
 		try

+ 42 - 0
tests/unit/issues/Issue1845.hx

@@ -0,0 +1,42 @@
+package unit.issues;
+
+private abstract A(Int) from Int {
+	inline public function new(x:Int) this=x;
+	@:from public static function fromArr(x:Array<Int>) return new A(x[0]);
+	public function toString() {
+		return 'A($this)';
+	}
+}
+
+private abstract M<T>(Null<T>) from Null<T> {
+	inline public function new(x:T) this=x;
+	public function toString() {
+		return 'M($this)';
+	}
+}
+
+private abstract A2(Int) from Int {
+	inline public function new(x:Int) this=x;
+	@:to public function fromArr():Array<Int> return [this];
+	public function toString() {
+		return 'A2($this)';
+	}
+}
+
+private abstract M2<T>(T) to T {
+	inline public function new(x:T) this=x;
+	public function toString() {
+		return 'M2($this)';
+	}
+}
+
+class Issue1845 extends Test {
+	function test() {
+		var m:M<A> = [10];
+		eq("M(10)", m.toString());
+
+		var m2:M2<A2> = new M2(12);
+		var a:Array<Int> = m2;
+		eq(12, a[0]);
+	}
+}