Browse Source

[display] don't lose switch subject if display is in case

closes #4345
Simon Krajewski 7 năm trước cách đây
mục cha
commit
47f5300e18

+ 12 - 0
src/optimization/optimizer.ml

@@ -1319,6 +1319,18 @@ let optimize_completion_expr e =
 		| EReturn _ ->
 			typing_side_effect := true;
 			map e
+		| ESwitch (e1,cases,def) when Parser.encloses_resume p ->
+			let e1 = loop e1 in
+			(* Prune all cases that aren't our display case *)
+			let cases = List.filter (fun (_,_,_,p) -> Parser.encloses_resume p) cases in
+			(* Don't throw away the switch subject when we optimize in a case expression because we might need it *)
+			let cases = List.map (fun (el,eg,eo,p) -> el,eg,(try Option.map loop eo with Return e -> Some e),p) cases in
+			let def = match def with
+				| None -> None
+				| Some (None,p) -> Some (None,p)
+				| Some (Some e,p) -> Some (Some (loop e),p)
+			in
+			(ESwitch (e1,cases,def),p)
 		| ESwitch (e,cases,def) ->
 			let e = loop e in
 			let cases = List.map (fun (el,eg,eo,p) -> match eo with

+ 2 - 1
src/typing/typeloadFunction.ml

@@ -111,7 +111,8 @@ let type_function ctx args ret fmode f do_display p =
 		let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in
 		try
 			if Common.defined ctx.com Define.NoCOpt || not !Parser.had_resume then raise Exit;
-			type_expr ctx (Optimizer.optimize_completion_expr e) NoValue
+			let e = Optimizer.optimize_completion_expr e in
+			type_expr ctx e NoValue
 		with
 		| Parser.TypePath (_,None,_) | Exit ->
 			type_expr ctx e NoValue

+ 35 - 0
tests/display/src/cases/Issue4345.hx

@@ -0,0 +1,35 @@
+package cases;
+
+class Issue4345 extends DisplayTestCase {
+	/**
+	typedef DTag = Tag<DTag>;  // kind of a defeat, but OK..
+	typedef Tag1 = { tag: TagE<Tag1>, name: String, count: Int }
+	typedef Tag2 = { tag: TagE<Tag2>, name: String, brand: String, liters: Float};
+
+	@:enum abstract TagE<T>(Int) {
+		var fruit:   TagE<Tag1> = 1;
+		var beverage:TagE<Tag2> = 2;
+	}
+
+	typedef Tag<T> = { tag:TagE<T> };
+
+	class Test {
+
+		static var data : Array<Dynamic> =
+		[
+			{ tag: fruit,    name: "Apple",  count: 5 },
+			{ tag: fruit,    name: "Orange", count: 3 },
+			{ tag: beverage, name: "Sprite", brand: "Coca-Cola", liters: 2.5 }
+		];
+
+		static function untag<T:Tag<T>>(t:T) switch t.tag {
+			case fruit:
+				t.{-1-}
+		}
+	**/
+	function test() {
+		var fields = fields(pos(1));
+		eq(true, hasField(fields, "name", "String"));
+		eq(true, hasField(fields, "count", "Int"));
+	}
+}