ソースを参照

determine array matches from the constructors if subterm is Dynamic (closes #3377)

Simon Krajewski 11 年 前
コミット
4eb09262e7
2 ファイル変更64 行追加7 行削除
  1. 13 7
      matcher.ml
  2. 51 0
      tests/unit/issues/Issue3377.hx

+ 13 - 7
matcher.ml

@@ -217,7 +217,7 @@ let mk_subs st con =
 		end
 	| CArray 0 -> []
 	| CArray i ->
-		let t = match follow con.c_type with TInst({cl_path=[],"Array"},[t]) -> t | _ -> assert false in
+		let t = match follow con.c_type with TInst({cl_path=[],"Array"},[t]) -> t | TDynamic _ as t -> t | _ -> assert false in
 		ExtList.List.init i (fun i -> mk_st (SArray(st,i)) t st.st_pos)
 	| CEnum _ | CConst _ | CType _ | CExpr _ | CAny ->
 		[]
@@ -524,7 +524,7 @@ let to_pattern ctx e t =
 		| EArrayDecl el ->
 			pctx.pc_is_complex <- true;
 			begin match follow t with
-				| TInst({cl_path=[],"Array"},[t2]) ->
+				| TInst({cl_path=[],"Array"},[t2]) | (TDynamic _ as t2) ->
 					let pl = ExtList.List.mapi (fun i e ->
 						loop pctx e t2
 					) el in
@@ -989,7 +989,7 @@ let rec convert_st ctx st = match st.st_def with
 		Typer.acc_get ctx (Typer.type_field ctx e cf.cf_name st.st_pos Typer.MGet) st.st_pos
 	| SArray (sts,i) -> mk (TArray(convert_st ctx sts,mk_const ctx st.st_pos (TInt (Int32.of_int i)))) st.st_type st.st_pos
 	| STuple (st,_,_) -> convert_st ctx st
-	| SEnum(sts,ef,i) -> mk (TEnumParameter(convert_st ctx sts, ef, i)) st.st_type st.st_pos
+	| SEnum (sts,ef,i) -> mk (TEnumParameter(convert_st ctx sts, ef, i)) st.st_type st.st_pos
 
 let convert_con ctx con = match con.c_def with
 	| CConst c -> mk_const ctx con.c_pos c
@@ -1029,10 +1029,16 @@ let convert_switch mctx st cases loop =
 	| TAbstract({a_path = [],"Bool"},_) ->
 		wrap_exhaustive (e_st)
 	| _ ->
-		if List.exists (fun (con,_) -> match con.c_def with CEnum _ -> true | _ -> false) cases then
-			mk_index_call()
-		else
-			e_st
+		let rec loop cases = match cases with
+			| [] -> e_st
+			| (con,_) :: cases ->
+				begin match con.c_def with
+					| CEnum _ -> mk_index_call()
+					| CArray _ -> mk (TField (e_st,FDynamic "length")) ctx.t.tint p
+					| _ -> loop cases
+				end
+		in
+		loop cases
 	in
 	let null = ref None in
 	let def = ref None in

+ 51 - 0
tests/unit/issues/Issue3377.hx

@@ -0,0 +1,51 @@
+package unit.issues;
+
+class Issue3377 extends Test {
+	function test() {
+		function f1(a:Array<Dynamic>) {
+			return switch (a) {
+				case [["a"]]: "match";
+				default: "no match";
+			}
+		}
+		eq("match", f1([["a"]]));
+		eq("no match", f1([["b"]]));
+		eq("no match", f1([[]]));
+
+		function f2(a:Array<Dynamic>) {
+			return switch (a) {
+				case [[]]: "match";
+				default: "no match";
+			}
+		}
+		eq("no match", f2([["a"]]));
+		eq("no match", f2([["b"]]));
+		eq("no match", f2([["a", "b"]]));
+		eq("no match", f2([[12]]));
+		eq("match", f2([[]]));
+	}
+
+	function testAtry() {
+		var complexObject =
+		{
+			field1: 123,
+			field2: 8.0,
+			field3: "foo",
+			field4: ([ "foo", null, [], "bar", ([ ([ [], 2, null, { a: 0, } ]:Array<Dynamic>), "baz", [], ]: Array<Dynamic>), { b: null } ]: Array<Dynamic>),
+			field5: null,
+		}
+
+		var s = switch (complexObject)
+		{
+			case {
+				field1: 123,
+				field2: 8.0,
+				field3: "foo",
+				field4: [ "foo", null, (_:Array<Dynamic>) => [], "bar", (_:Array<Dynamic>) => [ (_:Array<Dynamic>) => [ (_:Array<Dynamic>) => [], 2, null, (_: { ?a:Int }) => { a: 0, } ], "baz", [], ], (_: { ?b:Dynamic }) => { b: null } ],
+				field5: null,
+			}: "Matched!";
+			default: "Not matched!";
+		}
+		eq("Matched!", s);
+	}
+}