Преглед изворни кода

[matcher] look through enum abstracts to find actual match kind

closes #11213
Simon Krajewski пре 2 година
родитељ
комит
4138953a55

+ 21 - 16
src/typing/matcher/texprConverter.ml

@@ -77,9 +77,10 @@ let unify_constructor ctx params t con =
 	| _ ->
 		Some(con,params)
 
-let rec extract_const e = match e.eexpr with
-	| TConst ct -> Some ct
-	| TCast(e1,None) -> extract_const e1
+let rec extract_ctor e = match e.eexpr with
+	| TConst ct when ct <> TNull -> Some (ConConst ct)
+	| TField(_,FEnum(en,ef)) -> Some (ConEnum(en,ef))
+	| TCast(e1,None) -> extract_ctor e1
 	| _ -> None
 
 let all_ctors ctx e cases =
@@ -117,32 +118,36 @@ let all_ctors ctx e cases =
 	let add constructor =
 		Compile.ConTable.replace h constructor true
 	in
-	let rec loop t = match follow t with
+	let rec loop deep t = match follow t with
 		| TAbstract({a_path = [],"Bool"},_) ->
-			add (ConConst(TBool true),null_pos);
-			add (ConConst(TBool false),null_pos);
+			if not deep then begin
+				add (ConConst(TBool true),null_pos);
+				add (ConConst(TBool false),null_pos);
+			end;
 			SKValue,RunTimeFinite
 		| TAbstract({a_impl = Some c} as a,pl) when a.a_enum ->
-			List.iter (fun cf ->
+			if not deep then List.iter (fun cf ->
 				ignore(follow cf.cf_type);
 				if has_class_field_flag cf CfImpl && has_class_field_flag cf CfEnum then match cf.cf_expr with
 					| Some e ->
-						begin match extract_const e with
-						| Some ct -> if ct <> TNull then add (ConConst ct,null_pos)
+						begin match extract_ctor e with
+						| Some ctor -> add (ctor,null_pos)
 						| None -> add (ConStatic(c,cf),null_pos)
 						end;
 					| _ -> add (ConStatic(c,cf),null_pos)
 			) c.cl_ordered_statics;
-			SKValue,CompileTimeFinite
+			let real_kind,_ = loop true (Abstract.get_underlying_type a pl) in
+			real_kind,CompileTimeFinite
 		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-			loop (Abstract.get_underlying_type a pl)
+			loop deep (Abstract.get_underlying_type a pl)
 		| TInst({cl_path=[],"String"},_)
 		| TInst({cl_kind = KTypeParameter _ },_) ->
 			SKValue,Infinite
 		| TInst({cl_path=[],"Array"},_) ->
 			SKLength,Infinite
 		| TEnum(en,pl) ->
-			PMap.iter (fun _ ef -> add (ConEnum(en,ef),null_pos)) en.e_constrs;
+			if not deep then
+				PMap.iter (fun _ ef -> add (ConEnum(en,ef),null_pos)) en.e_constrs;
 			SKEnum,RunTimeFinite
 		| TAnon _ ->
 			SKValue,Infinite
@@ -151,7 +156,7 @@ let all_ctors ctx e cases =
 		| _ ->
 			SKValue,Infinite
 	in
-	let kind,finiteness = loop t in
+	let kind,finiteness = loop false t in
 	let compatible_kind con = match fst con with
 		| ConEnum _ -> kind = SKEnum
 		| ConArray _ -> kind = SKLength
@@ -168,12 +173,12 @@ let report_not_exhaustive v_lookup e_subject unmatched =
 	let sl = match follow e_subject.etype with
 		| TAbstract({a_impl = Some c} as a,tl) when a.a_enum ->
 			List.map (fun (con,_) -> match fst con with
-				| ConConst ct1 ->
+				| ConConst _ | ConEnum _ ->
 					let cf = List.find (fun cf ->
 						match cf.cf_expr with
 						| Some e ->
-							begin match extract_const e with
-							| Some ct2 -> ct1 = ct2
+							begin match extract_ctor e with
+							| Some ctor -> Constructor.equal (ctor,null_pos) con
 							| None -> false
 							end
 						| _ -> false

+ 21 - 0
tests/misc/projects/Issue11231/Main.hx

@@ -0,0 +1,21 @@
+enum Ordering {
+	EQ;
+	LT;
+	GT;
+  }
+
+@:publicFields
+enum abstract TriState(Ordering) from Ordering {
+	var True = GT;
+	var False = LT;
+	var Both = EQ;
+
+	function icon():Int {
+		return switch (this : TriState) {
+			case True:1;
+			case Both:3;
+		}
+	}
+}
+
+function main() {}

+ 22 - 0
tests/misc/projects/Issue11231/Main2.hx

@@ -0,0 +1,22 @@
+enum Ordering {
+	EQ;
+	LT;
+	GT;
+  }
+
+@:publicFields
+enum abstract TriState(Ordering) from Ordering {
+	var True = GT;
+	var False = LT;
+	var EvenFalser = LT;
+	var Both = EQ;
+
+	function icon():Int {
+		return switch (this : TriState) {
+			case True:1;
+			case Both:3;
+		}
+	}
+}
+
+function main() {}

+ 1 - 0
tests/misc/projects/Issue11231/compile-fail.hxml

@@ -0,0 +1 @@
+Main

+ 1 - 0
tests/misc/projects/Issue11231/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+Main.hx:14: characters 17-34 : Unmatched patterns: False

+ 1 - 0
tests/misc/projects/Issue11231/compile2-fail.hxml

@@ -0,0 +1 @@
+Main2

+ 1 - 0
tests/misc/projects/Issue11231/compile2-fail.hxml.stderr

@@ -0,0 +1 @@
+Main2.hx:15: characters 17-34 : Unmatched patterns: False

+ 30 - 0
tests/unit/src/unit/issues/Issue11213.hx

@@ -0,0 +1,30 @@
+package unit.issues;
+
+import utest.Assert;
+
+private enum Ordering {
+	EQ;
+	LT;
+	GT;
+}
+
+@:publicFields
+private enum abstract TriState(Ordering) from Ordering {
+	var True = GT;
+	var False = LT;
+	var Both = EQ;
+
+	function icon():Int {
+		return switch (this : TriState) {
+			case True: 1;
+			case False: 2;
+			case Both: 3;
+		}
+	}
+}
+
+class Issue11213 extends unit.Test {
+	function test() {
+		Assert.pass();
+	}
+}