Browse Source

[typer] clean up with_type in operators.ml

closes #11392
Simon Krajewski 1 year ago
parent
commit
52bb47510e

+ 24 - 16
src/typing/operators.ml

@@ -193,7 +193,7 @@ let unify_int ctx e k =
 		unify ctx e.etype ctx.t.tint e.epos;
 		true
 
-let make_binop ctx op e1 e2 is_assign_op with_type p =
+let make_binop ctx op e1 e2 is_assign_op p =
 	let tint = ctx.t.tint in
 	let tfloat = ctx.t.tfloat in
 	let tstring = ctx.t.tstring in
@@ -204,7 +204,7 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
 			| KInt | KFloat | KString -> e
 			| KUnk | KDyn | KNumParam _ | KStrParam _ | KOther ->
 				let std = type_type ctx ([],"Std") e.epos in
-				let acc = acc_get ctx (type_field_default_cfg ctx std "string" e.epos (MCall []) with_type) in
+				let acc = acc_get ctx (type_field_default_cfg ctx std "string" e.epos (MCall []) WithType.value) in
 				ignore(follow acc.etype);
 				let acc = (match acc.eexpr with TField (e,FClosure (Some (c,tl),f)) -> { acc with eexpr = TField (e,FInstance (c,tl,f)) } | _ -> acc) in
 				make_call ctx acc [e] ctx.t.tstring e.epos
@@ -405,14 +405,14 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
 	| OpAssignOp _ ->
 		die "" __LOC__
 
-let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op with_type p =
+let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op p =
 	let map = apply_params a.a_params tl in
 	let make op_cf cf e1 e2 tret needs_assign swapped =
 		if cf.cf_expr = None && not (has_class_field_flag cf CfExtern) then begin
 			if not (Meta.has Meta.NoExpr cf.cf_meta) then Common.display_error ctx.com "Recursive operator method" p;
 			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 result = make_binop ctx op {e1 with etype = Abstract.follow_with_abstracts e1.etype} {e1 with etype = Abstract.follow_with_abstracts e2.etype} is_assign_op with_type p in
+				let result = make_binop ctx op {e1 with etype = Abstract.follow_with_abstracts e1.etype} {e1 with etype = Abstract.follow_with_abstracts e2.etype} is_assign_op p in
 				let t_expected = BinopResult.get_type result in
 				begin try
 					unify_raise tret t_expected p
@@ -525,15 +525,15 @@ let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op with_type
 	else
 		find (loop op)
 
-let try_abstract_binop_overloads ctx op e1 e2 is_assign_op with_type p =
+let try_abstract_binop_overloads ctx op e1 e2 is_assign_op p =
 	try
 		begin match follow e1.etype with
-			| TAbstract({a_impl = Some c} as a,tl) -> find_abstract_binop_overload ctx op e1 e2 a c tl true is_assign_op with_type p
+			| TAbstract({a_impl = Some c} as a,tl) -> find_abstract_binop_overload ctx op e1 e2 a c tl true is_assign_op p
 			| _ -> raise Not_found
 		end
 	with Not_found ->
 		begin match follow e2.etype with
-			| TAbstract({a_impl = Some c} as a,tl) -> find_abstract_binop_overload ctx op e1 e2 a c tl false is_assign_op with_type p
+			| TAbstract({a_impl = Some c} as a,tl) -> find_abstract_binop_overload ctx op e1 e2 a c tl false is_assign_op p
 			| _ -> raise Not_found
 		end
 
@@ -542,17 +542,23 @@ let type_binop_rhs ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p =
 		| OpEq | OpNotEq | OpLt | OpLte | OpGt | OpGte -> WithType.with_type e1.etype
 		| _ -> wt
 	in
-	type_expr ctx e2 with_type,with_type
+	type_expr ctx e2 with_type
 
-let type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op with_type p =
-	let e2,with_type = type_binop_rhs ctx op e1 e2 is_assign_op with_type p in
+let type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op with_type_rhs p =
+	let e2 = type_binop_rhs ctx op e1 e2 is_assign_op with_type_rhs p in
 	try
-		try_abstract_binop_overloads ctx op e1 e2 is_assign_op with_type p
+		try_abstract_binop_overloads ctx op e1 e2 is_assign_op p
 	with Not_found ->
-		make_binop ctx op e1 e2 is_assign_op with_type p
+		make_binop ctx op e1 e2 is_assign_op p
+
+let with_type_or_value with_type = match with_type with
+| WithType.NoValue ->
+	(* Even if we expect no value, we still want to type the lhs expression as a value. *)
+	WithType.value
+| _ ->
+	with_type
 
 let type_assign ctx e1 e2 with_type p =
