Browse Source

extension should not shadow single pattern match for abstracted enum (#9596)

Dmitrii Maganov 5 years ago
parent
commit
589001ae02
3 changed files with 15 additions and 10 deletions
  1. 0 6
      src/core/abstract.ml
  2. 6 4
      src/typing/typer.ml
  3. 9 0
      tests/unit/src/unit/issues/Issue9577.hx

+ 0 - 6
src/core/abstract.ml

@@ -111,9 +111,3 @@ let rec follow_with_abstracts_without_null t = match follow_without_null t with
 		follow_with_abstracts_without_null (get_underlying_type a tl)
 	| t ->
 		t
-
-let rec follow_with_abstracts_forward t = match follow t with
-	| TAbstract(a,tl) when (Meta.has Meta.Forward a.a_meta) && not (Meta.has Meta.CoreType a.a_meta) ->
-		follow_with_abstracts_forward (get_underlying_type ~return_first:true a tl)
-	| t ->
-		t

+ 6 - 4
src/typing/typer.ml

@@ -2446,13 +2446,15 @@ and type_call ?(mode=MGet) ctx e el (with_type:WithType.t) inline p =
 		e
 	| (EField(e,"match"),p), [epat] ->
 		let et = type_expr ctx e WithType.value in
-		let is_enum_match = match follow et.etype with
+		let rec has_enum_match t = match follow t with
 			| TEnum _ -> true
-			| TAbstract _ as t when (match Abstract.follow_with_abstracts_forward t with TEnum _ -> true | _ -> false) ->
-				(try ignore (type_field (TypeFieldConfig.create true) ctx et "match" p mode); false with _ -> true)
+			| TAbstract (a,tl) when (Meta.has Meta.Forward a.a_meta) && not (Meta.has Meta.CoreType a.a_meta) ->
+				(match a.a_impl with
+					| Some c when (PMap.exists "match" c.cl_statics) && (Meta.has Meta.Impl (PMap.find "match" c.cl_statics).cf_meta) -> false
+					| _ -> has_enum_match (Abstract.get_underlying_type ~return_first:true a tl))
 			| _ -> false
 		in
-		if is_enum_match then
+		if has_enum_match et.etype then
 			Matcher.Match.match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p),p] (Some (Some (EConst(Ident "false"),p),p)) (WithType.with_type ctx.t.tbool) true p
 		else
 			def ()

+ 9 - 0
tests/unit/src/unit/issues/Issue9577.hx

@@ -6,8 +6,14 @@ class Issue9577 extends Test {
   function test() {
     var foo: Foo = Some(9577);
     var bar: Bar = Some(9577);
+    var baz: Baz = Some(9577);
     eq(true, foo.match(Some(9577)));
     eq(9578, bar.match(9577));
+    eq(false, baz.match(None));
+  }
+
+  public static function match(baz: Baz, value: Int) {
+    return value + 1;
   }
 }
 
@@ -18,3 +24,6 @@ class Issue9577 extends Test {
     return value + 1;
   }
 }
+
+@:using(unit.issues.Issue9577)
+@:forward private abstract Baz(Option<Int>) from Option<Int> {}