浏览代码

allow field-less ops again if their return type is an abstract whose underlying type is equal to the result of the native operation (see #2409)

Simon Krajewski 11 年之前
父节点
当前提交
e7963f58c7
共有 2 个文件被更改,包括 23 次插入26 次删除
  1. 16 0
      tests/unit/issues/Issue2409.hx
  2. 7 26
      typer.ml

+ 16 - 0
tests/unit/issues/Issue2409.hx

@@ -0,0 +1,16 @@
+package unit.issues;
+
+private abstract Foo(Int) {
+    public function new(x:Int) this = x;
+    @:op(A+B) public static function add(a:Foo, b:Foo):Foo;
+	public function get() {
+		return this;
+	}
+}
+
+class Issue2409 extends Test {
+	function test() {
+		var f:Foo = new Foo(1);
+		eq(1, (f+f).get());
+	}
+}

+ 7 - 26
typer.ml

@@ -2111,42 +2111,23 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 	| OpAssignOp _ ->
 		assert false
 	in
-	let rec expected_result_type = function
-		| OpAdd | OpSub | OpMult | OpDiv | OpMod -> ctx.t.tfloat
-		| OpGt | OpGte | OpLt | OpLte | OpEq | OpNotEq | OpBoolAnd | OpBoolOr -> ctx.t.tbool
-		| OpAnd | OpOr | OpXor | OpUShr | OpShr | OpShl -> ctx.t.tint
-		| OpArrow -> t_dynamic
-		| OpAssignOp op -> expected_result_type op
-		| OpInterval | OpAssign -> assert false
-	in
 	let find_overload a c tl left =
 		let map = apply_params a.a_params tl in
 		let make op_cf cf e1 e2 tret =
 			if cf.cf_expr = None then begin
 				if not (Meta.has Meta.CoreType a.a_meta) then begin
 					(* for non core-types we require that the return type is compatible to the native result type *)
-					let t_expected = expected_result_type op_cf in
+					let e' = make {e1 with etype = Abstract.follow_with_abstracts e1.etype} {e1 with etype = Abstract.follow_with_abstracts e2.etype} in
+					let t_expected = e'.etype in
 					begin try
 						unify_raise ctx tret t_expected p
 					with Error (Unify _,_) ->
-						let invalid_return () =
-							let s_expected = match op with
-								| OpAdd | OpAssignOp OpAdd -> "String or "
-								| _ -> ""
-							in
-							let pctx = print_context() in
-							let st = s_type pctx in
-							error (Printf.sprintf "The result of this operation (%s%s) is not compatible with declared return type %s" s_expected (st t_expected) (st tret)) p
-						in
-						match op with
-							| OpAdd | OpAssignOp OpAdd ->
-								begin try
-									unify_raise ctx tret ctx.t.tstring p
-								with Error (Unify _,_) ->
-									invalid_return()
-								end
+						match follow tret with
+							| TAbstract(a,tl) when type_iseq (Abstract.get_underlying_type a tl) t_expected ->
+								()
 							| _ ->
-								invalid_return()
+								let st = s_type (print_context()) in
+								error (Printf.sprintf "The result of this operation (%s) is not compatible with declared return type %s" (st t_expected) (st tret)) p
 					end;
 				end;
 				mk_cast (Codegen.binop op e1 e2 tret p) tret p