-	let e1 = !type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type in
 	let type_rhs with_type = try
 		type_expr ctx e2 with_type
 	with Error e ->
@@ -604,6 +610,8 @@ let type_assign ctx e1 e2 with_type p =
 			let dispatcher = new call_dispatcher ctx (MCall [e2]) with_type p in
 			dispatcher#field_call fa_set [sea.se_this] [e2]
 	in
+	let with_type = with_type_or_value with_type in
+	let e1 = !type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type in
 	check_acc e1
 
 let type_non_assign_op ctx op e1 e2 is_assign_op abstract_overload_only with_type p =
@@ -625,8 +633,8 @@ let type_non_assign_op ctx op e1 e2 is_assign_op abstract_overload_only with_typ
 	in
 	let e1 = type_expr ctx e1 wt in
 	let result = if abstract_overload_only then begin
-		let e2,with_type = type_binop_rhs ctx op e1 e2 is_assign_op with_type p in
-		try_abstract_binop_overloads ctx op e1 e2 is_assign_op with_type p
+		let e2 = type_binop_rhs ctx op e1 e2 is_assign_op with_type p in
+		try_abstract_binop_overloads ctx op e1 e2 is_assign_op p
 	end else
 		type_binop2 ctx op e1 e2 is_assign_op wt p
 	in
@@ -745,6 +753,7 @@ let type_assign_op ctx op e1 e2 with_type p =
 			let e = BinopResult.to_texpr vr r_rhs assign in
 			vr#to_texpr e
 	in
+	let with_type = with_type_or_value with_type in
 	loop (!type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type)
 
 
@@ -763,7 +772,6 @@ let type_binop ctx op e1 e2 is_assign_op with_type p =
 			let op = if is_assign_op then OpAssignOp op else op in
 			die ~p ("Failed to type binary operation " ^ (s_binop op)) __LOC__
 
-
 let type_unop ctx op flag e with_type p =
 	let try_abstract_unop_overloads e = match follow e.etype with
 		| TAbstract ({a_impl = Some c} as a,tl) ->

+ 5 - 0
tests/misc/projects/Issue11392/Main.hx

@@ -0,0 +1,5 @@
+function main() {
+	var a:Int;
+	var b:Int;
+	$type(a, _) = $type(b, _) = 0;
+}

+ 2 - 0
tests/misc/projects/Issue11392/compile.hxml

@@ -0,0 +1,2 @@
+--main Main
+--interp

+ 2 - 0
tests/misc/projects/Issue11392/compile.hxml.stderr

@@ -0,0 +1,2 @@
+Main.hx:4: characters 8-9 : Warning : Int (expected: Value)
+Main.hx:4: characters 22-23 : Warning : Int (expected: WithType(Int, None))

+ 1 - 0
tests/optimization/run.hxml

@@ -21,6 +21,7 @@
 --macro Macro.register('TestJs')
 --macro Macro.register('TestLocalDce')
 --macro Macro.register('TestNadako')
+--macro Macro.register('TestCompoundBlockElements')
 --macro Macro.register('TestTreGeneration')
 --macro Macro.register('TestInlineConstructors')
 --macro Macro.register('issues')

+ 70 - 0
tests/optimization/src/TestCompoundBlockElements.hx

@@ -0,0 +1,70 @@
+import TestJs.use;
+
+class TestCompoundBlockElements {
+	@:js('
+		run(1);
+		run(1);
+		run(1);
+	')
+	static function testUnop() {
+		-run(1);
+		!run(1);
+		~run(1);
+	}
+
+	@:js('
+		run(1);
+		run(2);
+		run(3);
+		run(4);
+		run(5);
+		run(6);
+		run(7);
+		run(8);
+		run(9);
+		run(10);
+	')
+	static function testBinop() {
+		run(1) + run(2);
+		run(3) - run(4);
+		run(5) & run(6);
+		run(7) == run(8);
+		run(9) > run(10);
+	}
+
+	@:js('
+		run(1);
+		run(2);
+	')
+	static function testArrayAccess() {
+		run(1)[run(2)];
+	}
+
+	@:js('
+		run(1);
+		run(2);
+		run(3);
+	')
+	static function testArrayDeclaration() {
+		[run(1), run(2)];
+		run(3);
+	}
+
+	@:js('
+		run(1);
+		run(2);
+		run(3);
+	')
+	static function testObjectDeclaration() {
+		{
+			a: run(1),
+			b: run(2)
+		};
+		run(3);
+	}
+
+	@:pure(false)
+	static inline function run(i:Int):Dynamic {
+		return js.Syntax.code("run({0})", i);
+	}
+}