浏览代码

[optimizer] don't switch-optimize if we have something that has an unknown value

Simon Krajewski 3 年之前
父节点
当前提交
efaeae7b39
共有 2 个文件被更改,包括 53 次插入3 次删除
  1. 36 3
      src/optimization/optimizer.ml
  2. 17 0
      tests/unit/src/unit/issues/Issue10624.hx

+ 36 - 3
src/optimization/optimizer.ml

@@ -238,11 +238,40 @@ let check_enum_construction_args el i =
 	) (true,0) el in
 	b
 
+let rec extract_constant_value e = match e.eexpr with
+	| TConst (TInt _ | TFloat _ | TString _ | TBool _ | TNull) ->
+		Some e
+	| TConst (TThis | TSuper) ->
+		None
+	| TField(_,FStatic(c,({cf_kind = Var {v_write = AccNever}} as cf))) ->
+		begin match cf.cf_expr with
+		| Some e ->
+			(* Don't care about inline, if we know the value it makes no difference. *)
+			extract_constant_value e
+		| None ->
+			None
+		end
+	| TField(_,FEnum _) ->
+		Some e
+	| TParenthesis e1 ->
+		extract_constant_value e1
+	| _ ->
+		None
+
 let check_constant_switch e1 cases def =
 	let rec loop e1 cases = match cases with
 		| (el,e) :: cases ->
-			if List.exists (Texpr.equal e1) el then Some e
-			else loop e1 cases
+			(* Map everything first so that we find unknown things eagerly. *)
+			let el = List.map (fun e2 -> match extract_constant_value e2 with
+				| Some e2 -> e2
+				| None -> raise Exit
+			) el in
+			if List.exists (fun e2 ->
+				Texpr.equal e1 e2
+			) el then
+				Some e
+			else
+				loop e1 cases
 		| [] ->
 			begin match def with
 			| None -> None
@@ -259,7 +288,11 @@ let check_constant_switch e1 cases def =
 in
 	match Texpr.skip e1 with
 		| {eexpr = TConst ct} as e1 when (match ct with TSuper | TThis -> false | _ -> true) ->
-			loop e1 cases
+			begin try
+				loop e1 cases
+			with Exit ->
+				None
+			end
 		| _ ->
 			if List.for_all (fun (_,e) -> is_empty e) cases && is_empty_def() then
 				Some e1

+ 17 - 0
tests/unit/src/unit/issues/Issue10624.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+class Issue10624 extends unit.Test {
+	static final RANDOM:Int = 33;
+
+	public function test() {
+		var v = switch (33) {
+			case 1:
+				"no";
+			case RANDOM:
+				"yes";
+			default:
+				"noooo";
+		}
+		eq("yes", v);
+	}
+}