Browse Source

recurse into KAbstract when determining string handling (closes #3121)

Simon Krajewski 11 years ago
parent
commit
7b758a486e
2 changed files with 27 additions and 12 deletions
  1. 11 0
      tests/optimization/src/Test.hx
  2. 16 12
      typer.ml

+ 11 - 0
tests/optimization/src/Test.hx

@@ -8,6 +8,10 @@ class InlineCtor {
 	}
 }
 
+@:enum abstract MyEnum(String) to String {
+	var A = "a";
+}
+
 class Test {
 	@:js('3;')
 	static function testNoOpRemoval() {
@@ -128,4 +132,11 @@ class Test {
 		var a = [1, 2];
 		a[2];
 	}
+
+	@:js('
+		var s = "" + "a";
+	')
+	static function testAbstractOverStringBinop() {
+		var s = "" + A;
+	}
 }

+ 16 - 12
typer.ml

@@ -89,12 +89,12 @@ type type_class =
 	| KDyn
 	| KOther
 	| KParam of t
-	| KAbstract of tabstract
+	| KAbstract of tabstract * t list
 
 let rec classify t =
 	match follow t with
 	| TInst ({ cl_path = ([],"String") },[]) -> KString
-	| TAbstract({a_impl = Some _} as a,_) -> KAbstract a
+	| TAbstract({a_impl = Some _} as a,tl) -> KAbstract (a,tl)
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
 	| TAbstract (a,[]) when List.exists (fun (t,_) -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KParam t
@@ -1855,16 +1855,20 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 	let tfloat = ctx.t.tfloat in
 	let tstring = ctx.t.tstring in
 	let to_string e =
-		match classify e.etype with
-		| KAbstract {a_impl = Some c} when PMap.mem "toString" c.cl_statics ->
-			call_to_string ctx c e
-		| KUnk | KDyn | KParam _ | KOther | KAbstract _ ->
-			let std = type_type ctx ([],"Std") e.epos in
-			let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in
-			ignore(follow acc.etype);
-			let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,f)) } | _ -> acc) in
-			make_call ctx acc [e] ctx.t.tstring e.epos
-		| KInt | KFloat | KString -> e
+		let rec loop t = match classify t with
+			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
+				call_to_string ctx c e
+			| KInt | KFloat | KString -> e
+			| KUnk | KDyn | KParam _ | KOther ->
+				let std = type_type ctx ([],"Std") e.epos in
+				let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in
+				ignore(follow acc.etype);
+				let acc = (match acc.eexpr with TField (e,FClosure (Some c,f)) -> { acc with eexpr = TField (e,FInstance (c,f)) } | _ -> acc) in
+				make_call ctx acc [e] ctx.t.tstring e.epos
+			| KAbstract (a,tl) ->
+				loop (Codegen.Abstract.get_underlying_type a tl)
+		in
+		loop e.etype
 	in
 	let mk_op e1 e2 t =
 		if op = OpAdd && (classify t) = KString then