Skip to content

Commit

Permalink
[matcher] look through enum abstracts to find actual match kind
Browse files Browse the repository at this point in the history
  • Loading branch information
Simn committed May 9, 2023
1 parent ea57ab1 commit 4138953
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 16 deletions.
37 changes: 21 additions & 16 deletions src/typing/matcher/texprConverter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
21 changes: 21 additions & 0 deletions tests/misc/projects/Issue11231/Main.hx
Original file line number Diff line number Diff line change
@@ -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 changes: 22 additions & 0 deletions tests/misc/projects/Issue11231/Main2.hx
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions tests/misc/projects/Issue11231/compile-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11231/compile-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main.hx:14: characters 17-34 : Unmatched patterns: False
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11231/compile2-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main2
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11231/compile2-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main2.hx:15: characters 17-34 : Unmatched patterns: False
30 changes: 30 additions & 0 deletions tests/unit/src/unit/issues/Issue11213.hx
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit 4138953

Please sign in to comment.